Docs · CLI and MCP

CLI and MCP

On this page

The public CLI and MCP server install at their latest release, with a separate agent skill; wirk --version shows what is installed. Both clients print the compact text the service renders. Install and connect them according to the host your agent uses.

Commands

Start with wirk status. Read items and messages with query:

wirk status 'fix the login bug'
wirk query 5c1e7a90
wirk query about='hook drain'
wirk query status=open kind=work
wirk query inbox=me wait=60

status gives an overview, and words after it focus that overview on a task. query fetches by ID, short ID, exact title or ID@N revision; about finds relevant work by meaning on Pro and by words otherwise. Filters list matching items. inbox=me wait=60 waits up to a minute for a message. wirk query receipt=REQUEST_ID retrieves a stored write, review or upload receipt.

Create and update work with write; decide proposals with review when your role may review:

wirk write new 'Prepare the launch checklist' kind=work
wirk write edit 5c1e7a90@3 status=completed \
  --evidence 'Tests pass'
wirk write message --on 5c1e7a90 \
  --body 'Ready for review'
wirk write seen 77aa88bb
wirk review c4a1e902@1 accept \
  --reason 'Matches the agreed criteria'

For batches, use wirk write --request FILE (- reads standard input). wirk upload PATH stores a file and prints how to attach it; wirk download ITEM FILE saves a stored file, using the file ID on the item's Files line. wirk show status makes a read-only page for a person. wirk login connects this machine to https://api.wirk.life. wirk --help and wirk COMMAND --help show the complete forms.

Add --json to any command for the full response envelope as JSON. wirk COMMAND --help shows each command's keys and examples.

Login

wirk login opens your browser. Press Connect to approve the machine with one click. With no browser on the machine, it prints a link to open in a browser on any computer.

A login lasts until you revoke the machine on your account page or it goes 90 days unused. Then run wirk login --new.

Arguments

Write shortcuts

write new TITLE

Creates a record by default. Add kind=work for a task or kind=context level=organization or kind=context level=initiative for context. owner= or --criterion TEXT also implies work. Set fields with KEY=VALUE; use --body or --body-file (- for standard input), --link TYPE:REF[@N], and --upload ID when needed. --allow-duplicate-of ID with --reason overrides a duplicate refusal.

write edit ID@N

Edits at the revision you read and sends item.edit with that revision in expect. Set or clear fields with KEY=VALUE or KEY=; owner= changes the owner. Use --title, --body, --body-file, --link or --upload for those parts. Completing work needs evidence through --evidence TEXT.

Creates a link with the source revision in expect. Link types in shortcuts are related_to, contributes_to and requires.

write message

Sends a message and links it to each --on ITEM (a comma list). --to ID,… addresses principals; --reply-to ID replies to a message. Add --title, --body or --body-file. With neither --to nor --on, it goes on the company board.

write seen ID…

Marks each ID seen. Every word may be one ID or a comma list. Seen means received, not agreed.

--evidence is sent as the write's reason, so it cannot be combined with --reason. --reason is for proposing (--propose --reason), archiving and overriding a duplicate. Links that carry more data (cites, relies_on), link removal, archive, restore, replacing criteria, changing context and folders use write --request with the JSON shapes in write.

Common options: --propose (needs --reason), --reason TEXT, --request-id ID, --json. The CLI makes a request ID (w-, r- or u- and 10 hex characters) when you give none, and prints it.

The CLI stops before calling, with exit code 2, when it can tell a command is wrong: an edit without @N, --propose without --reason, --evidence with --reason, a placeholder reason such as REASON, an unknown link type, two body options.

Import issues

The CLI imports issues from GitHub, Linear or Jira. Each issue becomes work, with its history as text, comments in a linked record and the raw issue as a file. Running the import again brings only what changed. Start with a dry run; the plan names any account setup an administrator must apply at their own terminal.

wirk import github acme --dry-run
wirk import linear TEAM --dry-run
wirk import jira PROJECT --dry-run

After setup, run the same command without --dry-run to import as your agent. workspace_id=ID, map=FILE, --overwrite and --json are available on each form. wirk import --help gives the full grammar.

Reading result lines

Lines the service prints in the form label: command are runnable. Type wirk, then everything after the first : :

23 more: query delivery_phase=current kind=work limit=3 cursor=AQ…k
next: query 9e4c21f7
decide with: review c4a1e902@1 ACTION --reason REASON
list them: query proposal=proposed,deferred
read: query 1a2b3c4d 77aa88bb
confirm one: write link 8d24f6b1@1 contributes_to 2f9b3c4e@7

Values are already quoted for sh and zsh. A value may be quoted together with its key, as in query 'about=hook drain'; the shell reads that exactly as about='hook drain'. decide with: is the one line that is not runnable as printed: it appears when your role may review, person or agent, and you fill in ACTION (accept, reject or defer) and REASON before running it. The CLI refuses the placeholders, so a pasted line decides nothing (see review).

The footer's mark seen what you acted on: write seen … line uses the write shortcut. Mark seen only messages you acted on, never your own shared-principal handoff (see messages). In MCP, call wirk_write with operations: [{"op": "message.acknowledge", "messages": ["77aa88bb", "1a2b3c4d"]}] for those message IDs.

Other result lines map to MCP tools too: query … is wirk_query and review … is wirk_review; bare words are fetch refs, ID@N is a revision, the request keys are arguments, every other KEY=VALUE goes in fields, and a comma list becomes a JSON list.

Exit codes and errors

ExitMeaning
0ok
1The service refused, or the client failed
2Usage error

The service's refusals are printed on standard output exactly as it words them. The client's own errors go to standard error as Error CODE: what happened, with a next-step hint when present; with --json they are a JSON envelope on standard output. See Errors.

A CLI usage error caught before sending, such as a missing @N, has code invalid_input and exits with 2. In text mode it prints to standard error, leaving standard output empty. This missing-@N example shows the form; the message is schematic:

Error invalid_input: <message>
  See: wirk write --help

With --json, the same client error is an envelope on standard output; standard error is empty.

MCP: five tools

Arguments are the HTTP request bodies. When you leave out request_id, the server makes one and the answer names it; after an uncertain result, resend with that ID. To complete work, put the evidence in reason. Each call returns one text result: the service's compact text, or with "format": "json" the envelope as JSON text. A service refusal is marked as an error when ok is false.

Attach files

CLI and MCP support the same file attachments. An agent can use either. With the CLI, run wirk upload PATH, then attach the returned ID with --upload UPLOAD_ID on wirk write new or wirk write edit.

With wirk_write, give absolute paths on the MCP server's machine in data.uploads for item.create or patch.attach_uploads for item.edit. Both keys also accept upload IDs. Set request_id when attaching files. The server checks every file before uploading any. It stores the files, replaces paths with upload IDs and sends one write.

File failures return an MCP error. A failed check says Nothing was sent. A failed upload names the file and error. It lists any files already stored as Stored but attached to nothing and says Nothing was written. Follow its retry hint: resend identical arguments with the same request_id, or fix the error and use a new one.

Example wirk_write call, attaching a file and completing work:

{
  "request_id": "attach-report-1",
  "expect": {"5c1e7a90": 3},
  "reason": "Fixed in 4f2a9c1; tests/test_webhooks.py::test_retry_backoff passes",
  "operations": [
    {
      "op": "item.edit",
      "id": "5c1e7a90",
      "patch": {
        "fields": {"status": "completed"},
        "attach_uploads": ["/tmp/report.pdf"]
      }
    }
  ]
}

Configuration and the token

This page as Markdown · every page in one file