CLI Reference β
@semanticintent/rune-cli provides two commands for working with Rune binding manifests.
npm install -g @semanticintent/rune-cliWorkflow β
The typical workflow is a round-trip: extract a manifest from existing source, then validate to see what's missing, then enrich until the manifest is a complete contract.
rune extract src/ # scan source β generate rune.json
rune validate rune.json # find missing types and intent annotations
# enrich rune.json with type, intent, min/max/enum
rune validate rune.json # clean β manifest is now a cross-layer contractrune validate β
Validates a .rune.json binding manifest against the Rune schema.
rune validate <manifest>
rune validate my-app.rune.json
rune validate my-app.rune.json --format jsonOptions:
| Option | Default | Description |
|---|---|---|
--format text|json | text | Output format. json is CI/editor friendly |
Exit codes: 0 = valid (warnings may exist), 1 = one or more errors.
Text output:
β my-app.rune.json β valid
3 warnings
[RNE006] tasks binding 'tasks' has no intent annotation
Bindings without ? intent travel without rationale. Consider adding one.JSON output:
{
"manifest": "my-app.rune.json",
"valid": true,
"errorCount": 0,
"warningCount": 3,
"diagnostics": [
{
"code": "RNE006",
"severity": "warning",
"binding": "tasks",
"message": "binding 'tasks' has no intent annotation",
"hint": "Bindings without ? intent travel without rationale."
}
]
}CI integration:
# GitHub Actions
- name: Validate Rune manifest
run: rune validate rune.json --format jsonrune extract β
Scans source files for Rune binding patterns and generates a .rune.json manifest. Zero-friction onboarding for existing Rune-annotated codebases.
rune extract <source>
rune extract src/app.tsx # single file
rune extract src/ # scan directory recursively
rune extract src/ --host html # force host format
rune extract src/ --out my-app.rune.json # custom output pathOptions:
| Option | Default | Description |
|---|---|---|
--host auto|html|ts|csharp|sql | auto | Host format. auto detects from file extension |
--out <file> | rune.json | Output manifest path |
Output:
β extracted 7 bindings from 3 files
@ read: 2 ~ sync: 2 ! act: 2 ? intent: 1
β rune.json
Run 'rune validate rune.json' to find missing types and intent annotations.Supported host formats β
| Format | Extensions | Patterns detected |
|---|---|---|
html | .html, .mp | @id, ~id, !id as attribute names; ?"annotation" |
ts | .ts, .tsx, .js, .jsx | useRead(), useSync(), useAct(), useIntent() |
csharp | .cs | [RuneState], [RuneComputed], [RuneAction], [RuneIntent("...")] |
sql | .sql | COMMENT ON ... IS 'rune:@ ...' annotation convention |
Host format details β
<!-- Detected as attribute names and sigil-prefixed values -->
<field ~new-task placeholder="New taskβ¦"/>
<button !add-task>Add</button>
<list @tasks><item @item.title /></list>
<screen ?"mobile task list, focus on speed">// Detected from hook calls in the reference implementation
const tasks = useRead('tasks') // β @ tasks
const [v, set] = useSync('new-task') // β ~ new-task
const act = useAct('add-task') // β ! add-task
useIntent('screen', 'mobile task list') // β ? screen, with annotation
// host.* patterns also detected
host.read('tasks')
host.sync('new-task', value)
host.act('add-task', handler)
host.recordIntent('screen', 'annotation')// Attributes map to rune types, PascalCase β kebab-case
[RuneState]
public string NewTask { get; set; } // β ~ new-task
[RuneComputed]
public IEnumerable<Task> Tasks { get; } // β @ tasks
[RuneAction]
public void AddTask(string title) { } // β ! add-task
// Stacked attributes are handled β intent travels with the binding
[RuneState]
[RuneIntent("approved by risk committee")]
public decimal RiskThreshold { get; set; } // β ~ risk-threshold + intent-- Use COMMENT ON with 'rune:sigil intent' annotation
COMMENT ON COLUMN tasks.task_title IS 'rune:~ user-entered β cleared after add_task';
COMMENT ON COLUMN tasks.task_id IS 'rune:@ system-assigned β do not mutate';
COMMENT ON FUNCTION add_task IS 'rune:! no-op if title is empty';
COMMENT ON TABLE tasks IS 'rune:? personal task tracking';Extract output β
The manifest generated by rune extract is a valid starting point β types and intent annotations are absent until you add them. rune validate tells you exactly what's missing:
rune extract src/ && rune validate rune.json
# β valid, 10 warnings (missing types and intent annotations)Enrich the manifest, re-validate, and the warnings disappear. The manifest is now a full cross-layer contract.
Diagnostic codes β
| Code | Severity | Description |
|---|---|---|
RNE001 | error | Invalid rune type β must be @ ~ ! ? |
RNE002 | error | Unknown binding β used but not declared in manifest |
RNE003 | error | Wrong rune type for binding kind (e.g. args on @) |
RNE004 | error | Missing required field (e.g. intent on ? binding) |
RNE005 | error | Constraint violation β min/max on non-number, enum on non-string, min > max |
RNE006 | warning | Missing intent annotation or type declaration |
RNE007 | error | Manifest does not conform to rune.schema.json structurally |
RNE002 and RNE003 are also raised by the LSP in real time as you type.