CLI

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
stdout
{
"ok": true,
"project": { "name": "My Project", "key": "MP", "path": ".longclaw/" }
}

Define a label before anything uses it.

longclaw label add --slug storage --name Storage
stdout
{
"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"
stdout
{
"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
stdout
{
"ok": true,
"ticket": { "key": "MP-1", "status": "in_progress" },
"event": "status_changed"
}

Read the backlog the way the app sees it.

longclaw ticket list
stdout
{
"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.