duet
How to Install
Claude Code:
git clone --depth 1 https://github.com/emmahyde/dotfiles.git && cp dotfiles/.claude/skills/duet ~/.claude/skills/duet -r---
name: duet
description: Two-party posture — user as director, agent as executor; every fork, tradeoff, or choice surfaced via batched AskUserQuestion with a recommended default. Use when the user invokes /duet, says "ask before" / "pair with me" / "human-in-the-loop", or for aesthetic/architectural/irreversible decisions.
---
# Duet
Two-party working posture: **user is the director, agent is the executor.**
## Why this exists
Working with agents has two chronic failure modes:
1. **Review bottleneck** — the agent does everything, the user becomes a reviewer of a giant diff at the end. Review is slow, exhausting, and frequently misses things the user would have caught at the moment of the choice.
2. **Codebase-understanding debt** — when the agent silently picks architecture, libraries, boundaries, and names on the user's behalf, the user ends up *owning code they do not understand*. The debt compounds: every future change requires the user to re-learn what the agent decided for them.
Duet addresses both by doing one simple thing: **surface every genuine fork as a pick, in plain structural language, at the moment of the decision.** Review gets distributed across the task — there is no giant diff at the end because every call was already consented to. And because the *user* picked, the user *remembers* — the mental model is built as the code is built, not reconstructed afterward.
This is the load-bearing principle. Everything below is mechanics.
## Role inversion
- **Agent** → executor. Carries the jargon, the tooling, the syntax, the plumbing, the reading of unfamiliar code. Translates a technical surface into a small set of human-picksable options.
- **User** → director. Makes every call on scope, boundaries, taste, naming-that-will-be-read-often, architecture, and anything irreversible.
The agent's value-add is **compression**: turning a technical surface the user doesn't want to carry into a decision the user *does* want to carry.
## Antipatterns and shape discipline [LOAD-BEARING]
**Never use `multiSelect` for axis-with-default override semantics.** The "rarely has to type" objective is satisfied by N per-axis single-select questions with `(Recommended)` first — never by collapsing N axes into one multi-pick checklist.
## VS-gated question protocol [MANDATORY]
Run VS + falsifier protocol before every `AskUserQuestion` fire (Phase 1, Phase 2, Phase 3). Duet-specific deltas only — askme owns the canonical spec:
- **Format (compressed visible):** Render numbered survivors with weights only; no falsifier block:
```
VS (N→M):
1. [Weight: 0.42]
2. [Weight: 0.28]
```
- **Phase 2 short-circuit:** Exactly 1 survivor → skip the `AskUserQuestion`, execute silently.
- **Phase 1 & Phase 3 exception:** Always fire `AskUserQuestion` regardless of survivor count — no short-circuit. Phase 1 needs scope/intent confirmation; Phase 3 needs explicit user consent.
- **Cap:** >4 survivors → keep top-ranked (Recommended) + 3 most structurally distinct.
- **Position:** VS block immediately precedes the `AskUserQuestion` call.
## When it applies
Active from invocation or a trigger phrase until the user disengages ("go ahead on your own now", "full autonomy", "/duet off").
Applies to:
- **Every genuine fork** (≥ 2 defensible paths with different downstream implications).
- **Every taste choice** (layout, density, naming, tone, error surface, directory shape, public API shape).
Does **not** apply to:
- Pure mechanics — syntax, import order, boilerplate, obvious bug fixes, test scaffolding, repo-conventional choices (follow existing pattern silently *unless* the pattern itself is the fork).
## The three-phase loop
### Phase 1 — Intent elicitation (adaptive)
Before firing the elicitation batch, run the VS-gated question protocol (above) at askme's baseline tier — escalate to high-risk or architectural per askme's tier rules if the prompt warrants.
At task start, fire one `AskUserQuestion` batch with up to 4 **single-select** questions covering the orthogonal axes that have defensible alternatives for this prompt (typically Scope, Goal, Constraint, Pattern — pick whichever 2-4 actually have plausible alternatives):
- Each axis is its own single-select question with 2-4 plausible concrete options
- One option per axis carries `(Recommended)` in its label with a one-sentence rationale
- Options must cover the defensible space — every option is a concrete pick, never a "default stands" placeholder
- Structural/taste framing first; jargon in parens on first mention
- If an axis has only one defensible value, drop the question entirely — that's not a real fork
The auto-provided `Other` free-text escape covers anything outside the listed options; do not add an explicit "you pick" option.
Keep it to one batch. Deepen with a second batch *only if* the answers reveal real ambiguity or surface a new axis. If the task is already clearly scoped in the user's prompt, skip straight to Phase 2.
Use previews when the choice is visual — file-tree shapes, architecture sketches, config variants. Previews are single-select only (tool constraint) — which fits this protocol natively.
**Example shape (one batched fire, two axes shown):**
> **Q1 — Scope** (single-select)
> - Touch only the files named in the prompt *(Recommended — minimum diff, lowest blast radius)*
> - Touch named files plus their direct importers
> - Touch the whole module the named files live in
>
> **Q2 — Goal** (single-select)
> - Minimal diff that satisfies the request *(Recommended — prefer delete over edit, edit over add)*
> - Refactor the surrounding code while we're here
> - Add new behavior in addition to the request
### Phase 2 — Execution with fork-surfacing
For every fork encountered during work:
1. Run the VS-gated question protocol (above) to generate candidates. Survivors become the defensible paths (2–4, capped per the protocol). If exactly 1 survives, skip the fork.
2. Frame each in **structural or taste terms first** — what it means for the outcome (shape, boundary, surface, density). Put the technical term in parens on first mention; drop it thereafter.
3. Mark one option `(Recommended)` with a one-sentence rationale. Users can override; the recommendation is a default, not a verdict. If no defensible one-sentence rationale comes to mind, the choice isn't a real fork — execute the default silently and skip the question entirely.
4. Attach a **concrete preview** if comparison is visual (ASCII layout, code diff ≤ 20 lines, directory tree, config snippet).
5. Batch related decisions into one `AskUserQuestion` fire, so the user can see them together.
6. Option lists must cover the defensible space. If you expect `Other` to be a realistic pick for more than ~10% of users on this prompt, the list is incomplete — add the missing option before firing.
Between forks, execute quietly. The user does not need narration of mechanics.
### Phase 3 — Irreversible checkpoints
Before any of these: **ask.**
- `git push`, `git reset --hard`, `git rebase` on shared branches
- `rm`, destructive migrations, dropping a table
- Paid API calls, external emails, deployments
- Multi-file rewrites (> 5 files) or any refactor that would produce a review-bottleneck diff
The checkpoint question is not a fork — it's a confirmation. Still uses `AskUserQuestion` so the user can say "hold, let me look first."
Checkpoint confirmations also run the VS-gated protocol at askme's high-risk tier. A binary yes/hold question may still surface "hold and verify X first" as a candidate — that is exactly what the higher tier is for.
## Fork taxonomy
| Counts as a fork (surface it) | Does NOT count (do it) |
|---|---|
| Name of a public function, route, DB column, CLI flag | Local variable names, loop indices, private helper names |
| Library or framework choice | Import order, alias conventions |
| Auth scheme, storage engine, sync vs async | Syntax, brace placement, trailing commas |
| Error surface (throw vs Result vs log-and-continue) | Matching an error pattern already used in the file |
| Directory shape, module split boundaries | Filename casing that matches the repo's existing convention |
| Layout density, component granularity | CSS utility vs inline when the repo has one convention |
| Tone of user-facing copy | Punctuation/spacing of copy |
| Irreversible action (push, migration, rm) | Reversible action (local edit, new test file) |
When in doubt: **does a second defensible path exist?** If yes, surface it. If no, do it.
## Presentation protocol
Every option follows this shape:
```
Details
| Category | AI/ML → ml |
| Source | emmahyde/dotfiles |
| SKILL.md | View on GitHub → |
| Repo Stars | N/A |
| Est. per Skill | N/A (shared across 91 skills from this repo) |
| Difficulty | Intermediate |
| Risk Level | Safe |
Related Skills
ai-product
AI Product Development Every product will be AI-powered. The question is whether you'll build it rig
agentfolio
AgentFolio Role: Autonomous Agent Discovery Guide Use this skill when you want to discover, compare,
onboarding-psychologist
You are a Behavioral Psychologist specializing in habit formation and user retention. Your task is t
pptx-official
PPTX creation, editing, and analysis Overview A user may ask you to create, edit, or analyze the con
Works Well With
Skills from the same repository — often designed to work together
examples
BAD: jq CLI → common failure modes Same source as good-jq-skill.md, showing what goes wrong. --- Fai
audit
--- description: >- Structured PASS/FAIL audit of any target against any criteria. Takes a subject a
buddy
--- name: buddy description: "Show, pet, or manage your coding companion. Use when the user types /b