The longclaw command
The same crate the app uses ships as a command-line binary — key allocation, the write seams, and the file format have exactly one implementation. This is how an agent files and updates work.
Build it
The binary is built from the same workspace as the app:
cargo build --release \
--manifest-path apps/desktop/src-tauri/Cargo.toml --bin longclaw
Run longclaw with no arguments for the full surface.
A project, start to finish
Create the project record — longclaw.yaml — and choose the key every ticket ID starts with.
longclaw project init --name "My Project" --key MP
{
"ok": true,
"project": { "name": "My Project", "key": "MP", "path": ".longclaw/" }
}Define a label before anything uses it.
longclaw label add --slug storage --name Storage
{
"ok": true,
"label": { "slug": "storage", "name": "Storage" }
}File a ticket as an agent. The CLI allocates the key and records exactly who created it.
longclaw ticket create --title "Fix the retry policy" --label storage \ --checklist "Reproduce it" --agent-id claude-code --agent-name "Claude Code"
{
"ok": true,
"ticket": {
"key": "MP-1",
"status": "todo",
"actor": { "kind": "agent", "id": "claude-code", "name": "Claude Code" }
}
}Move it. The status change lands in the ticket's activity, attributed to the agent.
longclaw ticket edit MP-1 --status in_progress --agent-id claude-code
{
"ok": true,
"ticket": { "key": "MP-1", "status": "in_progress" },
"event": "status_changed"
}Read the backlog the way the app sees it.
longclaw ticket list
{
"ok": true,
"count": 1,
"tickets": [
{ "key": "MP-1", "title": "Fix the retry policy", "status": "in_progress" }
]
}The rules
JSON on stdout
Every command prints JSON and exits non-zero with a typed error on failure.
Labels are defined before use
The CLI refuses a slug the project does not define, so a label cannot be created by using it.
Agents pass —agent-id
The file format declares an actor and never infers one; without it, the activity entry claims a human did the work. The CLI is the creation surface agents use: it allocates the ticket key, so an agent never invents one.
When two branches mint the same key
Keys are allocated from the ticket directories in one working tree, so a second branch, worktree or clone reads a lower maximum and can mint the same number again. The random trailing letter usually makes the two differ anyway; when it does not, re-key one side rather than resolving the conflict by taking one:
Re-key one of a collided pair. --id names which one, because the pair shares its key and its path and differs only in id — read it from the file's frontmatter.
longclaw ticket renumber LC-230 --id <uuid> --agent-id claude-code
It moves the directory, rewrites the key field, records the old key in the
activity, and then prints every path in the repository that still names it —
those are yours to follow, because they are not files LongClaw owns.
Why the CLI, and not the app
Agents create tickets through the CLI rather than through the window so that key allocation stays in a single implementation. Two surfaces allocating keys is two chances to allocate the same one.
That decision is recorded as ADR 0011.
This repository tracks its own work this way. Every LC-* item under
.longclaw/tickets/ was filed through this CLI, and the agent-authored entries
in those files were written by agents reading the same contract yours will.