Reference
Command behavior, addressing rules, workflow flags, and examples for day-to-day use.
Common Commands
etch mutates structured files and commits each successful mutating invocation.
Core structured edits
| Common forms | Class | Description |
|---|---|---|
| idempotent | Set JSON/YAML/frontmatter or Markdown inline fields. | |
| idempotent | Delete a file or selected JSON/YAML/frontmatter/inline-field value. | |
| non-idempotent | Append a value to an array, or a JSONL record to .jsonl/.ndjson. | |
| idempotent | Ensure an array contains a value. | |
| idempotent | Ensure an array does not contain a value. |
Markdown sections and lists
| Common forms | Class | Description |
|---|---|---|
| idempotent | Replace the body under one Markdown heading. | |
| non-idempotent | Append a block fragment under one Markdown heading. | |
| non-idempotent | Prepend a block fragment under one Markdown heading. | |
| idempotent | Ensure one Markdown task is closed. | |
| idempotent | Ensure one Markdown task is open, creating it when a destination is addressed. | |
| non-idempotent | Add one open Markdown task. | |
| non-idempotent | Add one Markdown list item. |
Tables
| Common forms | Class | Description |
|---|---|---|
| idempotent | Set CSV or Markdown table cells. | |
| non-idempotent | Append a CSV or Markdown table row. | |
| non-idempotent | Insert a CSV or Markdown table row. | |
| idempotent | Delete table rows. | |
| idempotent | Ensure a table column exists. | |
| idempotent | Rename a table column. | |
| idempotent | Ensure a table column is absent. |
Files
| Common forms | Class | Description |
|---|---|---|
| idempotent | Create a new file; omitted content uses an extension-aware default. | |
| idempotent | Replace an existing file's entire content. | |
| idempotent | Move a file path. | |
| idempotent | Copy a file path. |
Guards
| Common forms | Class | Description |
|---|---|---|
| guard | Guard that a path exists in the admitted input view. | |
| guard | Guard that a path is missing in the admitted input view. | |
| guard | Guard that admitted file bytes contain a literal. |
Agent setup
| Common forms | Class | Description |
|---|---|---|
| introspection | Print agent setup or durable context prompts. |
Model
Mutating invocations plan from HEAD and commit as one transaction.
Invocation
Global flags appear before the command path; CWD is the path and capability boundary.
Shapes
etch [flags] <command> [args...]
etch run [script]
etch --plan <command> [args...]
etch --dry-run <command> [args...]Examples
--untracked
Admit untracked source paths under the current working directory; touched paths become tracked if the command commits.
$ etch --untracked set scratch.json status openPrompts
etch prompt prints agent-facing Markdown. By default it prints a one-shot bootstrap prompt; --context prints durable instructions for future agent context.
Commands
etch prompt
etch prompt --bootstrap
etch prompt --contextScripts
etch run [script] executes a batch script as one transaction.
set posts/hello.md title "Hello, world"
append events.jsonl '{"kind":"prompt","name":"first"}'
set state.json payload --json '{"name":"first"}'section replace posts/hello.md "## Summary" <<EOF
$FOO is not expanded.
EOFExamples
run
Execute a batch of commands as one atomic commit. All-or-nothing — if any operation fails, no commit. Quote JSON as one token; no shell expansions.
$ etch run - <<'SCRIPT'
contains state.json open
set state.json status complete
SCRIPT| 1 | - | {"status":"open"} | |
| 1 | + | {"status":"complete"} |
Selectors
Selectors are singular JSONPath-style paths.
Accepted
$.agents.assistant.last_run
agents.assistant.last_run
$.items[0].title
$["key.with.dots"]Values
Structured values are strings by default. Use --json for a strict JSON value. For structured commands, --json may appear immediately before or after the value.
Examples
etch set state.json status complete # string "complete"
etch set state.json count --json 12 # number 12
etch set state.json count 12 --json # number 12
etch append state.json events --json '{"kind":"prompt"}'
etch append events.jsonl '{"kind":"prompt"}'
etch set state.json status=complete count:=12Examples
set
Set one or more structured values. Strings by default; use --json or := for typed values.
$ etch set state.json status=complete priority:=1| 1 | 1 | { | |
| 2 | - | "status": "open", | |
| 3 | - | "priority": 0, | |
| 2 | + | "status": "complete", | |
| 3 | + | "priority": 1, | |
| 4 | 4 | "labels": ["agent"] | |
| 5 | 5 | } |
delete
Delete a key from structured data, or delete an entire file.
$ etch delete config.yaml old_key| 1 | 1 | db_host: localhost | |
| 2 | - | old_key: unused | |
| 3 | 2 | timeout: 30 |
append
Append a value to an array. Not idempotent — always adds.
$ etch append log.json entries --json '{"event":"sync"}'| 1 | 1 | { | |
| 2 | 2 | "entries": [ | |
| 3 | - | {"event": "start"} | |
| 3 | + | {"event": "start"}, | |
| 4 | + | {"event":"sync"} | |
| 4 | 5 | ] | |
| 5 | 6 | } |
add
Ensure an array contains a value. No-op if already present.
$ etch add people/alice.md tags vip| 1 | 1 | --- | |
| 2 | 2 | name: Alice Chen | |
| 3 | - | tags: [partner, technical] | |
| 3 | + | tags: [partner, technical, vip] | |
| 4 | 4 | --- | |
| 5 | 5 | ||
| 6 | 6 | ## Notes | |
| 7 | 7 | ||
| 8 | 8 | Key decision-maker. |
remove
Ensure an array does not contain a value. No-op if absent.
$ etch remove config.json features dark-mode| 1 | 1 | { | |
| 2 | - | "features": ["dark-mode", "notifications"] | |
| 2 | + | "features": ["notifications"] | |
| 3 | 3 | } |
Formats
Porcelain commands infer formats from path extensions; plumbing commands make the format explicit.
Examples
append (jsonl)
Append one compact JSON record, preserving object member order. Missing files are created.
$ etch append events.jsonl '{"kind":"deploy","at":"2026-05-02T14:00:00Z"}'| 1 | 1 | {"kind":"heartbeat","at":"2026-05-02T13:00:00Z"} | |
| 2 | 2 | {"kind":"sync","at":"2026-05-02T13:30:00Z"} | |
| 3 | + | {"kind":"deploy","at":"2026-05-02T14:00:00Z"} |
Inline Fields
Markdown fields: use frontmatter for note-global metadata; use inline fields for body-local metadata.
Examples
etch set note.md status Driving
etch set note.md last "2026-05-02" --body
etch set note.md done "2026-05-01" --task "Send follow-up"Examples
set (inline)
Set Dataview-style inline fields in Markdown body text. Use --task or --section to target location.
$ etch set tasks/todo.md done "2026-05-02" --task "Send follow-up"| 1 | 1 | ## Actions | |
| 2 | 2 | ||
| 3 | - | - [ ] Send follow-up | |
| 3 | + | - [ ] Send follow-up [done:: 2026-05-02] | |
| 4 | 4 | - [ ] Review draft |
Markdown Addressing
Markdown addressing uses exact matching with syntax normalization and ambiguity errors.
Forms
etch set <path.md> <field> <value> <address>
etch delete <path.md> <field> <address>
etch task close <path> <text> [<address>]
etch task open <path> <text> [<address>]
etch list add <path> <text> [--task] [<placement>]
etch task add <path> <text> [<placement>]Inline Field Address
| Form | Meaning |
|---|---|
--body | Address inline fields in the whole Markdown body. |
--section <heading> | Limit the address to one heading section. |
--item <text> | Address an inline field on one matching list item. |
--task <text> | Address an inline field on one matching task item. |
--item-type <type> | Filter --item or --task matches by task, plain, numbered, or bullet. Repeat to combine independent filters. |
--head | Place a created inline field at the start of the addressed scope. |
--tail | Place a created inline field at the end of the addressed scope. |
--before <literal> | Place or narrow before a matching literal inside the addressed scope. |
--after <literal> | Place or narrow after a matching literal inside the addressed scope. |
--hidden | Use hidden Dataview field syntax. Accepted by set only. |
Task/List Address
| Form | Meaning |
|---|---|
--section <heading> | Limit the task/list command to one heading section. |
--before <item> | For task close/open, narrow the search before a matching list item. For task/list add, place the new item before it. |
--after <item> | For task close/open, narrow the search after a matching list item. For task/list add, place the new item after it. |
--task | With list add, create a task item instead of a plain list item. |
Examples
section replace
Replace everything under a heading, preserving surrounding blank-line style.
$ etch section replace notes.md "## Summary" <<'EOF'
Project on track. Next: May 15.
EOF| 1 | 1 | ## Summary | |
| 2 | 2 | ||
| 3 | - | Old summary here. | |
| 3 | + | Project on track. Next: May 15. | |
| 4 | 4 | ||
| 5 | 5 | ## Details | |
| 6 | 6 | ||
| 7 | 7 | Some details. |
task close
Check off a task checkbox. Matches by text content.
$ etch task close tasks/sprint.md "Write tests"| 1 | 1 | ## In progress | |
| 2 | 2 | ||
| 3 | - | - [ ] Write tests | |
| 3 | + | - [x] Write tests | |
| 4 | 4 | - [ ] Review PR |
set (inline)
Set Dataview-style inline fields in Markdown body text. Use --task or --section to target location.
$ etch set tasks/todo.md done "2026-05-02" --task "Send follow-up"| 1 | 1 | ## Actions | |
| 2 | 2 | ||
| 3 | - | - [ ] Send follow-up | |
| 3 | + | - [ ] Send follow-up [done:: 2026-05-02] | |
| 4 | 4 | - [ ] Review draft |
Files
File verbs create, replace, delete, move, and copy whole paths inside the transaction.
Commands
etch create <path> [<content>]
etch replace <path> <content>
etch delete <path>
etch move <src> <dst>
etch copy <src> <dst>Examples
create
Create a new file. Fails if the file already exists. JSON defaults to {}; other omitted content is empty.
$ etch create people/bob.mdreplace
Replace an existing file's entire content.
$ etch replace notes/status.txt "complete"| 1 | - | open | |
| 1 | + | complete |
move
Move (rename) a file path.
$ etch move people/bob.md people/robert.md| 1 | - | # Bob |
| 1 | + | # Bob |
copy
Copy a file path.
$ etch copy templates/default.md tasks/new-task.md| 1 | + | # New task | |
| 2 | + | ||
| 3 | + | - [ ] Triage |
Guards
Guards assert preconditions for a transaction without printing values or making content changes.
Commands
etch exists <path>
etch missing <path>
etch contains <path> <literal>Examples
exists
Assert that a path exists. Guards never commit. Use in scripts to gate mutations.
$ etch exists state.jsonmissing
Assert that a path does not exist.
$ etch missing state.jsoncontains
Assert that file bytes contain a literal string.
$ etch contains state.json openSections
Markdown sections are heading-delimited body ranges.
Commands
etch section replace note.md "## Status" "done"
etch section append note.md Status "new block"
etch section prepend note.md Status "new block"Examples
section replace
Replace everything under a heading, preserving surrounding blank-line style.
$ etch section replace notes.md "## Summary" <<'EOF'
Project on track. Next: May 15.
EOF| 1 | 1 | ## Summary | |
| 2 | 2 | ||
| 3 | - | Old summary here. | |
| 3 | + | Project on track. Next: May 15. | |
| 4 | 4 | ||
| 5 | 5 | ## Details | |
| 6 | 6 | ||
| 7 | 7 | Some details. |
section append
Append content at the end of a section, before the next heading.
$ etch section append journal.md "## Log" <<'EOF'
- 10:00 Standup
EOF| 1 | 1 | --- | |
| 2 | 2 | date: "2026-05-02" | |
| 3 | 3 | --- | |
| 4 | 4 | ||
| 5 | 5 | ## Log | |
| 6 | 6 | ||
| 7 | 7 | - 09:00 Morning review | |
| 8 | 8 | ||
| 9 | + | - 10:00 Standup | |
| 9 | 10 | ## Notes | |
| 10 | 11 | ||
| 11 | 12 | Remember to follow up. |
section prepend
Prepend content at the start of a section, right after the heading.
$ etch section prepend journal.md "## Log" <<'EOF'
- 08:00 Early check-in
EOF| 1 | 1 | ## Log | |
| 2 | + | - 08:00 Early check-in | |
| 2 | 3 | ||
| 3 | 4 | - 09:00 Morning review | |
| 4 | 5 | - 10:00 Standup |
Tasks and Lists
Markdown task/list commands operate on exact source-normalized item text.
Commands
etch task close note.md "Send follow-up" --section Actions
etch task open note.md "Send follow-up" --section Actions
etch list add note.md "Launch notes" --section Actions
etch task add note.md "Send follow-up" --section ActionsExamples
task close
Check off a task checkbox. Matches by text content.
$ etch task close tasks/sprint.md "Write tests"| 1 | 1 | ## In progress | |
| 2 | 2 | ||
| 3 | - | - [ ] Write tests | |
| 3 | + | - [x] Write tests | |
| 4 | 4 | - [ ] Review PR |
task open
Uncheck a task checkbox. Creates the task if a destination is addressed.
$ etch task open tasks/sprint.md "Review PR"| 1 | 1 | ## Done | |
| 2 | 2 | ||
| 3 | 3 | - [x] Write tests | |
| 4 | - | - [x] Review PR | |
| 4 | + | - [ ] Review PR |
task add
Add a new open task item to an addressed section.
$ etch task add tasks/sprint.md "Deploy staging" --section "## Remaining"| 1 | 1 | ## Remaining | |
| 2 | 2 | ||
| 3 | 3 | - [ ] Write docs | |
| 4 | + | - [ ] Deploy staging |
list add
Add a plain list item (no checkbox) to an addressed section.
$ etch list add notes.md "Follow up with Alice" --section "## Action items"| 1 | 1 | ## Action items | |
| 2 | 2 | ||
| 3 | 3 | - Send proposal | |
| 4 | + | - Follow up with Alice |
Tables and CSV
Tables are ordered rows and named columns of string cells.
CSV
etch table set data.csv all,status done
etch table row append data.csv '{"id":"1","status":"open"}'
etch table column add data.csv owner --default BrandonMarkdown
etch table set notes.md doc @0 all,status done
etch table row append notes.md "## Inventory" '{"sku":"A1"}'Examples
table set
Set one or more cells in a CSV or Markdown table while preserving Markdown table whitespace when possible.
$ etch table set notes.md "## Inventory" sku=A1,status done| 1 | 1 | ## Inventory | |
| 2 | 2 | ||
| 3 | 3 | | sku | status | | |
| 4 | 4 | | --- | --- | | |
| 5 | - | | A1 | open | | |
| 5 | + | | A1 | done | |
table row append
Append a row to a CSV or Markdown pipe table.
$ etch table row append data.csv '{"id":"4","status":"open","owner":"dave"}'| 1 | 1 | id,status,owner | |
| 2 | 2 | 1,done,alice | |
| 3 | 3 | 2,closed,bob | |
| 4 | + | 4,open,dave |
table row insert
Insert a row before or after one matching row in a CSV or Markdown table.
$ etch table row insert data.csv --after id=1 '{"id":"2","status":"open","owner":"bob"}'| 1 | 1 | id,status,owner | |
| 2 | 2 | 1,done,alice | |
| 3 | + | 2,open,bob | |
| 3 | 4 | 3,open,carol |
table row delete
Delete rows matching a condition.
$ etch table row delete data.csv status=closed| 1 | 1 | id,status,owner | |
| 2 | 2 | 1,open,alice | |
| 3 | - | 2,closed,bob | |
| 4 | 3 | 3,open,carol |
table column add
Ensure a column exists, using an optional default value when creating it.
$ etch table column add data.csv priority --default medium| 1 | - | id,status | |
| 2 | - | 1,open | |
| 3 | - | 2,closed | |
| 1 | + | id,status,priority | |
| 2 | + | 1,open,medium | |
| 3 | + | 2,closed,medium |
table column rename
Rename a column in a CSV or Markdown table.
$ etch table column rename data.csv owner assignee| 1 | - | id,status,owner | |
| 1 | + | id,status,assignee | |
| 2 | 2 | 1,open,alice | |
| 3 | 3 | 2,closed,bob |
table column delete
Ensure a column is absent from a CSV or Markdown table.
$ etch table column delete data.csv owner| 1 | - | id,status,owner | |
| 2 | - | 1,open,alice | |
| 3 | - | 2,closed,bob | |
| 1 | + | id,status | |
| 2 | + | 1,open | |
| 3 | + | 2,closed |
Plans
--plan emits canonical JSON describing operations, input/output hashes, planned tree, and commit message.
Examples
--plan
Print the canonical JSON transaction plan without creating a commit or changing files.
$ etch --plan set state.json status complete--dry-run
Print a git-am-compatible patch preview without creating a commit or changing files.
$ etch --dry-run set state.json status completeCommits
Every successful mutating invocation creates one local git commit unless all mutating operations are no-ops.
Examples
--message
Override the generated commit message for one mutating invocation.
$ etch --message 'mark state complete' set state.json status complete--subject-prefix/suffix
Add text before or after the generated commit subject.
$ etch --subject-prefix '[agent] ' set state.json status complete--body-prefix/suffix
Add a body block before or after the generated commit body.
$ etch --body-suffix 'Reviewed-by: agent' set state.json status completeSecurity
etch is designed as a narrow CWD-scoped, git-backed mutation capability.
Conflicts
When materialization cannot merge local checkout changes after the commit lands, etch leaves recovery text on stderr.
Examples
--no-checkout
Commit the transaction without materializing touched paths into the index and working tree.
$ etch --no-checkout set state.json status completeCommand Index
etch mutates structured files and commits each successful mutating invocation.
Core structured edits
| Command | Class | Description |
|---|---|---|
| idempotent | Set JSON/YAML/frontmatter or Markdown inline fields. | |
| idempotent | Delete a file or selected JSON/YAML/frontmatter/inline-field value. | |
| non-idempotent | Append a value to an array, or a JSONL record to .jsonl/.ndjson. | |
| idempotent | Ensure an array contains a value. | |
| idempotent | Ensure an array does not contain a value. |
Markdown sections and lists
| Command | Class | Description |
|---|---|---|
| idempotent | Replace the body under one Markdown heading. | |
| non-idempotent | Append a block fragment under one Markdown heading. | |
| non-idempotent | Prepend a block fragment under one Markdown heading. | |
| idempotent | Ensure one Markdown task is closed. | |
| idempotent | Ensure one Markdown task is open, creating it when a destination is addressed. | |
| non-idempotent | Add one open Markdown task. | |
| non-idempotent | Add one Markdown list item. |
Tables
| Command | Class | Description |
|---|---|---|
| idempotent | Set CSV or Markdown table cells. | |
| non-idempotent | Append a CSV or Markdown table row. | |
| non-idempotent | Insert a CSV or Markdown table row. | |
| idempotent | Delete table rows. | |
| idempotent | Ensure a table column exists. | |
| idempotent | Rename a table column. | |
| idempotent | Ensure a table column is absent. |
Files
| Command | Class | Description |
|---|---|---|
| idempotent | Create a new file; omitted content uses an extension-aware default. | |
| idempotent | Replace an existing file's entire content. | |
| idempotent | Move a file path. | |
| idempotent | Copy a file path. |
Guards
| Command | Class | Description |
|---|---|---|
| guard | Guard that a path exists in the admitted input view. | |
| guard | Guard that a path is missing in the admitted input view. | |
| guard | Guard that admitted file bytes contain a literal. |
Agent setup
| Command | Class | Description |
|---|---|---|
| introspection | Print agent setup or durable context prompts. |
Advanced structured formats
| Command | Class | Description |
|---|---|---|
| idempotent | Set JSON values. | |
| idempotent | Delete a JSON value. | |
| non-idempotent | Append to a JSON array. | |
| idempotent | Ensure a JSON array contains a value. | |
| idempotent | Remove matching values from a JSON array. | |
| idempotent | Set YAML values. | |
| idempotent | Delete a YAML value. | |
| non-idempotent | Append to a YAML sequence. | |
| idempotent | Ensure a YAML sequence contains a value. | |
| idempotent | Remove matching values from a YAML sequence. | |
| idempotent | Set Markdown YAML frontmatter. | |
| idempotent | Delete Markdown YAML frontmatter. | |
| non-idempotent | Append to a frontmatter sequence. | |
| idempotent | Ensure a frontmatter sequence contains a value. | |
| idempotent | Remove matching values from a frontmatter sequence. |
Advanced logs and Markdown
| Command | Class | Description |
|---|---|---|
| non-idempotent | Append one compact JSON value as a JSONL/NDJSON record. | |
| idempotent | Replace the body under one Markdown heading. | |
| non-idempotent | Append a block fragment under one Markdown heading. | |
| non-idempotent | Prepend a block fragment under one Markdown heading. |
Advanced table formats
| Command | Class | Description |
|---|---|---|
| idempotent | Set CSV cells. | |
| non-idempotent | Append a CSV row. | |
| non-idempotent | Insert a CSV row. | |
| idempotent | Delete CSV rows. | |
| idempotent | Ensure a CSV column exists. | |
| idempotent | Rename a CSV column. | |
| idempotent | Ensure a CSV column is absent. | |
| idempotent | Set Markdown table cells. | |
| non-idempotent | Append a Markdown table row. | |
| non-idempotent | Insert a Markdown table row. | |
| idempotent | Delete Markdown table rows. | |
| idempotent | Ensure a Markdown table column exists. | |
| idempotent | Rename a Markdown table column. | |
| idempotent | Ensure a Markdown table column is absent. |