Side Quest
A thought that arrives mid-flow has two bad exits: chase it (lose the thread) or
suppress it (and risk losing it or returning to it repeatedly). This skill
builds the third exit: park it in one line, keep working, and collect the
finished work at your next natural break.
The trust contract, before any mechanics: a parked thought can never be
silently lost, and a completion mark can never lie. The moment either breaks
once, the user's mind stops releasing thoughts and the tool is dead. Every rule
below serves that contract; when in doubt, protect the contract, not the feature.
Step 1 — Capture and triage (≤5 seconds of the user's attention)
Explicit markers fire immediately, no questions: sq: / side quest: /
background this / park this / not now but: / 支线 / 先别进主线 / 后台弄.
Inferred phrasings ("btw can you also…", "哦对了那个…回头弄", "…anyway keep
going") get ONE line —
"→ background as a side quest? (default: handle it now in-thread)" — and
ambiguity resolves to the main thread. Capture never asks a second question.
Before dispatching, triage the thought — most "side quests" are something else:
| Shape |
Tell |
Route |
| Ten-second question |
You can answer confidently in one short line |
Answer inline in brackets, no dispatch, no file — ceremony here is self-parody |
| Blocking prerequisite |
"first / before we continue / 先" or it references the artifact being edited; the main task's next step depends on the answer |
Stays in the main thread — backgrounding it means the main line proceeds on an unverified assumption |
| Backfill quest |
The answer feeds a pending main-thread decision |
Dispatch, but declare: "conclusion (≤3 lines) will return to this thread; details to inbox" — a vetoable default, not a question |
| Reminder |
There is no work product, only a time ("submit readings tomorrow 10am") |
Route to the scheduler/reminders if available; receipt says "reminder set, not a task". Never manufacture fake work for it; no time given → default 'before end of day' and say so in the receipt; no scheduler available → ledger it as 'reminder — NOT scheduled, recorded only' and hand the text back |
| Life-size decision |
"should I kill project X" |
Receipt: "that's a decision, not a task — it deserves its own conversation." A background agent must not settle it from one sentence; if the user asked to park it (先别打断), capture and queue it — do not open the discussion now |
| Resident job |
It changes ground the main session stands on (its config, rules, deps, git state) |
Never execute live. Deliver a diff/plan to the inbox, to be applied at a session boundary |
| Quest about the main line itself |
"sq: check whether our current approach is over-engineered" |
Surface it: "this questions the current approach — discuss now, or truly background?" (the one place a question is allowed, and it happens pre-dispatch, in the main window) |
| Deprioritization |
"这个先放一边 / let's park this topic" with NO work requested — there is nothing to deliver |
Verbal ack only; no dispatch, no ledger entry |
| Quest about this conversation |
"sq: summarize what we did" — the object is the transcript itself, which side agents never receive |
Cannot background; run inline at the next boundary (defer to conclude-rounds if installed) |
| Actionable with side effects |
"email X / open a PR / file the ticket" |
Dispatch as DRAFT-only — the deliverable is the loaded gun, never the fired shot |
| True side quest |
≥2 minutes of independent work, no main-thread dependency, no side effects |
Dispatch (below) |
Multiple quests in one message ("sq×3: …") = one merged ledger entry set, one
combined confirmation line.
Step 2 — Ledger first (write-ahead; the non-negotiable)
BEFORE spawning anything, append to the inbox's _INBOX.md:
| date-time | user's words, VERBATIM | brief (1 line) | state |
States: captured → dispatched → done | failed | partial | queued. Every
terminal state produces a receipt. If a session dies, orphaned dispatched
entries are announced the next time this skill loads (any sq marker, "sq list",
or an inbox mention) — after reconciling with the inbox first: inspect any deliverable against the stored brief and check available agent status.
A file alone may be a partial write: mark done only when its content and completion
evidence satisfy the brief; otherwise preserve it as partial or keep a live dispatch
running. If agent status is unavailable, record that uncertainty before retrying.
Announcing a false failure breaks the same contract as silence. A quest may never end without a
durable trace. The verbatim words are sacred: never retitle the
user's thought; they find it by their own words, not by your summary.
Step 3 — The brief (curated context, not zero context)
The laziest real utterances are deictic — "this pattern", "that chart lib",
"刚才第三段". A background agent given only the raw words will guess, and
confidently. So the MAIN agent — the one holding the conversation — pays the
serialization cost, never the user:
- Resolve every pronoun and reference into a self-contained brief, ≤5 lines:
the thought itself, what it refers to (named explicitly), what the user was
doing, and the expected shape of the deliverable.
- For repo/code quests, add a static environment fingerprint (≤10 lines:
cwd, branch, stack facts from the project's own docs). Environment facts are
not contamination; conversation history is. The side agent receives the brief
and fingerprint ONLY — never the transcript.
- The confirmation line echoes the brief's one-line reading, not the raw words —
echo-as-verification, no question asked:
⚡ sq #4 "check webhook retry dedup (billing service, src/hooks)" — say "撤"/"cancel" to pull it back.
Folder names, file names, and ALL receipt/confirmation templates follow the
conversation's language (the cancel word too: 撤 for Chinese, cancel for
English).
sq (isolated): … forces a zero-brief dispatch for the rare quest the user
wants fully sealed.
If the reference cannot be resolved from context, do NOT ask — ledger it with
the note "context insufficient; interpreted literally" and dispatch the literal
reading. A wrong draft plus an honest note beats an interrogation.
Step 4 — Execution rules (for the side agent)
Rule transport: the side agent never reads this file — every dispatch
prompt embeds Step 4's rules verbatim beneath the brief. A rule not in the
prompt does not exist for the side agent.
- Draft-only, iron rule. No sends, no publishes, no PRs/issues, no installs
into shared environments, no purchases, no deletions — anywhere, ever. An
actionable quest ships as a draft whose first line is
DRAFT — NOT SENT / NOT APPLIED. The trigger word requests relief, not authority.
- Workspace law. Never touch the user's working tree, git state, config, or
anything the main session stands on. Repo quests run in a fresh
git worktree
(placed under ~/side-quests/worktrees/<slug>, never inside the user's repo)
from a clean ref; the deliverable is a branch name plus one merge command.
Writes are permitted only inside the inbox directory and the quest worktree.
- Assume forward, assumptions on top. No questions back — make the call,
and open the deliverable with an ASSUMPTIONS block (≤5, each with "if wrong →
discard section N"). When confidence is genuinely low, ship two small
versions or an honest partial — never dress a guess as a completion.
- Output is proportional to input. A two-word quest gets at most one page.
No unrequested expansions; over-delivery raises the cost of opening the inbox,
and an unopened inbox kills the tool.
- Run cheap and polite. Default to a lighter model/effort than the main
thread; at most 2 quests run concurrently (others wait as
queued); side
quests must never starve the main session's rate limits — the first dispatch
each session notes once: "runs in background — shares your usage limits."
Step 5 — Receipts (buffered, honest, verdict-bearing)
- Dispatch confirmation: one fixed-format line, immediately (Step 3's echo).
- Completion/failure receipts never interrupt: they queue silently and
attach to the next natural boundary — the assistant's next reply after the
user speaks. Never mid-generation, never as a standalone ping. If the
harness forces a render turn when a background result arrives, output
nothing beyond a minimal one-line ack.
- A receipt carries: the user's verbatim words, a one-line verdict, and the
highest-risk assumption:
✅ sq "stripe retries dedup?" — yes, dedupes on event_id (webhook.ts:41); assumed billing-service repo. Note in inbox.
Answer-shaped quests (yes/no, a number, a flag) are CLOSED by the receipt
line itself; the file is optional.
- Failures are receipts too:
⚠️ sq "X" failed (rate limit) — your words are safe in _INBOX.md; say "sq retry" to redispatch.
sq list shows the queue with states; sq kill <n> cancels; sq redo "<X>": <correction> redispatches with the stored brief plus the correction — no
re-explaining.
Step 6 — Inbox and resurfacing (anti-graveyard)
- Default location
~/side-quests/ — never colonize the Desktop uninvited; the
user may configure any folder (stored in ~/side-quests/config.md). Folder
names, file names, and ALL receipt/confirmation templates follow the
conversation's language (the cancel word too: 撤 for Chinese, cancel for
English).
- Files are named
YYMMDD--<slug of the user's verbatim words>.md, never
agent-invented titles, never bare timestamps.
- Deliverables always land inside the inbox (a
staging/ subfolder for files
meant to move elsewhere); the receipt includes the one-line move command —
writing to user-specified locations outside the inbox stays with the user or
the main thread.
- Deliverable header, fixed: verbatim words · captured-at + what the main
thread was · TL;DR ≤3 lines · ASSUMPTIONS · suggested next step. The reader
decides in one screen whether to read on.
_INBOX.md is the living index (date | words | state | three-word result |
file). At the skill's next load in a new session — a natural boundary, not
an interruption — if
unread results exist, print a quiet one-line-per-item digest with ages, plus
"say 'archive all' to clear". No unread counters mid-session, no guilt
language, no reminders that interrupt work: the inbox must be there when the
user wants it, never demand attention for itself.
- Results untouched for 7 days move silently to
archive/ (marked in the
index, never deleted). The pile must not be able to grow into a reproach.
Degraded environments
- No background-agent capability (some engines/harnesses): capture, triage,
ledger, and brief still run in full — they are the product's core. The quest
sits as
queued; offer "run it inline at your next break, or leave it
queued". Never pretend it is running.
- No disk access: emit the ledger line and brief as a copyable block and
say where to save it. Never drop a thought silently.
Boundaries
- The dispatch turn belongs to the main thread: acknowledge in one line and
continue the user's actual work — never let parking a thought become the
interruption it exists to prevent.
- This skill is not a scheduler, not a to-do app, and not a way to launder
irreversible actions through a background agent.
- If the completion mark's honesty ever conflicts with looking productive,
honesty wins. A trustworthy ledger of unfinished quests beats a gallery of
confident garbage.
1---2name: side-quest3description: Park a mid-flow thought without breaking your main thread — capture it in one line, a background agent works it while you keep going, and results land in an inbox outside the chat, keeping main context clean both ways. Ledger-first (a parked thought can never be silently lost), draft-only (side agents never send, commit, or touch your working tree), receipts carry a one-line verdict. Fires without confirmation on explicit markers — "sq:", "side quest:", "background this", "park this", "not now but:", 支线 / 先别进主线 / 后台弄 — and on queue check-ins ("sq list", "sq retry", "sq kill", "what came back from my side quests?"). Inferred phrasings get a one-line confirm, defaulting to the main thread. NOT for blocking prerequisites the main task needs next, NOT for ten-second questions (answered inline), NOT for reminders (routed to a scheduler, never faked as work), NOT for merely setting a topic aside with no work attached (这个先放一边), NOT a way to send or do anything irreversible.4---56# Side Quest78A thought that arrives mid-flow has two bad exits: chase it (lose the thread) or9suppress it (and risk losing it or returning to it repeatedly). This skill10builds the third exit: park it in one line, keep working, and collect the11finished work at your next natural break.1213**The trust contract, before any mechanics:** a parked thought can never be14silently lost, and a completion mark can never lie. The moment either breaks15once, the user's mind stops releasing thoughts and the tool is dead. Every rule16below serves that contract; when in doubt, protect the contract, not the feature.1718## Step 1 — Capture and triage (≤5 seconds of the user's attention)1920Explicit markers fire immediately, no questions: `sq:` / `side quest:` /21`background this` / `park this` / `not now but:` / 支线 / 先别进主线 / 后台弄.22Inferred phrasings ("btw can you also…", "哦对了那个…回头弄", "…anyway keep23going") get ONE line —24"→ background as a side quest? (default: handle it now in-thread)" — and25ambiguity resolves to the main thread. Capture never asks a second question.2627Before dispatching, triage the thought — most "side quests" are something else:2829| Shape | Tell | Route |30|---|---|---|31| Ten-second question | You can answer confidently in one short line | Answer inline in brackets, no dispatch, no file — ceremony here is self-parody |32| Blocking prerequisite | "first / before we continue / 先" or it references the artifact being edited; the main task's next step depends on the answer | Stays in the main thread — backgrounding it means the main line proceeds on an unverified assumption |33| Backfill quest | The answer feeds a pending main-thread decision | Dispatch, but declare: "conclusion (≤3 lines) will return to this thread; details to inbox" — a vetoable default, not a question |34| Reminder | There is no work product, only a time ("submit readings tomorrow 10am") | Route to the scheduler/reminders if available; receipt says "reminder set, not a task". Never manufacture fake work for it; no time given → default 'before end of day' and say so in the receipt; no scheduler available → ledger it as 'reminder — NOT scheduled, recorded only' and hand the text back |35| Life-size decision | "should I kill project X" | Receipt: "that's a decision, not a task — it deserves its own conversation." A background agent must not settle it from one sentence; if the user asked to park it (先别打断), capture and queue it — do not open the discussion now |36| Resident job | It changes ground the main session stands on (its config, rules, deps, git state) | Never execute live. Deliver a diff/plan to the inbox, to be applied at a session boundary |37| Quest about the main line itself | "sq: check whether our current approach is over-engineered" | Surface it: "this questions the current approach — discuss now, or truly background?" (the one place a question is allowed, and it happens pre-dispatch, in the main window) |38| Deprioritization | "这个先放一边 / let's park this topic" with NO work requested — there is nothing to deliver | Verbal ack only; no dispatch, no ledger entry |39| Quest about this conversation | "sq: summarize what we did" — the object is the transcript itself, which side agents never receive | Cannot background; run inline at the next boundary (defer to conclude-rounds if installed) |40| Actionable with side effects | "email X / open a PR / file the ticket" | Dispatch as DRAFT-only — the deliverable is the loaded gun, never the fired shot |41| True side quest | ≥2 minutes of independent work, no main-thread dependency, no side effects | Dispatch (below) |4243Multiple quests in one message ("sq×3: …") = one merged ledger entry set, one44combined confirmation line.4546## Step 2 — Ledger first (write-ahead; the non-negotiable)4748BEFORE spawning anything, append to the inbox's `_INBOX.md`:4950```51| date-time | user's words, VERBATIM | brief (1 line) | state |52```5354States: `captured → dispatched → done | failed | partial | queued`. Every55terminal state produces a receipt. If a session dies, orphaned `dispatched`56entries are announced the next time this skill loads (any sq marker, "sq list",57or an inbox mention) — after reconciling with the inbox first: inspect any deliverable against the stored brief and check available agent status.58A file alone may be a partial write: mark done only when its content and completion59evidence satisfy the brief; otherwise preserve it as partial or keep a live dispatch60running. If agent status is unavailable, record that uncertainty before retrying.61Announcing a false failure breaks the same contract as silence. A quest may never end without a62durable trace. The verbatim words are sacred: never retitle the63user's thought; they find it by their own words, not by your summary.6465## Step 3 — The brief (curated context, not zero context)6667The laziest real utterances are deictic — "this pattern", "that chart lib",68"刚才第三段". A background agent given only the raw words will guess, and69confidently. So the MAIN agent — the one holding the conversation — pays the70serialization cost, never the user:7172- Resolve every pronoun and reference into a **self-contained brief, ≤5 lines**:73 the thought itself, what it refers to (named explicitly), what the user was74 doing, and the expected shape of the deliverable.75- For repo/code quests, add a **static environment fingerprint** (≤10 lines:76 cwd, branch, stack facts from the project's own docs). Environment facts are77 not contamination; conversation history is. The side agent receives the brief78 and fingerprint ONLY — never the transcript.79- The confirmation line echoes the brief's one-line reading, not the raw words —80 echo-as-verification, no question asked: `⚡ sq #4 "check webhook retry81 dedup (billing service, src/hooks)" — say "撤"/"cancel" to pull it back.`82 Folder names, file names, and ALL receipt/confirmation templates follow the83 conversation's language (the cancel word too: 撤 for Chinese, cancel for84 English).85- `sq (isolated): …` forces a zero-brief dispatch for the rare quest the user86 wants fully sealed.8788If the reference cannot be resolved from context, do NOT ask — ledger it with89the note "context insufficient; interpreted literally" and dispatch the literal90reading. A wrong draft plus an honest note beats an interrogation.9192## Step 4 — Execution rules (for the side agent)9394**Rule transport:** the side agent never reads this file — every dispatch95prompt embeds Step 4's rules verbatim beneath the brief. A rule not in the96prompt does not exist for the side agent.9798- **Draft-only, iron rule.** No sends, no publishes, no PRs/issues, no installs99 into shared environments, no purchases, no deletions — anywhere, ever. An100 actionable quest ships as a draft whose first line is `DRAFT — NOT SENT / NOT101 APPLIED`. The trigger word requests relief, not authority.102- **Workspace law.** Never touch the user's working tree, git state, config, or103 anything the main session stands on. Repo quests run in a fresh `git worktree`104 (placed under `~/side-quests/worktrees/<slug>`, never inside the user's repo)105 from a clean ref; the deliverable is a branch name plus one merge command.106 Writes are permitted only inside the inbox directory and the quest worktree.107- **Assume forward, assumptions on top.** No questions back — make the call,108 and open the deliverable with an ASSUMPTIONS block (≤5, each with "if wrong →109 discard section N"). When confidence is genuinely low, ship two small110 versions or an honest partial — never dress a guess as a completion.111- **Output is proportional to input.** A two-word quest gets at most one page.112 No unrequested expansions; over-delivery raises the cost of opening the inbox,113 and an unopened inbox kills the tool.114- **Run cheap and polite.** Default to a lighter model/effort than the main115 thread; at most 2 quests run concurrently (others wait as `queued`); side116 quests must never starve the main session's rate limits — the first dispatch117 each session notes once: "runs in background — shares your usage limits."118119## Step 5 — Receipts (buffered, honest, verdict-bearing)120121- Dispatch confirmation: one fixed-format line, immediately (Step 3's echo).122- Completion/failure receipts **never interrupt**: they queue silently and123 attach to the next natural boundary — the assistant's next reply after the124 user speaks. Never mid-generation, never as a standalone ping. If the125 harness forces a render turn when a background result arrives, output126 nothing beyond a minimal one-line ack.127- A receipt carries: the user's verbatim words, a **one-line verdict**, and the128 highest-risk assumption:129 `✅ sq "stripe retries dedup?" — yes, dedupes on event_id (webhook.ts:41);130 assumed billing-service repo. Note in inbox.`131 Answer-shaped quests (yes/no, a number, a flag) are CLOSED by the receipt132 line itself; the file is optional.133- Failures are receipts too: `⚠️ sq "X" failed (rate limit) — your words are134 safe in _INBOX.md; say "sq retry" to redispatch.`135- `sq list` shows the queue with states; `sq kill <n>` cancels; `sq redo "<X>":136 <correction>` redispatches with the stored brief plus the correction — no137 re-explaining.138139## Step 6 — Inbox and resurfacing (anti-graveyard)140141- Default location `~/side-quests/` — never colonize the Desktop uninvited; the142 user may configure any folder (stored in `~/side-quests/config.md`). Folder143 names, file names, and ALL receipt/confirmation templates follow the144 conversation's language (the cancel word too: 撤 for Chinese, cancel for145 English).146- Files are named `YYMMDD--<slug of the user's verbatim words>.md`, never147 agent-invented titles, never bare timestamps.148- Deliverables always land inside the inbox (a `staging/` subfolder for files149 meant to move elsewhere); the receipt includes the one-line move command —150 writing to user-specified locations outside the inbox stays with the user or151 the main thread.152- Deliverable header, fixed: verbatim words · captured-at + what the main153 thread was · TL;DR ≤3 lines · ASSUMPTIONS · suggested next step. The reader154 decides in one screen whether to read on.155- `_INBOX.md` is the living index (date | words | state | three-word result |156 file). At the skill's next load in a new session — a natural boundary, not157 an interruption — if158 unread results exist, print a quiet one-line-per-item digest with ages, plus159 "say 'archive all' to clear". No unread counters mid-session, no guilt160 language, no reminders that interrupt work: the inbox must be there when the161 user wants it, never demand attention for itself.162- Results untouched for 7 days move silently to `archive/` (marked in the163 index, never deleted). The pile must not be able to grow into a reproach.164165## Degraded environments166167- **No background-agent capability** (some engines/harnesses): capture, triage,168 ledger, and brief still run in full — they are the product's core. The quest169 sits as `queued`; offer "run it inline at your next break, or leave it170 queued". Never pretend it is running.171- **No disk access**: emit the ledger line and brief as a copyable block and172 say where to save it. Never drop a thought silently.173174## Boundaries175176- The dispatch turn belongs to the main thread: acknowledge in one line and177 continue the user's actual work — never let parking a thought become the178 interruption it exists to prevent.179- This skill is not a scheduler, not a to-do app, and not a way to launder180 irreversible actions through a background agent.181- If the completion mark's honesty ever conflicts with looking productive,182 honesty wins. A trustworthy ledger of unfinished quests beats a gallery of183 confident garbage.