Skip to content

CLI reference

Every command and flag of the wrktr CLI, as wrktr <command> --help describes them.

Every command takes these, before or after the subcommand.

Flag
--project <org>/<name> Act on that project on wrktr instead of the clone you’re in. No clone is needed, so name the branch too (--branch, or the command’s branch argument). Commands that act on this machine or your account (login, whoami, token, init, clone, branch new, branch rm, branch ls without --all, skill, daemon) refuse it.
--json Print the result as JSON on stdout, and a failure as JSON on stderr. See JSON output.
--help, -h Help for any command.
--version, -v The CLI’s version and build.
--log-level <level> all, trace, debug, info, warn, error, fatal or none.
--completions <shell> Print a completion script for bash, zsh, fish or sh.
--wizard Build a command interactively.

Where a command takes a branch and you leave it out, it uses the branch of the worktree you’re standing in.

wrktr setup [<org>/<project>] [<directory>]

Section titled “wrktr setup [<org>/<project>] [<directory>]”

Everything a machine needs to work the wrktr way, in one command, and safe to run again: each step it finds done, it skips.

  1. Signs in (wrktr login), unless this machine is signed in and its token still works.
  2. Runs the daemon as a login service (wrktr daemon install), or moves the service to this CLI’s build if it’s on an older one. A daemon you run by hand is left alone. The service is macOS-only; elsewhere it says to run wrktr daemon.
  3. Installs the agent skill (wrktr skill install).
  4. Given a project, gets you a copy to work in: a clone if it’s yours (one of your organizations’, or a fork you made before), otherwise a fork into your personal organization (wrktr fork), cloned into <directory> (the project’s name by default).
Terminal window
wrktr setup # just the machine
wrktr setup wrktr/starter # the machine, and your own fork of the starter in ./starter

Sign this machine in. By default it shows a code and opens the browser to approve it; the token it receives is saved in ~/.wrktr/config.json, readable only by you.

Flag
--env <prod|dev> Which wrktr to sign in to (default prod). Use a separate WRKTR_HOME per environment.
--api <url> The API’s base URL (overrides --env).
--token <token> Use an existing access token, or an op:// 1Password reference, instead of the browser.

Who the CLI acts as, and the organizations they belong to with their role in each.

Your access tokens: name, prefix, when each was created and last used, and when it expires. Never the values.

Mint an access token for CI or another agent. It opens the browser so you can approve it (the page shows <name>), then prints the token once on stdout, alone, so wrktr token create --name ci | pbcopy captures just the token. Use it as WRKTR_TOKEN.

Revoke a token. Whatever uses it stops working at once. <id> can be the start of an id from token ls.

Create a wrktr project for the repo you’re in and push it, or link the repo to an existing one. It registers the repo with the daemon and sets up wrktr credential so plain git works with the remote.

Flag
--name <name> The project’s name (defaults to the repo folder’s name).
--org <org> The organization to put it in (defaults to the one it’s linked to, or your own).

Clone a project (into <directory>, by default the project’s name) and register it with the daemon. Plain git works in it from then on (see wrktr credential).

Fork a project you can read (a public one, or one of your organizations’) into an organization of yours, by default your personal one, then clone the fork like wrktr clone does. The fork is a new private project with a copy of the source’s default branch; it remembers where it came from, and project show names it. The clone has the source as an upstream remote, so git pull upstream main brings in its later changes.

  • --org <org>: the organization to fork into.
  • --name <name>: the fork’s name, if not the source’s (needed when that name is taken there).
  • --no-clone: only make the fork on wrktr.

git’s credential helper for a wrktr remote: you don’t run it, git does. The remote only takes short-lived tokens, so instead of a saved password, init and clone set this in the repo’s .git/config, for the remote’s URL only:

[credential "https://…/git/<namespace>/<project>.git"]
helper =
helper = !wrktr credential <org>/<project>

Then git pull, git fetch and git push (and your editor’s git) work as they do anywhere else: each time git needs to authenticate, it gets a fresh token minted for you. The empty helper = keeps a global helper (such as the macOS keychain) from storing a token that’s about to expire. store and erase do nothing. Repos set up before this get it the next time the daemon starts. When you’re not signed in, git fails with the reason instead of asking for a password.

Projects, with their default branch and when they last changed: one organization’s, or by default every one you belong to.

A project: who can see it, its default branch, last push, git remote and id. Defaults to the clone you’re in, or --project.

Create a project on wrktr without a local repo (for one you have locally, use init).

Flag
--import <url> Start it as a copy of an HTTPS git remote, such as a GitHub repo, instead of empty.
--description <text> What the project is.

Make the project public, so anyone can read its code, history, branches, reviews and CI, signed in or not, or private again (its organization’s members only). Owners only. Only members can ever change a project; someone outside it who runs wrktr clone gets a read-only copy that git pull keeps current and the daemon leaves alone.

People are named by email. <org> defaults to the organization of the clone you’re in, or of --project.

The organizations you belong to, and your role in each.

An organization: its name, your role, and its projects.

Create an organization; you become its owner. <slug> is its name in URLs and on the CLI.

Change an organization’s display name (owners only; its slug stays).

Its members with their roles, and pending invites.

Add someone (owners only). If they have an account they join at once; otherwise they’re invited and join when they first sign in with that email. --role <member|owner> (default member).

wrktr org role [<org>] <email> <owner|member>

Section titled “wrktr org role [<org>] <email> <owner|member>”

Change a member’s role (owners only). An organization always keeps at least one owner.

Remove a member, or cancel a pending invite to that email. Owners remove anyone; you can remove yourself to leave.

Create a branch in its own worktree under .wrktr/worktrees/<name>, copy the files listed in wrktr.json copy into it, run its install command, and push it. The daemon keeps it in sync from then on. A name used before is reused only if that branch is fully merged.

It starts from the default branch as wrktr has it: the latest is fetched first, so a local copy that fell behind is never the base (and is fast-forwarded when nothing has it checked out). Offline, it starts from the local copy.

Flag
--from <ref> Where to start it (defaults to the latest default branch).
--experiment A spike or prototype: it stays in progress and never lands.

The branches that have a worktree on this machine. With --all, every branch in progress on wrktr instead (its head, state and when it last moved, newest first), from anywhere: it takes --project.

Flag
--all List the branches on wrktr, not the worktrees here.
--landed With --all, include branches that landed.
--closed With --all, include branches that were closed.

What a branch does: the review agent’s description of it (a title, a summary, the changes by area, risks and how to check it), its head and its state. The description follows the branch as it moves; it says so when it was written for an older head.

Remove a branch’s worktree. Alias: wrktr branch remove.

Flag
--force Remove it even with uncommitted changes (they’re lost).
--delete Also delete the branch, on wrktr and locally. Its review history stays.

Mark a branch as an experiment that never lands. --off lets it land again.

Close a branch without landing it (a spike, an abandoned approach). Its agents and checks stop; its history and reviews stay.

Reopen a closed branch.

Read a project’s history and changes from wrktr, no clone needed.

Commits, newest first: short sha, date, author and subject. <ref> is a branch or a commit; it defaults to the worktree’s branch, or the default branch outside a clone. --limit <n> for how many (default 20).

What a branch changes against its base: by default a stat, one line per file (Added, Modified, Deleted, +added -deleted lines), then the totals.

Flag
--patch, -p Every file’s changes as a unified diff, like git diff.
--file <path> Only this file’s changes, as a unified diff.
--base <branch> Compare against this branch (default: the default branch).

The branch’s head (and whether this worktree has commits not pushed yet), its state (in progress, landing when ready, landed, closed, an experiment), its checks, the review agent’s verdict, open threads, and whether it conflicts with the default branch or the daemon can’t sync it. Once it has landed, where the land is deployed: each environment, its url and run when what’s live there has it (and whether the url serves it, for an environment with verify), or that it isn’t there yet.

dev live at https://dev.example.com (run #4) · serving
production not yet: run #3 (125fa7d) is live, from before it
Flag
--branch <name> The branch.
--watch Refresh every 10 seconds. With --json, prints one JSON line per refresh.

The branch’s open reviews, their threads and failing checks: what an agent works through. --branch <name> for another branch.

Reply to a review thread, as the agent: what you did, or why not. --branch <name> for another branch.

Mark a thread resolved. --branch <name> for another branch.

A branch’s reviews, newest first.

Review a branch, yours or another agent’s: a summary, a verdict and line comments, in one go. Line numbers refer to the branch’s head.

Flag
--verdict <approve|changes|comment> Approve, request changes, or leave notes without a verdict.
--summary <markdown> What you found.
--comments <file.json> Line comments: [{"path": "src/a.ts", "line": 12, "body": "..."}], or {"comments": [...], "notes": ["..."]} to add points that aren’t about one line.

Set a review aside so it no longer counts. <id> can be the start of an id from review ls.

Ask the review agent to review the branch’s head now, replacing a review of it. It reviews by itself after each push once checks pass; this is for a review that failed, or a fresh look at the same head.

Each push runs the checks in wrktr.json ci. The review agent reads their results, and land waits for the required ones to pass.

A CI run: each check’s state, time and notes (optional, cached, exit code, a retry), and the last lines of the ones that failed. Without <run>, the branch head’s run. <run> can be the start of an id from ci runs.

Flag
--branch <name> The branch.
--wait Wait until the head’s run is over, then exit 1 unless it passed: wrktr ci show --wait && wrktr land.
--timeout <seconds> With --wait, give up after this long (default 1800), exiting 1.

The project’s CI runs, newest first: status, branch, commit, how long each took. --branch <name> for one branch’s; --limit <n> for how many (default 10).

A check’s full log, as stored when it finished (ci show prints only the last lines of a failed one). Defaults to the branch head’s run: --run <id> for another, --branch <name> for another branch’s head.

Run the branch head’s checks again, ignoring results reused from an identical tree (for a flaky check, or one that depends on something outside the repo). --branch <name> for another branch.

Land a branch on the default branch with a merge commit, made by the server. It lands only if checks pass, the review agent approved the current head and no blocking thread is open (nits never block); otherwise it says what’s missing. Run from the branch’s worktree, it refuses uncommitted changes and a head the daemon hasn’t pushed yet. After it lands, its on: land environments deploy it; wrktr env wait dev waits for that, and wrktr status shows every run that shipped it.

Flag
--when-ready Don’t land now: the server lands it (as you) as soon as it’s ready. Nothing has to keep running.
--cancel Stop waiting to land it (undoes --when-ready).
--force Land even though checks, threads or the review say it isn’t ready.
--rm Remove the branch’s worktree after landing, if it has no uncommitted changes.

Environments are declared in wrktr.json under environments. An on: land environment deploys every land by itself; an on: promote one deploys the commit someone promotes.

An environment whose secrets aren’t all set on the project isn’t set up: a land doesn’t run it, and promoting or re-running it is refused, with what’s missing and wrktr secret set <name> to fix it. wrktr env ls and the Environments page show it as not set up (gray, not a failed deploy); a fork starts that way, since secrets aren’t copied. Once the secrets are set, the next land deploys it.

Every run’s steps get what they deploy as WRKTR_PROJECT, WRKTR_ENVIRONMENT, WRKTR_COMMIT, WRKTR_RUN, WRKTR_TRIGGER and WRKTR_URL, for deploy scripts that want them.

Every Workers deploy says what it is. A run’s requests to the Cloudflare API go through wrktr’s deploy gateway, which adds a small manifest to every Worker the run uploads, as a static asset at /.well-known/wrktr.json. For a public project:

{
"project": "acme/web",
"environment": "dev",
"commit": "94b562e5c0d1a2b3c4d5e6f708192a3b4c5d6e7f",
"run": 4,
"trigger": "land",
"deployedAt": "2026-10-13T17:05:12.000Z",
"previous": { "commit": "5f3a1c0e9b8d7a6f5e4d3c2b1a0f9e8d7c6b5a49", "run": 3 },
"promotedFrom": null,
"branches": ["copy-hex", "lock-colors"],
"checks": { "ci": "passed", "review": "approved" },
"links": {
"project": "https://wrktr.com/acme/web",
"run": "https://wrktr.com/acme/web/-/environments/dev/runs/4",
"compare": "https://wrktr.com/acme/web/main/commits"
}
}
Field What it is
previous The environment’s run that was live before this one (it ships previous.commit..commit), or null
promotedFrom For a promotion or rollback, the run of the from environment that passed this commit; else null
branches The branches landed between previous.commit and commit, oldest first ([] when it can’t tell)
checks The deployed commit’s landing: its CI run and its review (approved, changes, commented); null if it wasn’t a land
links.compare The default branch’s commits (wrktr has no compare page yet; links.run lists what the run shipped)

A private project’s site serves only environment, commit and run: no project name, links, branches or checks. Neither ever has people, commit messages, branch titles, review text, Cloudflare account or script names, or secret names. The Worker version each run uploaded, and its compatibility date, are in the run (wrktr env show, the API) rather than the file: Cloudflare names a version only after the assets, the manifest among them, are up.

Nothing to configure: it rides along on the assets upload your deploy already makes (a Worker without assets gets a set holding just this file), so any bundler or framework works. Static assets are matched before your Worker runs, so it’s served ahead of your own routes; a Worker with run_worker_first sees the request first and decides. If anything about an upload isn’t what the gateway expects, it leaves the upload exactly as it was.

After a run passes, wrktr checks each environment with a url: the url must serve the manifest of the run’s commit, retrying for about a minute while the edge catches up, and Cloudflare must have the Worker versions the run uploaded deployed (asked with the same secret the deploy used). The run is then serving, not serving (with what the url or Cloudflare has instead), or unverified when the url serves no manifest and Cloudflare can’t be asked (a deploy that didn’t go through a Workers upload), which is gray, not red. wrktr env ls, wrktr env show, wrktr status and the Environments page show which. "verify": { "check": "/health" } also requires a 2xx there. Nothing secret or personal goes in the manifest; "verify": false on an environment turns off both the manifest and the check (do that for one whose url isn’t the deployed site, like a package page, or to keep a private project’s commits off its site).

The project’s environments: what’s live in each, what’s running, and what a promotion would ship. Each one’s url is its address; --json gives it to agents, who can check a landed change on dev there.

An environment’s runs, newest first. --limit <n> for how many (default 10).

One run: every step (done or not) with its command and state, the last lines of a failed step’s log, and the commits it ships.

wrktr env logs <environment> <run> [<step>]

Section titled “wrktr env logs <environment> <run> [<step>]”

A run’s step logs, in order (or only <step>): a finished step’s full stored log, and what a running step has printed so far. --json gives every step’s log in one result.

Flag
--follow, -f Keep printing as the run goes, step after step; when it ends, exit 1 unless it passed. Not with --json.

Wait for a landed branch’s deploy to an environment, then say how it went: exit 0 once it’s live (serving, if the environment checks its url, or replaced by a newer run that still has it), 1 if it didn’t go out, isn’t served or was rolled back, 2 if the environment isn’t set up. It prints the url and what the site serves there (/.well-known/wrktr.json: its commit, run and branches). The step after wrktr land --when-ready: wait, then open the url and check the change.

Flag
--branch <name> The landed branch (default: the current worktree’s)
--commit <sha> A commit of the default branch (the full 40 characters), instead
--timeout <secs> How long to wait before giving up with 1 (default 900)

wrktr env promote <environment> [<commit>]

Section titled “wrktr env promote <environment> [<commit>]”

Deploy a commit to a promote environment: by default what its from environment has live. The commit must be the full 40 characters. An older commit than what’s live is a rollback.

Run an environment’s newest run again, once it’s over.

Stop a queued or running run.

Values an environment’s steps use, listed under environments.<name>.secrets in wrktr.json. They’re stored encrypted and only reach a deploy while it runs.

Set a secret from stdin, never from the command line (so it isn’t in your shell history): pbpaste | wrktr secret set CLOUDFLARE_API_TOKEN. Owners only. Names are capitals, digits and _, starting with a letter.

The project’s secrets: names, who set each and when. Never the values.

Remove a secret. Owners only.

The daemon keeps every worktree of every registered repo in sync: it commits after a quiet moment, pushes, merges the default branch in, and writes the files agents read.

Run it in the foreground.

Flag
--quiet-ms <ms> Commit after this long without file changes (overrides wrktr.json; default 30000).
--poll-ms <ms> How often to check the remote (default 5000).

wrktr daemon install / upgrade / restart / uninstall

Section titled “wrktr daemon install / upgrade / restart / uninstall”

Run it as a login service from a stable copy of the CLI; move the service to this CLI’s build and restart it; restart it; stop it and remove it. The service is a macOS LaunchAgent; elsewhere, run wrktr daemon under your own supervisor (systemd, a container’s entrypoint).

What the running daemon is syncing, repo by repo and worktree by worktree, with any errors.

The service’s log. --follow (-f) keeps printing; --lines <n> (-n) for how many lines (default 50).

Install the wrktr skill, which teaches coding agents (Claude Code and others) to work the wrktr way. --dir <path> for another skills directory (defaults to ~/.claude/skills and ~/.agents/skills).

Print the skill (SKILL.md).

With --json:

  • stdout carries exactly one JSON value: the command’s result. Progress lines, and the output of a new worktree’s install command, go to stderr instead. status --watch --json is the exception: one JSON value per line, one line per refresh. wrktr daemon (in the foreground) and wrktr daemon logs stream, so they refuse --json.
  • A failure prints {"error": {"tag": "...", "message": "..."}} on stderr. tag names the kind of failure when there is one (ProjectNotFound, Unauthorized, InvalidProjectFlag, ProjectFlagNotAllowed, JsonNotSupported, …).

Exit codes: 0 when the command did what it was asked, 1 when it didn’t (including a refusal, such as land when the branch isn’t ready). Act on the exit code, not the wording.

Terminal window
wrktr status --project acme/api --branch fix-login --json | jq -r '.review.verdict'
wrktr land fix-login --project acme/api --json || echo "not landed yet"
Variable
WRKTR_TOKEN An access token. When set, the CLI uses it instead of ~/.wrktr/config.json, so no login is needed.
WRKTR_API_URL The API to use with WRKTR_TOKEN (default https://api.wrktr.com).
WRKTR_HOME Where the CLI keeps its config, state and the daemon’s files (default ~/.wrktr). Use one per wrktr environment.
WRKTR_DEBUG Set to 1 to print a failure’s full cause instead of one line.
WRKTR_INSTALL_DIR, WRKTR_VERSION For the install script: where to put the binary, and which release.
File
~/.wrktr/config.json The API and the access token (or an op:// reference), written by login.
wrktr.json At the repo root, committed. copy: gitignored files to copy into each new worktree (such as .env). install: a command run in each new worktree. quietMs: how long the daemon waits before committing. maxFileBytes: files larger than this are never committed. ci: the checks each push runs. environments: where the project deploys.
.wrktr/worktrees/<branch>/ Each branch’s worktree. .wrktr/ is kept out of git.
.wrktr/FEEDBACK.md In a worktree: the branch’s open review threads and failing checks.
.wrktr/BEHIND.md Merging the default branch in conflicts: what to do.
.wrktr/DAEMON.md The daemon can’t sync this worktree: why.
.wrktr/CONFLICT.json A rebase onto the remote stopped on conflicts: resolve them, then git rebase --continue.