# kingshand (kingshand.emgeelabs.in): full text > A Windows tool that runs several Claude Code sessions at once: you talk to one session, it dispatches each worker into its own git worktree and brings back what needs deciding. Every page of kingshand.emgeelabs.in inlined, in the order a reader would take them. The short index is at https://kingshand.emgeelabs.in/llms.txt ------------------------------------------------------------------------------ # kingshand - run several Claude Code sessions from one Source: https://kingshand.emgeelabs.in/ kingshand One Claude Code session you talk to, which puts every other one to work. kingshand takes a description of the work, writes a brief, waits for your approval, and runs each worker as its own Claude Code session in its own git worktree. Windows, PowerShell 7, MIT licensed. Install it · Read the design decisions · Source on GitHub The problem it solves Running one Claude Code session is easy. The trouble starts at three: a fix in one repository, an investigation in another, a flaky test somebody has to sit with. You become a tab-juggler - three terminals, three sets of context in your head, and no way of knowing which session went quiet an hour ago because it is waiting on a question nobody is there to answer. kingshand makes one session the only one you talk to. It dispatches the others, watches their screens rather than a status word, and comes back to you when there is something to decide. What it gives you - Parallel workers. One background session per unit of work, each isolated in its own git worktree, so several tickets can be in flight without treading on each other. - Two gates. You approve what is dispatched and you approve what lands. Both can be turned off per project. - A delivery posture per project. A repository is registered local-only , direct-PR or no-mistakes . Nothing is dispatched into a repository that is not registered, and the posture is read rather than guessed at. - A queue that survives a restart. Work items, dependencies and held decisions are stored on disk, because a decision that lives only in the conversation is a decision you will lose. - A digest at session start. Registered projects, live workers, the queue, your standing instructions and the curated memory, all handed over when the session opens, so a restart is close to a non-event. - Short replies, and a review surface for what cannot be short. Next action first, numbered steps, no preamble. Anything you have to decide opens in your browser instead of scrolling past in chat. - Standing instructions it cannot edit. Your instructions.md is read every session and never written to - enforced by the permission layer, not by prose asking nicely. - Nothing installed into your other projects. All thirteen skills live in kingshand's own repository, so a Claude Code session anywhere else on the machine behaves exactly as it did before. How a piece of work moves through it - You describe the work in the one session you talk to. - It writes a brief and waits for your word. Nothing is dispatched before you approve it. - It creates a git worktree inside the target repository, writes the worker's settings and marks the worktree trusted, so an unattended worker does not stop on a folder-trust dialog. - The worker runs as an ordinary interactive Claude Code session in a terminal kingshand owns, which is what lets it read a worker's screen while it runs and send text to one that has gone astray. - The worker leaves a report.md . That reaches the landing gate, and the landing gate reaches you. Who it is for Someone on Windows who already uses Claude Code and wants more than one piece of work running at a time without supervising each one by hand. It needs PowerShell 7, Git for Windows, Claude Code, and three small tools the installer fetches or names - the install page lists all six and what each is for. What it is not - It does not do the project work itself. It dispatches and supervises; the workers write the code. - It is Windows only. Every script targets PowerShell 7 on Windows. On macOS or Linux the tool to use is firstmate by Kun Chen, which kingshand is a Windows-native rebuild of ideas from, and which does some things kingshand cannot. - It is not a hosted service. You clone a repository and run it on your own machine. There is nothing to sign up for and no account. Permissions, stated before you install kingshand ships with Claude Code's permission prompts turned off for itself and for every worker it starts: neither will ask you to approve a tool call. That is deliberate - the session reads diffs, runs git and merges locally hundreds of times in a session - but it is a real decision, and better made knowingly. What still constrains it: - Workers only ever run inside their own git worktree, never in your checkout. - Nothing is dispatched into a repository you have not registered. - Nothing pushes unless that project is registered with a push-capable posture, and nothing is merged for you at all - a pull request is where the work stops. - Reads of ~\.ssh , AWS credentials and kingshand's own credentials directory are blocked, as are edits to your instructions.md . If you would rather approve each call, the setting is one line in .claude\settings.json and removing it restores the prompts. Where everything is - Install and first run - the requirements, the commands, and what the installer writes outside the repository. - Design decisions - the records kept about how workers are run and controlled, mirrored from the repository. - llms.txt and llms-full.txt - this subdomain as plain text. - emgee-labs/kingshand - the source, the tests, and the MIT licence. ------------------------------------------------------------------------------ # Install kingshand Source: https://kingshand.emgeelabs.in/install Install kingshand kingshand runs from a clone of its own repository. You clone it, open Claude Code in that directory and tell it to set itself up; the installer checks what is on the machine, names anything missing with the command that fixes it, and installs nothing unless you ask it to. Install and first run Clone it wherever you keep things. Any drive, any folder, spaces in the path are fine. git clone https://github.com/emgee-labs/kingshand cd kingshand claude Then type set it up - or setup , or /setup . Every skill ships inside the repository, so they are readable in a fresh clone with nothing installed yet. The installer names what it found, what it installed, and what still needs you. The manual equivalent, if you would rather run it yourself: .\install.ps1 -InstallMissing -InstallMissing is opt-in. Without it nothing is installed and each missing tool is reported with the exact command that fixes it. Nothing self-elevates. Open a new shell afterwards so KINGSHAND_HOME is picked up. There is no one-line remote installer There is no irm ... | iex for kingshand, and a page that offered one would be offering something that does not work. install.ps1 resolves its own location and imports PowerShell modules from the bin\ directory beside it, so it only runs from inside a clone. The three commands above are the install path, and they are the ones the repository itself documents. What you need Six things, and the installer fetches or names every one of them. Requirement Why Install PowerShell 7+ every script targets it winget install --id Microsoft.PowerShell Claude Code the session you talk to, and every worker npm install -g @anthropic-ai/claude-code Git for Windows worktrees are the isolation winget install --id Git.Git lavish-axi the review surface both gates render to npm install -g lavish-axi tasks-axi the durable backlog npm install -g tasks-axi herdr the terminal every worker is spawned and watched through fetched by the installer herdr is the one thing fetched directly. It is checked against the SHA-256 published at https://herdr.dev/latest.json before it is extracted; a mismatch deletes the download and installs nothing, and an offline machine is told so in one line rather than shown a web exception. What the installer writes outside the repository Three things, each named as it is written: - The user environment variable KINGSHAND_HOME . - The user environment variable LAVISH_AXI_PORT . - One line, .claude/worktrees/ , in your global gitignore - because workers live inside your own repositories and would otherwise show up there as untracked changes. It creates that file and points core.excludesFile at it when the config is unset, and it never writes the line twice. Nothing is linked into ~\.claude\skills\ , so a Claude Code session in any other directory is unaffected. The installer is idempotent: running it twice does nothing the second time except say so, and it never overwrites an existing instructions.md or an existing config value without telling you what it left alone. Optional, and only if you need them The GitHub CLI, for pull requests gh is needed by the push-capable postures - direct-PR , no-mistakes , no-mistakes-prod-only - because those end at a pull request. Work that stops at a finished local branch never calls it. winget install --id GitHub.cli , then gh auth login . The review gate no-mistakes is needed only by projects registered no-mistakes or no-mistakes-prod-only . setup asks whether you want it, and .\install.ps1 -WithReviewGate adds it at any time. Do not run npm install -g no-mistakes : that name on npm belongs to a different, unrelated tool, which installs cleanly and then does not work. Azure DevOps Only if you work ADO tickets. Reading a work item straight into a brief needs the ado-local-mcp server configured in Claude Code, plus an organization and a token. Nothing in the installer needs it; without it you paste the ticket or describe the work, which is the ordinary path. Pester 6+ Only to run kingshand's own test suite. Install-Module Pester -MinimumVersion 6.0.0 -Force -SkipPublisherCheck -Scope CurrentUser , or let -InstallMissing do it. Tests run with Invoke-Pester -Path .\tests . After it is installed - Open a new shell, cd kingshand , run claude . The screen will be empty - that is normal and not a failed install. Say anything, and the first reply tells you where things stand. - Write your standing instructions in instructions.md : how you want to be addressed, your delivery defaults, your conventions. Read every session, never written to, gitignored. - Register a repository with /annex D:\code\your-repo - any path on any drive. It records the delivery posture and never clones. - Give it work: fix the flaky login test in your-repo . You get a brief to approve before anything is dispatched. - Check in with /survey for where everything stands, and /audience for what you missed. The design decisions explain how workers are actually run and watched, and the overview covers what the tool is for. ------------------------------------------------------------------------------ # kingshand design decisions Source: https://kingshand.emgeelabs.in/docs kingshand design decisions These are the records kingshand keeps about how it runs and controls workers: what was decided, what prompted it, what it costs, and what would reverse it. They are mirrored from the repository when this site is built, so they say what the repository says. The records Worker control plane: stay on claude --bg This record's own revisit trigger fired. It is kept because the reasoning is still the reason kingshand refused a heavier control plane for as long as it did, and because the trade table below is what the replacement... Worker control plane: herdr Kingshand spawns and controls workers through herdr. Each worker is an ordinary interactive Claude Code session running in a herdr pane, in a git worktree kingshand creates itself. claude --bg --worktree is gone, and... Where these come from - Source: github.com/emgee-labs/kingshand/tree/main/docs - Mirrored from commit 617dca36 , dated 2026-08-30. - Anything not here - the README, the skills, the tests - is in the repository itself . To install the tool these records describe, see the install page . ------------------------------------------------------------------------------ # Worker control plane: stay on claude --bg - design record Source: https://kingshand.emgeelabs.in/docs/2026-08-28-worker-control-plane-decision Date: 2026-08-28 Status: **superseded on 2026-08-29 by `2026-08-29-herdr-worker-control-plane.md`** **This record's own revisit trigger fired.** It is kept because the reasoning is still the reason kingshand refused a heavier control plane for as long as it did, and because the trade table below is what the replacement was measured against. Do not follow its instructions - workers are no longer spawned this way, and a running worker can now be steered. ## The decision Kingshand keeps spawning workers with `claude --bg --worktree` and accepts that it cannot steer a running worker. It does not adopt the ConPTY model firstmate uses on Windows. Revisit only under the conditions at the end of this file. ## What prompted it Porting the `rally` procedure from the tool kingshand derives from exposed that three of its five escalation steps - answer a question in one line, interrupt and redirect a confused worker, relaunch carrying a progress note - have no mechanism in kingshand. The verified control surface is `claude agents --json`, `logs`, `stop`, `rm` and `attach`. There is no `claude send`. `attach` is interactive and belongs to the user, not to the Hand. ## Why a ConPTY harness can steer and kingshand cannot This is architectural, not a Windows limitation. A harness that hosts the agent inside a pseudoconsole it creates itself owns that ConPTY, and can therefore write into the agent's stdin: send the literal text, then send the Enter key to submit it. Liveness comes from OSC 133 prompt marks emitted into the same stream. A working implementation of exactly this exists, so the capability is real rather than hypothetical. Steering requires owning the process's terminal. Kingshand's workers are Claude Code background sessions, so Claude Code's supervisor owns them and there is no pseudoconsole to write into. No amount of work inside kingshand changes that; only replacing the spawn mechanism would. ## The trade | | `claude --bg` (chosen) | ConPTY daemon | |---|---|---| | Infrastructure | none | a Node daemon, ~5 JS files, a native dependency, its own liveness machinery | | Steer a live worker | no | yes | | Interrupt and redirect | no | yes | | Relaunch carrying a note | no | yes | | Stuck-worker options | stop and re-dispatch, or hand to the user via `claude attach` | full five-step escalation | ## Why the cheap option wins here A worker costs almost nothing to re-dispatch: the brief is on disk, the worktree persists through `claude stop`, and a replacement starts from the same brief plus a progress note in its text. The escalation steps that are lost are the ones that matter least when restarting is cheap. Against that, the ConPTY model adds a daemon and a native dependency to a tool whose whole appeal is having no moving parts. That is a poor trade today. ## What this costs, stated plainly - A worker waiting on a question its brief already answers cannot be answered by the Hand. It is stopped and re-dispatched with a better brief, or handed to the user with `claude attach`. - `Dispatch-Worker.ps1` always creates a fresh worktree, so a replacement is a second copy by construction. This sits in tension with firstmate's "never two worktrees for one task", and `rally` names that tension rather than hiding it: the stuck worktree's work must be committed and carried into the replacement's base before the replacement runs. ## What would change the decision - Claude Code gains a scriptable way to send input to a background session. That removes the whole reason to own a terminal, and the ConPTY model stays unnecessary. - Re-dispatching stops being cheap - long-running workers, expensive setup, or work that cannot be resumed from its brief. - Stuck workers become frequent enough that stop-and-re-dispatch is a real cost rather than a rare annoyance. Nothing so far suggests this; no worker has hung yet. **The third one fired the next day.** A worker opened an interactive prompt and sat on it for five to six hours with nothing watching, and the control plane above had no way to see that state at all. The successor record explains what replaced this and what that cost. ------------------------------------------------------------------------------ # Worker control plane: herdr - design record Source: https://kingshand.emgeelabs.in/docs/2026-08-29-herdr-worker-control-plane Date: 2026-08-29 Status: decided Supersedes: `2026-08-28-worker-control-plane-decision.md` ## The decision Kingshand spawns and controls workers through herdr. Each worker is an ordinary interactive Claude Code session running in a herdr pane, in a git worktree kingshand creates itself. `claude --bg --worktree` is gone, and so is the whole `claude agents --json` / `logs` / `stop` / `rm` / `attach` surface it came with. `bin\Herdr.psm1` is the only place that knows herdr's command line. Nothing else composes one. ## What prompted it Yesterday's record said the cheap option won because no worker had hung yet. One did, the next day. It called `AskUserQuestion`, drew a menu nobody could see, and waited five to six hours. The old control plane could not tell that state apart from working: a hung worker and a busy worker looked identical, so the hang was found by the user asking rather than by anything noticing. That was the trigger this record's predecessor wrote down for itself, and it fired sooner than the predecessor expected. ## Why herdr answers it herdr hosts the agent in a terminal it owns, so it can both write into it and read what is on it. Two capabilities follow, and they are the whole reason for the move. **It classifies state.** `idle`, `working`, `blocked`, `done` - and `blocked` is a first-class state, detected from what the agent actually rendered. In the trial, the five-hour hang was a state herdr reported within seconds of the menu appearing. **That classification did not hold in production, and the correction is recorded below** - what survives is the capability underneath it, that herdr can be asked what is on a worker's screen. **It waits on state.** A wait blocks inside herdr and returns the moment the worker reaches one of those states. The Hand's dispatch arms one, and its completion is the wake. There is no polling loop left anywhere, which is not just tidier - a poll on a 20-second interval was a promise the Hand had to keep making to itself, and the defect it was written to fix was the Hand not keeping it. Steering came along with it. A running worker can be sent text, and a blocked one can be answered a key at a time. That was the capability the predecessor record wrote off as not worth a daemon; it turns out to be free once something owns the terminal. ## The evidence All of it observed on this machine against herdr 0.8.2, protocol 20, on native Windows. Nothing below is inferred. - A genuinely busy worker read `working` for the full duration of a 75-second turn and settled to `idle` when it ended. The feared "reports everything as dead" failure did not occur. - State does not come from the process name. It comes from priority-ordered regex rules in a per-agent manifest run against the rendered terminal, and the manifest for Claude Code is current and fetched from herdr's own server. - A worker made to open an `AskUserQuestion` menu read `blocked` twelve seconds later, and a wait armed on `blocked` beforehand fired with it. **This held in the trial and does not hold generally** - see the correction below, which was measured later on the same machine. - Sending that worker a prompt while blocked was refused outright, with a distinct error, rather than silently swallowed. - A clean `/exit` proved the worker stopped in 1.7 seconds. A hard kill was detected in 662 ms. - Text arrives intact: a 3,374-character prompt reached the worker whole. ## Correction: blocked detection does not hold Added 2026-08-29, after a live end-to-end run of this layer. The trial evidence above is real and stays; this is what happened when the same thing was measured again in production conditions. herdr 0.8.2 with agent-detection manifest 2026.08.21.1 does **not** reliably classify a Claude Code worker sitting on an unanswered `AskUserQuestion` menu. With the menu visibly on screen: - `agent explain` reported `state: idle`, matched by rule `live_prompt_box` at priority 950. Rule `live_blocked_form` at priority 980 - the one that fired in the trial - evaluated and did not match. Every blocked rule failed. - Minutes later the same still-blocked worker reported `done`, while a genuinely finished worker reported `idle`. The two states effectively inverted. **Correction, established later the same day: the cause was terminal width, not the manifest.** Those panes were 3 to 6 columns wide, rendering one character per line, because dispatch split an existing pane for each new worker and every split halved the survivors. herdr's rules are regexes over the rendered screen, so they cannot match a UI that never renders - and neither can kingshand's own guard. Re-tested at 94 columns, herdr classified the same blocked worker correctly, and so did the guard. Dispatch now gives every worker its own workspace; four created in a row measured 93-94 columns with no degradation. So the accurate statement is not "herdr's blocked detection does not hold". It is that **detection of any kind needs a readable terminal**, and kingshand was destroying the terminal it depended on. The guard stays anyway: one correct classification is not proof across a Claude Code interface change, herdr's rules are a network-fetched artifact that can lag one, and a screen read costs almost nothing against a worker silently reported as finished. The consequence is worse than the hang this port was built for. `Wait-HerdrAgent` with no `-Until` matches `idle`, `done` or `blocked`, so a worker waiting on a human wakes the Hand claiming completion: previously the worker went silent, now it is actively reported as finished, and whatever is downstream tears it down and reports work nobody did. **Kingshand therefore no longer relies on herdr's classification for the blocked case.** The worker's screen is the authority, and `bin\Herdr.psm1` owns the guard in three functions: - `Test-HerdrAgentAwaitingInput` reads the LIVE VIEWPORT - `agent read --source visible` - and answers whether an interactive prompt is on screen now. The live viewport is load-bearing: `recent` and `recent-unwrapped` include scrollback, so a worker that answered a menu earlier still holds that text in history and would read as blocked forever. - `Get-HerdrAgentState` is herdr's state corrected by that screen, returning `blocked` whenever a prompt is showing whatever herdr said. It is the only state function anything downstream calls, and `bin\Get-CrewStatus.ps1` routes through it, so nothing above reads `agent_status` raw. - `Wait-HerdrAgentSettled` is the guarded wake. It wraps the wait, re-checks the screen before reporting a state, and distinguishes "not settled" from a state rather than inventing an outcome on a timeout. The classification is still used for `working` and for waking at all, which is what herdr is needed for. What is not used is its word for whether a stopped worker is finished or waiting on a person, and `muster` no longer treats any state alone as proof of completion - a worker is done when it settled, is not awaiting input, and left the `report.md` its brief required. ## What this costs, stated plainly **No arguments can be passed to a worker, at all.** herdr's argument form is broken on Windows for Claude Code - it launches through a mechanism that cannot run a PowerShell entry point - so the only working shape is the bare launch. Everything that used to be a flag now lives in the worktree's own `.claude\settings.local.json`, written before the worker starts. A future requirement that genuinely needs a command-line argument has nowhere to go. **A fresh worktree hits the folder-trust dialog.** The old spawn path inherited trust and never needed its own entry; this one does, so trust is pre-seeded before the worker starts. Skip that and the worker starts up blocked on a dialog instead of working. **A force-killed worker costs its pane permanently.** It never sends its terminal-mode reset, so the pane echoes every later keystroke as literal junk and no herdr command recovers it. The worktree is never harmed - it is only a directory - but the pane must be discarded and a new one made. Hence: always `/exit`, never a kill. **Answering a prompt is a wrong-answer risk, not just a fiddly one.** Sending an arrow key and Enter in one call selects the wrong option and reports success while doing it. Keys go one per call, with the screen read back in between. **Workers run with transcript saving off.** The Hand is itself a Claude Code session, so the herdr server and every pane inherit `CLAUDE_CODE_CHILD_SESSION`. Both are scrubbed where kingshand starts them, but a herdr server it did not start carries whatever it inherited. The practical consequence is that the session transcript is not a reliable fallback for a worker's findings any more. `report.md` is not a nicety; it is the only durable record. **herdr keeps state outside the repository**, in `%APPDATA%\herdr` and `%LOCALAPPDATA%\herdr`, and there is no way to redirect it. Its server also fetches detection manifests over the network at start, falling back to bundled ones when offline. **The fragility moved rather than went away, and it has already cost us.** State classification is coupled to Claude Code's rendered interface and to herdr shipping a manifest that matches it. This was written as a future risk; it was live at the time of writing. Manifest 2026.08.21.1 does not classify the blocked case, and it degraded exactly as predicted - silently, with a confident wrong answer rather than an error. A versioned, network-fetched artifact can be fixed without waiting for a release, which is the good half; the bad half is that nothing announces the degradation, so kingshand carries its own screen check rather than waiting for a manifest to be right. ## What would change the decision - Claude Code gains a first-class scriptable way to run, watch and steer a background session. That would make owning a terminal unnecessary and this whole layer removable. - State classification degrades further. The blocked case has already gone, and the answer was to read the screen directly rather than to abandon herdr - the terminal it owns is what makes that possible at all. What would genuinely reopen the decision is losing `working`, or the screen read itself becoming unreliable, because then nothing distinguishes a busy worker from a stuck one and the case for this layer is gone. - herdr's argument handling is fixed on Windows. That does not undo the decision, but it would let configuration go back to being explicit rather than written into a settings file first. ## What must not be undone - The wait is an event, not a poll. Reintroducing a sleep-and-check loop rebuilds the thing this replaced and re-opens the silence it was meant to close. - `blocked` reaches the user immediately, and is never answered on their behalf. It is the defect this port exists to fix. - The screen check stays, and it reads the live viewport. Deleting it, or pointing it at `recent` or `recent-unwrapped`, restores a control plane that reports a worker waiting on a person as finished. No state is ever proof of completion on its own. - One file knows herdr's command line. Two would mean the next migration touches everything again.