Coders CLI
Coders is a transpiler that generates native code for multiple platforms from a single DSL (.jssp). It uses platform prompts to map declared resources (such as controller, mapper, message, error) into 1:1 target outputs, so the same DSL can expand across languages and frameworks.
For setup, see Quick Start and What is Coders?.
Configuration notes
config.yml controls the CLI end to end.
entry: root.jsspfile to parse by default.projects: each item definesplatform,name,outPath,entry,target,language, andoptions. Inoptionsyou can set fields such aspackage,namespace,module,mainClass,languageVersion,version,group,description,plugins,dependencies,onlySource,extra, anduseHistoryto suit the platform needs.llmOptions: configure provider (provider), model (model), endpoint (url), auth (apiKey), timeout (timeoutSeconds), and streaming (stream). Add any extra fields required by your provider in the same block.
Coders DSL Overview
Coders DSL is composed of:
- declarations:
domain,table,entity,mapper,struct,class,controller,api,define - execution:
func,main,@prompt - resources:
message,error,property,css - UI:
html+<template>
Each declaration is converted into platform-specific files by the prompts. Core syntax is covered in the Syntax page.
Data Modeling
Domain
domain Url string(512);
domain Name string(32);Table
table user {
user_id int64 auto;
name Name;
create_at datetime = now();
key(user_id);
index(create_at);
unique index(name);
}Data
data user(name) {
('user1');
('user2');
}Entity
entity UserVo from @table.user {}
entity UserProfileVo {
var userId int64;
var name Name;
var avatarUrl Url;
}Mapper
mapper UserMapper {
query insertUser(name Name) int32 {
insert user(name)
values(:name);
}
query updateUser(userId int64, name Name) int32 {
update user set name = :name
where user_id = :userId;
}
}DB Procedure / Function
dbproc sample(userId string(10), out name string(100)) {
var _name string(100);
var c cursor = select name into _name from user_id = userId;
c.open();
c.fetch();
name = _name;
c.close();
}
dbfunc countUser() int32 {
var _count int32;
select count(*) into _count from user;
return _count;
}Application Structure
Struct / Class / Interface
struct SignupRequest {
var email string;
var password string;
}
abstract class BaseSample {
func hello() void;
}
class Sample extends BaseSample {
var name string;
constructor(name string) {
this.name = name;
}
func hello() void {
@console.log("hello");
}
}[alias='console']
interface Console {
static func log(message string) void;
static func error(message string) void;
static func warn(message string) void;
}Enum
define enum Status {
READY 1,
RUNNING 2,
DONE 3
}API and Services
Controller
[baseUrl='/api/v1', comment='User controller']
controller UserController {
[method=post, route='/signup']
func signup(@body req SignupRequest) SignupResponse {
var res = SignupResponse();
var n = @mapper.UserMapper.insertUser(req.email, req.password);
if (n <= 0) {
res.code = AppErrors.failed.code;
res.message = AppErrors.failed.message;
return res;
}
res.code = AppErrors.success.code;
return res;
}
}Api (Client)
[comment='User API']
api UserApi from @controller.UserController {}Frontend targets (React/Vue/Svelte) and Flutter widgets
The Coders DSL html class is converted into frontend components. The same DSL maps to React, Vue, or Svelte components depending on the platform. Flutter uses the widget class, which is generated as widgets.
Common concepts
ref var-> component state@model-> input binding@click-> event handlerdefine css-> style tokens@api-> controller-based API calls
Example: login screen DSL
define css {
text.primary {
text-gray-800
}
}
html LoginPage {
ref var nickname string = "";
ref var password string = "";
func login() {
var res = @api.login(nickname, password);
@console.log(res.code);
}
// Define UI in the template block.
}React mapping concepts
ref var->useState@model->value+onChange@click->onClickdefine css-> class/style token mapping
Vue/Svelte mapping concepts
ref var-> reactive state@model-> v-model or bind:value@click-> @click/on:click
Flutter widgets
Flutter uses the widget class instead of html.
widget LoginPage {
ref var nickname string = "";
ref var password string = "";
func login() {
var res = @api.login(nickname, password);
@console.log(res.code);
}
// Define UI in the widget layout block.
}Flutter mapping concepts
ref var-> State + setState@model-> TextEditingController/OnChanged@click-> onPressed
The output structure varies by platform, but html/widget declarations are always converted into components/widgets.
Resource Definitions
Property
define property app {
baseUrl = "https://api.example.com";
}
define property [profile='dev'] app {
baseUrl = "https://dev.api.example.com";
}Message + Message Class
define message[locale='en'] app {
hello: "Hello"
welcome: "Welcome {name}"
}
message MessageApp from @message.app {
static func setLocale(locale string) void;
static var hello string;
static func welcome(name string) string;
}Error + Error Class
define error[locale='en'] app {
not_found (100) = "Resource not found"
server_error (200) = "Internal server error"
}
error AppErrors from @error.app {}CSS + HTML
define css {
text.primary {
text-gray-800 dark:text-gray-100
}
}
html LoginPage {
ref var nickname string = "";
ref var password string = "";
func login() {
var res = @api.login(nickname, password);
@console.log(res.code);
}
template {
div class="@css.text.primary" {
input @model="nickname";
input @model="password";
button @click="login" { "Login" }
}
}
}@prompt Directives
@prompt is a hint for native code patterns that do not exist in the DSL. The LLM translates the instruction into platform-specific code.
func main() {
@prompt `"Hello, World!" output`
}@prompt Conversion Example (Rust/Go/Java)
func main(args list<string>) {
@prompt `Implement the Sieve of Eratosthenes to print primes up to args[0]`
}use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
let n: usize = args.get(1).unwrap_or(&"0".to_string()).parse().unwrap_or(0);
if n < 2 {
return;
}
let mut is_prime = vec![true; n + 1];
is_prime[0] = false;
if n >= 1 {
is_prime[1] = false;
}
let mut p = 2;
while p * p <= n {
if is_prime[p] {
let mut multiple = p * p;
while multiple <= n {
is_prime[multiple] = false;
multiple += p;
}
}
p += 1;
}
for i in 2..=n {
if is_prime[i] {
println!("{i}");
}
}
}package main
import (
"fmt"
"os"
"strconv"
)
func main() {
n := 0
if len(os.Args) > 1 {
if v, err := strconv.Atoi(os.Args[1]); err == nil {
n = v
}
}
if n < 2 {
return
}
isPrime := make([]bool, n+1)
for i := range isPrime {
isPrime[i] = true
}
isPrime[0] = false
if n >= 1 {
isPrime[1] = false
}
for p := 2; p*p <= n; p++ {
if isPrime[p] {
for m := p * p; m <= n; m += p {
isPrime[m] = false
}
}
}
for i := 2; i <= n; i++ {
if isPrime[i] {
fmt.Println(i)
}
}
}public class Main {
public static void main(String[] args) {
int n = 0;
if (args.length > 0) {
try {
n = Integer.parseInt(args[0]);
} catch (NumberFormatException ignored) {
n = 0;
}
}
if (n < 2) {
return;
}
boolean[] isPrime = new boolean[n + 1];
for (int i = 0; i <= n; i++) {
isPrime[i] = true;
}
isPrime[0] = false;
if (n >= 1) {
isPrime[1] = false;
}
for (int p = 2; p * p <= n; p++) {
if (isPrime[p]) {
for (int m = p * p; m <= n; m += p) {
isPrime[m] = false;
}
}
}
for (int i = 2; i <= n; i++) {
if (isPrime[i]) {
System.out.println(i);
}
}
}
}Bash/PowerShell prompts
The shell keyword is converted into script functions. The Bash/PowerShell platforms include a runner (main or invocation code) so the shell functions actually execute.
Bash conversion rules
- Include
set -euo pipefailat the top of the script. shellfunctions are converted into Bash functions.- For
shell identifier(),lower_snake_caseis recommended.
shell download_file(url string, dest string) {
@prompt `Download a file with curl`
}set -euo pipefail
download_file() {
local url="$1"
local dest="$2"
curl -fsSL "$url" -o "$dest"
}
main() {
download_file "$@"
}
main "$@"PowerShell conversion rules
shellfunctions are converted into PowerShellfunction.- For
shell identifier(), Verb-Noun PascalCase is recommended. - Include
mainor direct invocation code for execution.
shell download_file(url string, dest string) {
@prompt `Download a file with Invoke-WebRequest`
}function Download-File {
param (
[Parameter(Mandatory = $true)]
[string]$Url,
[Parameter(Mandatory = $true)]
[string]$Dest
)
Invoke-WebRequest -Uri $Url -OutFile $Dest
}
Download-File -Url $Url -Dest $DestConversion Overview
Coders splits DSL declarations into resource units, then renders files using platform templates.
- Analyze declarations (controller, mapper, html/widget)
- Generate resource-level code skeletons
- Expand @prompt instructions into native code
End-to-End Example
domain Email string(320);
domain Password string(128);
struct SignupRequest {
var email Email;
var password Password;
}
struct SignupResponse {
var code int32;
var message string;
}
table user {
user_id int64 auto;
email Email unique;
password Password;
key(user_id);
}
mapper UserMapper {
query insertUser(email Email, password Password) int32 {
insert user(email, password)
values (:email, :password);
}
}
define error[locale='en'] app {
success (0) = "OK"
failed (100) = "Failed"
}
error AppErrors from @error.app {}
[baseUrl='/api/v1']
controller UserController {
[method=post, route='/signup']
func signup(@body req SignupRequest) SignupResponse {
var res = SignupResponse();
var n = @mapper.UserMapper.insertUser(req.email, req.password);
if (n <= 0) {
res.code = AppErrors.failed.code;
res.message = AppErrors.failed.message;
return res;
}
res.code = AppErrors.success.code;
res.message = AppErrors.success.message;
return res;
}
}