diff --git a/README.md b/README.md index f1117cf..dd2dbdf 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,10 @@ A skill is a folder with a `SKILL.md` describing a task in enough detail that an | [`fix-pr-comments`](skills/fix-pr-comments) | Fetches review comments from a GitHub PR, triages them, and fixes each one test-first — write a failing test capturing the reviewer's concern, make it pass, then resolve the thread. Handles skip-reason replies for feedback you're not taking. | | [`write-a-pitch`](skills/write-a-pitch) | Collaborates with you on a [Shape Up](https://basecamp.com/shapeup) pitch — problem, appetite, solution, rabbit holes, no-gos. Explores your codebase so the pitch is grounded in real code, and aims for a pitch complete enough that an agent could generate a spec from it. | | [`chip-handoff`](skills/chip-handoff) | Summarizes the current conversation and hands it to a fresh session as a clickable task chip, rather than writing a handoff file you have to shuttle around yourself. | +| [`second-opinion`](skills/second-opinion) | Sends your whole session, verbatim, to a different agent CLI — Codex, Cursor, or Claude Code — and reports its answer back unedited alongside where it disagrees. The transcript goes over as-is rather than as a summary, so the other model can reject the framing rather than just pick between the options you already settled on. | | [`writing-tighten`](skills/writing-tighten) | Checks a draft against nine prose rules — kill the warm-up, cut 10%, no adverbs, active voice, concrete over abstract — one pass per rule. Reports what each pass found and applies only the fixes you pick, so the edit stays yours. Command-only; it won't fire on its own. | -`fix-pr-comments` needs the [`gh`](https://cli.github.com) CLI. `chip-handoff` is the one skill here that isn't portable — it depends on the `spawn_task` tool, which only exists in the Claude Code desktop app. +`fix-pr-comments` needs the [`gh`](https://cli.github.com) CLI. `second-opinion` needs at least one other agent CLI installed (`codex`, `cursor-agent`, or `claude`) and `jq` to extract the transcript; it sends the session to another vendor, so read the privacy note in its `SKILL.md` before using it on anything sensitive. `chip-handoff` is the one skill here that isn't portable — it depends on the `spawn_task` tool, which only exists in the Claude Code desktop app. `writing-tighten`'s rules are adapted from Kaguura Gichuru's [20,585 New Subscribers in 90 Days](https://kaguura.substack.com/p/90-days-20585-new-subscribers-heres). The essay-structure and audience-growth advice in that piece was left out — this is only the repeatable prose rules. diff --git a/skills/second-opinion/SKILL.md b/skills/second-opinion/SKILL.md new file mode 100644 index 0000000..b15d27d --- /dev/null +++ b/skills/second-opinion/SKILL.md @@ -0,0 +1,41 @@ +--- +name: second-opinion +description: Ask a different AI and read its take. +disable-model-invocation: true +argument-hint: "[harness] [model] [effort] — e.g. codex gpt-5.6-sol high" +--- + +# Second opinion + +Put a question to a **different harness** — a different model — and bring back its take. Copy-paste your session into it as is, no changes. + +## 1. Export the transcript + +Dump this session's conversation to `.scratch/second-opinion/.transcript.md`, `` naming the question (outside a repo, use a temp file). See [`transcripts.md`](transcripts.md) for the extraction recipe for the harness you're running in. + +Close with a rule and the live question in full, then: *and challenge any claim above you think is wrong*. It's the last thing read, and it has to outrank everything above it — a bare "Answer Q2" doesn't. Disagreement comes for free, but a pinned question keeps the other harness inside the frame; that clause is what buys back the licence to attack it. + +The transcript ships everything it contains — command output, file contents, whatever your tool calls returned — to another vendor's CLI. If anything in this session shouldn't travel, say so and let the user decide before you send. + +**Done when:** the file reads as the conversation, in order, including the recommendations you gave along the way. + +## 2. Ask the other harness + +The invocation takes `[harness] [model] [effort]`, each optional. For what wasn't given, ask the user which harness — naming the ones installed here other than the one you're running in — and let the CLI use its own default model and effort. + +Run it read-only from the repo root, feed the transcript in as the prompt, and capture the answer to `.answer.md`. Background it; these take minutes. + +## 3. Report the divergence + +Give the user, in order: + +1. **The answer, verbatim** — the whole of what came back, copied through unedited. +2. **Compare** — the specific claim, weighting, and assumptions. + +Check any repo fact it asserts that you hadn't, and say what you found. + +Hold both takes open. + +## 4. Resume + +Return to the grilling question and wait for the user's answer. diff --git a/skills/second-opinion/transcripts.md b/skills/second-opinion/transcripts.md new file mode 100644 index 0000000..6731f44 --- /dev/null +++ b/skills/second-opinion/transcripts.md @@ -0,0 +1,39 @@ +# Exporting the current session's transcript + +Each harness persists its own sessions locally. Use the recipe for the one you're running in. + +Keep assistant and user text; reduce tool calls to a one-line marker so the reader can see where legwork happened without drowning in tool output. + +Drop skill bodies. They arrive as user messages but they're instructions to *this* agent, not conversation — and the other harness will read them as its own. Left in, a skill's closing line ("ask the user which harness") outranks your appended question, and the answer comes back addressed to that instead. + +## Claude Code + +Sessions live in `~/.claude/projects//.jsonl`, where `` is the working directory with every `/` and `.` replaced by `-`. The current session is the most recently modified file there. + +```bash +SLUG=$(pwd | sed 's/[/.]/-/g') +SESSION=$(ls -t ~/.claude/projects/"$SLUG"/*.jsonl | head -1) +jq -r ' + select(.type=="user" or .type=="assistant") | select(.isSidechain|not) + | (.message.role // .type) as $role + | ((.message.content // []) | if type=="string" then [{type:"text",text:.}] else . end) + | map(if .type=="text" then .text + elif .type=="tool_use" then "[tool: " + .name + "]" + else empty end) | join("\n") + | select(length>0) + | select(test("^Base directory for this skill:|")|not) + | "\n## " + $role + "\n\n" + . +' "$SESSION" > .scratch/second-opinion/.transcript.md +``` + +## Codex + +Sessions live under `~/.codex/sessions////`, most recent last. Same JSONL shape in outline — inspect one line first and adjust the filter to the keys you find. + +## Cursor + +Chats live under `~/.cursor/chats/`. Inspect the store before writing a filter; the layout differs from the JSONL harnesses. + +## If extraction fails + +Don't reconstruct the conversation from memory — a remembered transcript is a summary, and a summary is the briefing this skill exists to avoid. Tell the user extraction failed, and ask them to paste the conversation into a file instead.