CodeHerderSearch⌘KRequest access →

Start a session in your own checkout

Turn the git checkout you're already sitting in into a CodeHerder session, in the same terminal, with nothing cloned or moved.

Starting a session on a device gives you a fresh worktree that CodeHerder cuts there. This works the other way around: you’re already sitting in a checkout on your own machine, and you turn it into a CodeHerder session right where it is — same terminal, same directory, nothing checked out or moved.

Looking for a way to hand off a task description instead of typing into a live terminal yourself? See Run a task on your own machine.

ch start

There’s no worktree to provision and no branch to pick — it starts from the terminal you’re already sitting in. If nothing is set up on this machine yet, ch start sets it up for you (see Setting up the first time below). Starting from a folder that holds several repos? See Start from a parent folder of repos. Not sure whether it will work before you run it? See Check before you start below.

Without a CodeHerder login or configured server, it runs in standalone local mode. Once you’re logged in, it uses the same connected workspace as the session list. Pass --local to keep a session local even while logged in. The requirements and preflight below describe connected sessions.

What you need

  • macOS or Linux, in a real terminal. ch start isn’t available on Windows, and it refuses if stdin isn’t an interactive terminal — so it won’t run from a script or a pipe.
  • The top level of a git checkout, or a parent folder of repos. Run it from the repository root, not a subdirectory. A folder that holds several checkouts also works: see Start from a parent folder of repos.
  • A workspace where you’re a member, using a device you own — or one you administer as an owner or admin. Starting a session on a device as an agent needs owner or admin access. This only needs ordinary membership on your own device.

Your own device works across accounts. Starting a local session uses your membership in the selected workspace; it does not share your device with that workspace’s agents. Each session keeps its own workspace, credentials, visibility, and cost attribution. An admin using someone else’s device still needs a fleet link to that workspace or an ancestor.

If any of these aren’t true, ch start tells you exactly which one failed rather than a generic error — see If it refuses below.

Check before you start

ch start --check runs the same checks ch start itself runs before it does anything, including your credentials, whether you’re at a git top level, which harness it would pick, which workspace it would use, whether a device-server is reachable, whether that device runs through a container executor, whether it has a session root configured, whether your device is registered and linked to that workspace, whether the extra flags you passed with --arg or --skip-permissions are allowed, whether you have a free worktree slot, and whether your CLI is up to date. It creates no sandbox, starts no device-server, and registers no device. It writes nothing.

The flag check needs one harness. Pass --harness when you have more than one installed. The check asks the server, so it uses the same rules as a real start. If the server cannot answer, the check uses the rules built into your ch and says so. A flag the check refuses fails the check, and the message names the flag and the rule it broke.

ch start --check

Each check comes back with one of four verdicts:

  • pass — this step will succeed.
  • repairable — ch start fixes this itself, so it’s never a reason to stop.
  • fail — something needs your attention. For most causes, the line names the exact command to fix it.
  • unknown — the check couldn’t read the fact it needed. Also never a reason to stop.

The command exits 0 unless at least one check comes back fail, in which case it exits 1. That makes it safe to run in a script or a CI job — unlike plain ch start, which needs a real terminal and refuses on a pipe.

When everything passes, it prints one short line:

ch start --check: all clear — workspace <workspaceId> (acme/widgets), source: --workspace flag; device <deviceId> registered; harness: Claude Code

When something needs attention, it lists only the checks that didn’t pass, then a count:

[FAIL] workspace: no workspace resolved (source: unset) — fix: pass --workspace <ref>, or `export CH_WORKSPACE_ID=<id>` (see `ch workspace list`)
[UNKNOWN] device_workspace_link: not checked yet — workspace or device not resolved
9/11 checks pass

Pass --json for a structured version of the same report — {"data":{"ok":false,"checks":[{"key":"workspace","status":"fail","summary":"..."},...]}} — so a script can gate on ok instead of parsing the text.

--check predicts the same launch you’re about to run, so pass it the same --harness and --no-autostart flags you intend to use — a different combination can change which checks matter.

Setting up the first time

You do not need to run ch device-server by hand first. If ch start doesn’t find one already running on this machine, it registers the device and starts one for you, in the background, then waits for it to come up. It prints where the device-server’s own log is going, in case anything is slow to start.

That first-run registration also marks this machine as a personal device: it joins the workspace disabled, so the engine never hands it someone else’s tasks — it’s there to run your own ch start sessions, nothing more. ch start prints the device’s ID and the command to share it with the rest of the workspace:

ch device enable <deviceId>

See Managing your devices for what that changes and who’s allowed to run it.

The device server it starts

The device server ch start puts up for you is temporary, not something to manage yourself the way you would one started with ch device-server. It stops itself once your session ends, whether that’s a clean exit or ch start failing partway through. While a session is still running on it, though, it stays up — even a session from an earlier ch start.

If it’s ever left running with nothing on it, say the terminal got killed outright, it gives up on its own after about 10 minutes idle. The device doesn’t disappear when that happens; it just goes Offline.

A device server you start yourself, with plain ch device-server, is never stopped this way.

Choosing a harness

ch start offers only a coding-agent CLI proven to open a real interactive terminal you can type into — today that’s all five: Claude Code, Codex, Cursor, OpenCode, and Pi. Leave off --harness and it always opens a picker for you to choose from, even when only one is installed. In a terminal, the picker is a clickable set of tiles — click one, or use the arrow keys and Enter; a harness that isn’t installed shows an install link instead of a tile you can launch, and pressing Esc backs out without starting a session. Pass --harness <name> to skip the picker entirely:

ch start
ch start --harness claude
ch start --harness claude --skip-permissions
ch start --repo acme/widgets --title "fix the flaky test"

Flags, all optional:

  • --harness <name> — which coding-agent CLI to run. Must have a proven interactive shape (today, all five: claude, codex, cursor, opencode, pi); naming an unrecognized value, or one not installed on this device, refuses and names the fix.
  • --skip-permissions — start the harness without its permission prompts. Only Claude Code and Codex have this option. Another harness refuses it. See Skipping permission prompts.
  • --arg <flag> — pass one extra flag to the harness. Repeat it for more. CodeHerder checks the flags with the same rules as a launch config when the session registers. ch start --check runs the same check before the harness starts.
  • --repo <ref> — which registered repository this checkout counts as, if the match isn’t obvious. See Repo binding below.
  • --title <text> — a friendly label so you can find the session later.
  • --no-autostart — refuse instead of starting a device-server automatically, if you’d rather run ch device-server yourself.
  • --check — run the preflight instead of starting a session. See Check before you start above.

Launch options in the picker

To set options for one harness from the picker, right-click its tile, or select it and press o. The panel offers two options:

  • Skip permission prompts is a toggle. A harness without this option shows it as not available.
  • Extra flags takes flags separated by spaces. They go to the harness as you type them.

Click or press Space to toggle. Press Enter to launch, or use the Launch and Back buttons. Esc returns to the tiles and keeps your edits. A tile with options set shows Skip permissions or Custom flags in place of “Ready to start”. The panel starts from any --skip-permissions and --arg you passed. A harness that isn’t installed has no launch options. The options last for that one picker run. CodeHerder doesn’t save them.

What the banner tells you

Once the session is up, it prints a short banner before handing you the terminal: the sandbox and session IDs, the directory, which harness is running, whether a repo is bound yet, and whether the change-shape report and other awareness features are on, pending, or off (and why). It also tells you who can see the session and confirms that spend is tracked against the workspace. The session runs as you, the human who typed the command, never as an agent persona — every API mutation it makes (task comments, task creates, and so on) is attributed to your own identity. The idea is that the session tells you up front what it can and can’t see, instead of leaving you to find out the hard way.

Repo binding

Pass --repo and the binding is immediate. Leave it off and CodeHerder settles it shortly after launch, once the session’s first awareness scan runs — ch sandbox show <sandboxId> shows the settled answer. If your checkout’s remote matches more than one repository registered in the workspace, name the one you mean with --repo.

Start from a parent folder of repos

Many teams keep related repos side by side in one folder, such as ~/work/shop/ with web-app and orders-service inside. The folder itself is not a git checkout. Run ch start there, and the session works across all of those repos.

cd ~/work/shop
ch start

How CodeHerder detects it

A folder that is inside no git work tree is a parent folder. ch start looks at its immediate child folders only. A repo two levels down is not found. Files and dot entries are ignored.

A child counts when it is a git checkout whose origin remote matches a repo of your workspace. The workspace’s parent groups count too.

Skipped children

CodeHerder skips a child it cannot use. It does not refuse the start. The banner names each skipped child and says why:

  • a symlink
  • not a git checkout
  • no origin remote
  • not a repo of this workspace
  • its origin matches several workspace repos
  • its origin is not a usable repo URL
  • another folder already holds that repo

The banner

The banner shows a summary like this:

Parent folder: 3 of 5 child folders match repos of this workspace
Matched: web-app, orders-service, billing
Skipped: scratch (not a repo of this workspace), notes (not a git checkout)
The session works in your own checkouts; CodeHerder cuts no worktree or branch for them.

ch start --check reports the same facts. With --json, they appear under parentFolder, with the keys dir, matched and skipped.

Work in your own checkouts

The harness runs in the parent folder, so a relative path such as ../orders-service works. CodeHerder cuts no worktree, no branch and no merge request for these checkouts. Commit only in the repos you change. The change shape reports only the repos that have commits made after the session started. An untouched repo shows no branch, no push and no merge request.

Available repos and on-demand checkout

The session brief lists two groups:

  • Local repos are the matched children.
  • Available repos (no local copy) are workspace repos with no checkout in this folder.

Every active repo of the workspace and its parent groups is available. There is no repo cap. To check one out, run:

ch sandbox repos create <sandboxId> <repo>

This clones the repo into <parent folder>/<repo folder> on its default branch. The command fails when that path already exists. The clone stays after the session ends. ch sandbox show <sandboxId> lists the local and available repos, and the repo moves from available to local after the clone.

What it does not accept

--repo is refused in a parent folder, because the session is not bound to one repo.

When no child matches and the workspace has no active repo, ch start refuses:

<folder> is not a git checkout, and none of its child folders matches a repo of workspace <ref> — run ch start from a repository's root folder, or from a parent folder of workspace repos

If no workspace is named, it asks for --workspace or CH_WORKSPACE_ID. A subdirectory of a checkout is refused, and the message names the checkout’s root folder.

With --local

ch start --local works from a parent folder too. The parent folder is the local workspace, keyed by its path. The matched children are its repos, and ch repo list --local lists them. The brief names them.

  • Offline, every child checkout with an origin remote matches. There is no workspace repo list to compare it with.
  • The first local start can offer to set up Git for autonomous work. In a parent folder, choose Skip. A parent folder must stay outside every git work tree.
  • There is no on-demand clone offline. Clone the repo yourself.
  • Run ch from the parent folder. Inside a child, ch uses that repo’s own local workspace.
  • A local task create in a parent folder is refused with requires_team_workspace. Create the task in one repo’s folder, or connect the folder.
  • ch auth login in a parent folder offers local, cloud and hybrid modes. Cloud mode registers the unregistered children after you confirm once.

Where a parent folder keeps its definitions and state: see A parent folder of repos.

Detaching, reattaching, and stopping

Press Ctrl-] to detach without stopping the session — it keeps running, and so does the device server behind it (see The device server it starts above). To come back to it:

ch sandbox list workspace     # find it — its Type is "local"
ch session attach <sessionId> # reattach to its terminal

To stop it for good:

ch sandbox state <sandboxId> stopped

and bring it back later with:

ch sandbox activate <sandboxId>

One important difference from a session you start on a device: this kind of session does not come back on its own if your device reboots. Reattach or reactivate it by hand when you’re ready.

Your files stay put

CodeHerder never clones your repository, cuts a worktree, or switches your branch for this kind of session. Your checkout stays exactly as you left it, on whatever branch and commit you were already on. From a parent folder, this holds for each child checkout. The one exception is a repo you ask for with ch sandbox repos create.

Cost and visibility

Token spend from the session is attributed to the workspace and visible to its admins, and counts as task-free spend — see Task-bound vs. task-free spend for how that’s tracked and rolled up.

If it refuses

Run ch start --check first — see Check before you start above. It names the exact cause and, for most of them, the exact fix command. Here is what each cause means:

What it says, in short What it means
Not logged in Run ch login.
Not a git repository / not the top level Run it from the root of a git checkout, or from a parent folder of workspace repos. A subdirectory of a checkout is refused.
The path is a symlink, or isn’t a directory ch start needs a real directory, not a symlinked one.
Inside the device’s own session storage Your checkout happens to sit inside the folder the device uses for its own worktrees — move it, or use that folder for a different checkout.
ch start --check flags: no usable harness Not a plain ch start refusal — without --harness, ch start itself always opens the picker, and a harness that isn’t installed shows an install link there. --check still flags it, since it can’t open a picker of its own.
The server refused a flag you passed with --arg The message names the flag and the rule it broke, for example arg "-e" is not allowed for harness pi (denied flag). Remove the flag. An operator can allow a flag with CH_ALLOWED_AGENT_ARG_TOKENS on the server. ch start --check shows this message before the harness starts.
No workspace resolved Pass --workspace <ref>, or set CH_WORKSPACE_ID — see ch workspace list.
Signed in as a different user than the device server Run ch start as the same OS user account that’s running ch device-server.
Platform not supported ch start needs macOS or Linux.
CH_DOCKER_EXECUTOR is set Unset it — ch start refuses outright on a container executor.
The device server itself runs through a container executor Run that device-server without a container executor.
No session root configured on this device Set --session-root (or CH_SESSION_ROOT) on ch device-server and restart it.
Your device isn’t linked to this workspace, and you aren’t an owner or admin there Have an owner or admin run ch device workspaces create <deviceId> --workspace <ref> — or, if you are an owner or admin, ch start links it for you automatically.
Your device is archived Run ch device restore <deviceId>.
No free worktree slot on this device Run ch device reclaim <deviceId>, or stop an old session with ch sandbox state <sandboxId> stopped.
ch start --check flags: CLI more than a patch behind the server Not a refusal — ch start self-updates and restarts when it can, or carries on otherwise. Run ch self-update to get ahead of it.

Where the reason appears

When the server refuses a registration, the harness keeps running. The reason shows in four places:

  • The status bar shows Not registered: refused by server: <code>: <message> on one line. The tab shows only refused by server.
  • ch start prints the full reason and the path of the log.
  • registration-error.json holds the full reason in its reason field.
  • registration.log holds the full server response. Both files are in ~/.codeherder/launches/<runId>/.

Last updated

CodeHerder

Round up your herd.

Bring every human and every agent onto one table. Watch the work move. Costs update as it happens.

Try "pricing", "connect a device", or "who reviews the code"

↑↓ move · ↵ open · esc close