Confirmed via official Copilot CLI docs: there is no ask_user/elicitation tool available to custom agents (only execute/read/edit/search/agent/web/ todo aliases exist). Subagent calls made through the 'agent' tool are stateless — they run to completion and return one final result, with no mechanism to pause mid-task for a live human reply. This means conductor invoking interrogator via the agent tool could never work: interrogator would run as a subagent regardless of whether conductor itself was foreground or backgrounded, and subagents can't get real user answers. That's why it was silently writing fabricated decisions.md/ questionnaire.md content instead of actually asking anything. Fix: delete the interrogator agent entirely and fold its full Q&A procedure directly into conductor's own DESIGN PHASE, run inline in conductor's own foreground turn — never delegated. Updated the design skill/prompt, AGENTS.md, README, QUICKSTART, and role-tier config to match. Single entry point, no subagent path for anything that needs a live human answer.
12 KiB
Quick Start Guide
This walks a new user from zero to a finished, verified change using
redsen-lean-harness. For full command/flag reference see the main
README.md; this doc is the shortest path to "it worked".
0. Prerequisites
- Node >= 20
- Git
- GitHub Copilot CLI or VS Code Copilot
- A
CONTEXT7_API_KEY(required —lh doctorfails without it)
export CONTEXT7_API_KEY="<your key>" # add to ~/.bashrc or ~/.zshrc
The harness never writes this key to disk. It is read from the environment only.
1. Get the harness into your project
The harness has two layers you install separately: the behaviour layer
(.github/agents, skills, instructions, prompts, mcp.json — markdown, read by the
host) and the determinism layer (the lh CLI — Node, called by the agents). Every install
path below gets you the behaviour layer; only B and C also give you lh on PATH in one step.
A. Copilot CLI plugin (recommended — start here)
This is the primary distribution path for GitHub Copilot CLI users. It registers the
agents/skills/instructions host-wide, so every repo you open in that Copilot CLI account can
invoke its agents (e.g. redsen-lean-harness:conductor) and skills (e.g. /fast-track) — verified end-to-end on this machine:
# preferred: via the marketplace this repo publishes (no npm publish required, no deprecation warning)
copilot plugin marketplace add redsentech/lean-harness
copilot plugin install redsen-lean-harness@redsen
# also works, but Copilot CLI prints a deprecation warning for direct-source installs:
copilot plugin install redsentech/lean-harness
Use this when: you're a day-to-day Copilot CLI user who wants the harness available across multiple projects and doesn't need to modify the harness itself.
Limitation: this installs the behaviour layer only. You still need lh on PATH (see
below) — either npm install -g @redsentech/lean-harness from GitHub Packages (once you've
pointed the @redsentech scope at it, see The lh CLI), or step
B/C below.
B. Bootstrap an existing repo with the onboarding script
Use this when: you're on VS Code Copilot (which has no plugin installer and reads
.github/ directly), you want to try the harness against one specific repo before deciding to
install it host-wide, or you want lh linked in one shot without a separate npm step.
git clone git@github.com:redsentech/lean-harness.git # one-time, holds the source of scripts/onboard.mjs
cd lean-harness && npm install
node scripts/onboard.mjs /path/to/your-project --dry-run # preview only
node scripts/onboard.mjs /path/to/your-project --yes # do it
This copies the behaviour layer into /path/to/your-project, npm links the lh CLI onto
PATH there, and runs lh init + lh doctor for you. Safe to re-run.
C. Clone and work inside this repo directly
Use this when: you're contributing to the harness itself (fixing an agent, a skill, or lh).
git clone git@github.com:redsentech/lean-harness.git
cd lean-harness
npm install
npm link # puts `lh` on PATH globally, pointing at this checkout
2. Initialize and verify the environment
Inside your project (skip if the onboarding script already ran this):
lh init # first-run wizard; writes .agents/harness.config.json
lh doctor # confirms Node, git, Context7 key, verify commands, etc.
lh doctor should print all green checks. If it flags "no verify command configured", add a
test/build/lint command to .agents/harness.config.json — the Ralph loop uses it to decide
when a lane is actually done.
This creates a per-repo .agents/ footprint:
.agents/
harness.config.json
architecture.md # living ADR log
conventions.md # living project conventions
memory/INDEX.md # the only file auto-loaded every run
memory/{seed,failures,corrections,insights,conventions,quirks}.md
3. Run your first task
Open Copilot CLI or VS Code Copilot in the project and pick the entry point that matches the size of the change.
Full pipeline (new feature, non-trivial change). conductor is the single entry
point — it asks every design question itself, directly, in its own turn:
Use the conductor agent to build a rate limiter for the public API
If .agents/specs/<slug>/decisions.md is missing or incomplete, conductor asks its own
numbered questions right there (each with a recommended answer, a Why:, and a freeform
Other: option), then stops and waits for your real reply. It never guesses, infers, or
delegates the question to a subagent — subagent calls in Copilot CLI are stateless (they run
to completion and return one final result; they cannot pause mid-task for a live human reply)
— so you must answer before the pipeline proceeds.
How to invoke a custom agent (per the official docs):
@in Copilot CLI only mentions files, never agents. There are three ways:
/agent→ pickconductorfrom the list, then press Enter to confirm the selection before typing your build prompt (selecting and prompting are two separate steps).- Name it in your prompt —
Use the conductor agent to ...— Copilot infers which agent you mean.copilot --agent=NAME -p "..."— force a specific agent non-interactively.Agent name note: inside this repo (or any repo where the harness lives natively in
.github/agents), the bare nameconductorresolves. Once installed as a plugin into another project, Copilot CLI namespaces agents only — the resolvable name becomesredsen-lean-harness:conductor,redsen-lean-harness:architect, etc. Skills are never namespaced —/fast-track,/design,/build,/verify,/onboard, etc. work as plain slash commands regardless of install method.If
/agentdoesn't list it, or invoking it reports "not found": the plugin is stale. Runcopilot plugin update redsen-lean-harness(orcopilot plugin marketplace update redsen && copilot plugin update redsen-lean-harnessif that alone doesn't refresh it), then start a brand-newcopilotsession — an already-running session keeps the plugin snapshot it loaded at startup and won't pick up the update until restarted.
This runs the whole pipeline: conductor asks clarifying questions itself with recommended
answers (you must answer before it proceeds — this is a deliberate gate), then architect
writes the spec and acceptance criteria, splitter breaks it into lanes, builder/verifier
run the Ralph loop per lane (in parallel git worktrees when lanes don't overlap), integrator
merges sequentially, and scribe journals everything as it happens.
Small brownfield fix (skip spec + DAG ceremony):
/fast-track fix the off-by-one in pagination
Learn an unfamiliar codebase first:
/onboard
4. When do you need to type lh yourself?
Short answer: almost never during a normal pipeline run. Every agent's instructions
require it to call the relevant lh subcommand itself, at a specific point, every time —
you don't ask for it and you can't opt it out. The table below is exhaustive: every lh
subcommand, who calls it, and when.
| Command | Who runs it | When |
|---|---|---|
lh index |
conductor, scout, architect, splitter |
Automatically, before reading files, to build token-budgeted context |
lh host |
conductor |
Automatically, first thing, to pick parallel-vs-sequential strategy |
lh run start/event/end |
conductor (start/end), every agent (event) |
Automatically, for every phase transition — never skipped |
lh lane create/status/merge |
conductor, builder, integrator |
Automatically, before a write lane starts and when it merges |
lh memory get/put/scan |
conductor, architect, builder, scribe |
Automatically, to pull relevant shards before work and record facts/failures after |
lh graph |
verifier (always), plus architect/splitter/conductor/reviewer/scout/integrator at their own checkpoints |
Automatically — it's exit criterion #3, never skipped |
lh doctor |
conductor (first thing, before lh host), also you whenever you want to check the environment yourself |
Automatically at the start of every pipeline run — conductor's step 1 |
lh init --yes |
conductor, automatically, only if lh doctor reports config not initialised |
Self-heals a missing .agents/ baseline with non-interactive defaults, then re-runs lh doctor |
lh report <run-id> |
You | After a run, when you want a human-readable markdown summary instead of raw NDJSON. No agent generates this for you |
So in everyday use you don't have to type lh init or lh doctor by hand at all —
conductor runs lh doctor first, and if that reports the repo isn't initialised, it runs
lh init --yes for you (defaults, no prompts) and re-checks before doing anything else. It
still stops and reports the exact failing check if lh doctor finds something it can't
self-heal (for example no verify commands configured yet in a brand-new, empty repo).
lh init/lh doctor remain available for you to run by hand too — useful before starting
(to pre-flight a repo), after upgrading Node/git/the plugin, or to diagnose a stuck run outside
the agent flow. The only command with no agent equivalent at all is lh report (reading a past
run's summary). Everything else — lh index, lh host, lh run, lh lane, lh memory,
lh graph — is invoked by the agents as a scripted, mandatory step in their own instructions.
5. Know when it's actually done
A lane only completes when all five hold (otherwise it iterates, and escalates to you at the iteration cap):
- Every declared verify command exits 0
- Every acceptance criterion is individually checked off
lh graphpassesreviewerapproves- No files changed outside the lane's declared scope
6. Where things are written
Everything the harness does is self-documenting — nothing lives only in a chat transcript:
| What | Where |
|---|---|
| Design decisions | .agents/specs/<slug>/decisions.md |
| Spec + acceptance criteria | .agents/specs/<slug>/spec.md |
| Lane DAG | .agents/specs/<slug>/plan.dag.json |
| Run telemetry | .agents/runs/<id>/events.ndjson |
| Run journal | .agents/runs/<id>/journal.md |
| ADRs | .agents/architecture.md |
| Durable conventions | .agents/conventions.md |
| Cross-run memory | .agents/memory/*.md |
Troubleshooting
| Symptom | Fix |
|---|---|
lh doctor fails on Context7 |
export CONTEXT7_API_KEY=... in your shell, then re-run |
lh doctor warns "no verify command" |
Add a test/build/lint command to harness.config.json |
lh init refuses to run again |
Expected — it won't clobber an existing config. Use lh init --force to reset |
lh not found after onboarding |
Re-run without --no-npm-link, or invoke via the absolute path the script prints |
Agents/skills installed via copilot plugin install but lh init/lh doctor fail with "command not found" |
Expected — plugin install only adds the behaviour layer. Run npm link from a clone (path C) or scripts/onboard.mjs (path B) to get lh on PATH |
copilot plugin install owner/repo prints a deprecation warning |
Expected for direct-source installs. Use copilot plugin marketplace add + copilot plugin install name@marketplace instead (path A) |
npm install -g @redsentech/lean-harness gives 404/403 |
.npmrc isn't pointed at GitHub Packages, or the token lacks read:packages. Run node scripts/setup-npm-registry.mjs — see Generating a GitHub token if you don't have one yet |
setup-npm-registry.mjs doesn't open a browser (SSH/headless) |
Expected — it falls back to printing the token creation URL. Pass --no-open to skip the attempt entirely |
| Pipeline stuck at design gate | conductor is waiting on your answers — this is intentional, answer the questions |
Next steps
- Read the Pipeline and Agents sections in the README for the full mental model.
- Read the full
lhCLI flag reference for every subcommand. - Read ADR 0001 for why the harness is split the way it is.