scry
Breaks down huge projects into smaller decision tickets on GitHub so you can solve them one at a time.
Installation
Paste this into Claude Code, Cursor, or any agent that can run commands.
SKILL.mdShow the author's original SKILL.md
--- name: scry description: "Plan a chunk of work too big for one agent session as a shared map of decision tickets on GitHub, and resolve them one at a time. Use when asked to scry, wayfinder, chart a map, walk a map, take the next ticket on the map, or /scry." argument-hint: "[loose idea | map number | ticket number | issue URL] [you-pick]" disable-model-invocation: true --- <!-- BEGIN MANA PERSONA --> ## Persona at invocation Before conversational narration, read `Persona:` and `Style:` in the active project's `## Agent skills` block from `CLAUDE.md` or `AGENTS.md`. Prefer the file containing the block, then an existing file; ties use `CLAUDE.md`. A symlink pair is one file. Read the saved value anew on each invocation, including from a subdirectory using the project root. No accessible project or no line means ordinary behavior. Do not search another project or global settings for this preference. During the `Persona at invocation` stage, `archmage` on either line loads this skill's own [references/archmage.md](references/archmage.md) for the active workflow. `off` or an absent value leaves ordinary behavior active. An unknown value leaves ordinary behavior active and gets a brief explanation when conversational output is allowed; it does not stop the work. Explicit conversation instructions override the saved voice without writing settings. A request to enable Archmage for this workflow also loads the local reference. Apply the voice only to lead-agent conversation. Deliverables, specialist roles, reply-only responses, and JSON-only output retain their contracts, with no added narration. End the persona with this workflow unless the user requests otherwise or a `Style:` line names `archmage`, which keeps the voice on for the whole session. <!-- END MANA PERSONA --> # Scry Honor the user's explicit instructions and decisions already made in this conversation over this skill's workflow defaults. A rule this file states with never, or as read-only, is a gate: it holds whatever the conversation says, and an instruction to cross one is declined and reported. Continue authorized work; ask only about unresolved choices that would materially change the result. Preparing or reviewing work does not authorize publishing it. If a skill rule requires a pause or leaves requested work unfinished, name and link to the exact SKILL.md and quote the rule. Then explain what decision or prerequisite is missing. Distinguish a required gate from your interpretation. A loose idea has arrived, too big for one session. The way to the destination is still fog. This skill charts that way as a shared map on GitHub, then works **decision tickets** (questions whose answer is a decision) one at a time until the route is clear. The destination is named first. It might be a spec, a locked decision, or a change made in place. Name it, because every ticket hangs off it. ## Operating principles - **Decisions, then delivery.** Each ticket resolves a question. The map is done when nothing is left to decide before someone goes and builds. The pull to start building is the signal the map is finished. An effort can override this in its Notes. - **One ticket per session**, except research tickets created while charting, which resolve in parallel in that same session. - **Refer by name.** Every map and ticket is an issue with a title. In anything the human reads, use that title. Wrap the link inside the name. A wall of `#42, #43` is illegible. - **Claim before work.** Assign the ticket to the person driving this session first, so a parallel session skips it. An open unassigned ticket is unclaimed. - **The map is an index.** A decision lives on its ticket. The map gists it and links. It does not restate the answer. `<SKILL_DIR>` is the absolute directory this SKILL.md lives in. Substitute the real path every time it appears. Do not assign it to a shell variable first: a sandboxed or worktree-isolated session refuses `bash "$VAR/script.sh"` because it cannot resolve the path to read the script. ## Arguments Parse tokens, then treat the remainder as the idea, number, or URL. | Token | Effect | |-------|--------| | `you-pick` | On interrogation rounds, accept every recommended answer. Same meaning as the user saying "make the decisions" or "you pick". | **No number or URL (a loose idea).** Chart a new map. **A number or issue URL.** Load that issue. - Label `scry:map`: walk that map. - Label `scry:research`, `scry:prototype`, `scry:interrogation`, or `scry:task`: walk its parent map and claim this ticket. Treat the legacy label `scry:grilling` as `scry:interrogation` when resuming existing tickets. - The same labels under the older `wayfinder:` prefix mean the same thing. Walk them as they are; do not relabel. - Any other issue: chart a new map whose destination is informed by that issue. ## Execution spine 1. Resolve the tracker (Stage 1). 2. Decide chart vs walk from the arguments (above). 3. Chart: Stage 2, then stop. Walking tickets is a later session. 4. Walk: Stage 3. Check for an already finished map, or resolve one ticket and file new fog. Check closeout before stopping. --- ## Stage 1: Tracker If `docs/agents/issue-tracker.md` exists, read it. Its `Tracker:` line names the tracker. On `github`, follow its "Wayfinding operations" section for any mechanic it specifies (extra labels, owning docs, parent-link fallbacks) and continue below. On any other tracker, that section replaces `map.sh` entirely: it says what a map, a ticket, a blocking edge, a claim, and a resolution are there, and which connector or API to use. Follow it for every operation in Stage 2 and Stage 3, keep the same map body and ticket shapes from `references/map-shape.md`, and skip the rest of this stage. When it says maps are not supported, read `references/scratch.md` and keep the map under `.scratch/`. Missing file: GitHub via `gh`, using the operations in `references/github-ops.md`. Load `references/github-ops.md` now. `scripts/map.sh` is the only way to create issues, attach children, wire blocks, query the frontier, and claim. Do not improvise those `gh` calls. Confirm the host with `gh repo view`. If that fails, stop. Pass `GH_HOST=<host>` inline on every `map.sh` invocation. Derive the host from `gh repo view --json url --jq .url`, or from the issue URL if one was passed. Shell state does not persist between Bash calls. On `github.com` the prefix can be dropped. Ensure labels exist once per session: ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" ensure-labels ``` Exit 3 from the script means this token cannot write issues (usually HTTP 403). Read `references/scratch.md` and follow it. Do not keep retrying `gh issue create`. --- ## Stage 2: Chart Load `references/map-shape.md`, `references/interrogate.md`, and `references/domain.md`. ### 2a. Name the destination Interrogate the goal until the destination is a sentence or two: the spec, decision, or in-place change this map is finding its way to. Update `CONTEXT.md` and ADRs as terms land. The destination fixes the scope. Work past it belongs in Out of scope on the map, never in the ticket list. ### 2b. Map the frontier Interrogate the open decisions, breadth-first this time: fan across the space rather than deep on one thread. Surface the open decisions and the first steps takeable now. If this surfaces no fog (the way is already clear, and the whole journey fits one session), you do not need a map. Stop and ask how they want to proceed. ### 2c. Write the map Create the map issue, label `scry:map`. Destination and Notes filled in. Decisions so far empty. Fog sketched into **Not yet specified**. ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" create-map "Map: <destination in a few words>" <<'EOF' <body from references/map-shape.md> EOF ``` Notes record: domain; files every session should read; standing preferences; any owning doc that later resolutions should update (a decision log, a spec). ### 2d. File the tickets you can specify A ticket is ready to file when you can state its **Question** precisely. Sharpness of the question matters. Whether you can answer it yet does not. Create each one as a child of the map, labelled `scry:<type>` (`research`, `prototype`, `interrogation`, `task`). See Ticket types in `references/map-shape.md`. ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" create-ticket MAP_NUMBER TYPE "Title" <<'EOF' ## Question <the decision or investigation> EOF ``` Wire blocking edges in a **second pass**, once every ticket has a number: ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" wire CHILD_NUMBER BLOCKER_NUMBER ``` Everything still too dim to phrase stays in **Not yet specified**. Do not pre-slice fog into ticket-sized pieces. ### 2e. Fire research For each `research` ticket just created, read `references/research.md` and spawn a generic subagent seeded with that file plus the ticket's Question. They run as one concurrent batch. Charting hand-resolves nothing else. After recording the research results, run Stage 3f's closeout check. Stop. Charting is one session. --- ## Stage 3: Walk Load `references/map-shape.md` if you have not this session. ### 3a. Load the map Fetch the map issue (the low-resolution view). Do not fetch every child body yet. ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" view MAP_NUMBER GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" frontier MAP_NUMBER ``` Orient to Destination and Notes before picking a ticket. If the map is already closed, load `references/handoff.md` and produce the read-only handoff report it specifies. Do not add another completion note or change the map. Prefer an existing linked build effort and its available tickets. If none exists, follow that reference to identify implementation, another decision, or a destination requiring no further work. Stop after the handoff report. Otherwise run Stage 3f's closeout check before choosing work. If the map is finished, close it and stop. If the frontier is empty but the map remains unfinished, report what keeps it open: assigned or blocked tickets, unresolved fog, or an unmet destination. Specify remaining in-scope questions where possible; ask only about choices the available decisions do not settle. If no ticket can be worked, stop after reporting the remaining work. ### 3b. Choose and claim If the user named a ticket, use it. Otherwise take the first frontier row (open, unblocked, unclaimed, map order). Claim it before any work: ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" claim TICKET_NUMBER ``` ### 3c. Resolve Fetch that ticket's body. Zoom into a related or closed ticket only when this question needs it. Load the reference for its type, and only that type: | Type | Load | |------|------| | `interrogation` | `references/interrogate.md` and `references/domain.md` | | `research` | `references/research.md` | | `prototype` | `references/prototype.md`, then `references/interrogate.md` once there is an artifact to react to | | `task` | none. Do the work, or hand the user a precise checklist | If Notes name more files to read, read them. When the type is unclear, load `interrogate.md` and `domain.md`. `you-pick` (or the user saying "make the decisions") accepts recommended interrogation answers. ### 3d. Record Post the answer as a comment, close the ticket, append one gist line to the map's **Decisions so far**. ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" comment TICKET_NUMBER <<'EOF' <answer> Docs impact: <owning doc and what changes, or none> EOF GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" close TICKET_NUMBER ``` Then `view` the map, splice a line under **Decisions so far**, and `update-body` the map: ``` - [<ticket title>](<url>): <one-line gist> ``` If Notes or the repo name an owning document, write the decision there too. The ticket still holds the full answer. Assets created while resolving (research notes, a prototype path) are linked from the comment. Do not paste them into the map. ### 3e. Graduate fog Create-then-wire any question the answer just made specifiable. Clear each graduated patch from **Not yet specified** so it lives only as its new ticket. If this answer shows a ticket sits past the destination, close that ticket and move one line into **Out of scope** (gist, why, link). It does not go in Decisions so far. If the decision invalidates other tickets, update or close them. Run the closeout check below, then stop. Closing the parent finishes this session and does not count as working another ticket. ### 3f. Close out the map Re-read the map and check all children, including assigned or blocked tickets. On GitHub: ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" view MAP_NUMBER GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" children MAP_NUMBER ``` On GitHub, before reviewing or deriving the replacement, save the original body in a private temporary file. The body read must remove a partial snapshot and abort on failure: ```bash snapshot_path=$(mktemp) if ! GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" body MAP_NUMBER > "$snapshot_path"; then rm -f "$snapshot_path" exit 1 fi printf 'original_body=%s\n' "$snapshot_path" ``` An empty frontier or a full child progress count alone does not establish completion. Every child must be closed. Review **Not yet specified** against the recorded decisions: clear resolved fog, move work beyond the destination to **Out of scope** with a reason, and keep any unresolved in-scope question visible. Verify that **Destination** is reached under the map's **Notes**, and that required owning documents contain the decisions. Read individual resolutions when the gists do not establish this. Closed tickets that were invalidated or ruled out do not by themselves prove the destination was reached. If anything remains, keep the map open and tell the user what remains. Do not start building merely to close a decision map. If nothing remains, preserve the other sections and prepare any cleanup and a brief **Completion** section stating how the destination was reached and linking any resulting spec or owning document. Load `references/handoff.md` and add a durable **Next step** subsection: identify an existing build effort if one is linked, state that the destination is complete when no downstream work is required, or include the copyable implementation prompt with this map's URL and intended outcome. Update an existing completion note when retrying after a failed close. Shell variables do not persist between calls. Record the printed absolute path, then set `original_body` to that exact path in the update call below. Read the body and prepare the replacement from that snapshot. Write it with the guard, and stop without running `close-map` if the snapshot is missing, the read fails, or the current body differs: ```bash original_body='<recorded absolute snapshot path>' if ! GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" update-body MAP_NUMBER --expected-body "$original_body" <<'EOF' <updated body> EOF then rm -f "$original_body" exit 1 fi rm -f "$original_body" ``` The guard detects stale snapshots between the read and comparison. It cannot eliminate the residual read/write race between comparison and the GitHub write, since those calls are not an atomic compare-and-swap. ```bash GH_HOST=<derived-host> bash "<SKILL_DIR>/scripts/map.sh" close-map MAP_NUMBER ``` `close-map` rechecks child states before closing; the agent owns the destination and fog checks above. If a read fails or a child remains open, report the reason and leave the map open. Confirm the final state with `view` before reporting it closed. The final response must include the **Next step** and its exact copyable action, even when no tickets remain open. On another tracker, apply the same checks through its Wayfinding operations and close the parent using that tracker. For a scratch map, check every linked ticket file, append the completion note to the map, and set its `Status: closed`. A map already closed needs no further write. --- ## References | Reference | Load at | Purpose | |-----------|---------|---------| | `references/github-ops.md` | Stage 1 | How `map.sh` talks to GitHub, including exit 3 | | `references/map-shape.md` | Stage 2, Stage 3 | Map body, ticket types, fog, out of scope | | `references/handoff.md` | Stage 3a, Stage 3f | Completion handoff and closed-map revisit report | | `references/interrogate.md` | Stage 2; Stage 3 on interrogation or prototype | Design-tree interview | | `references/domain.md` | With interrogation | Glossary and ADRs as terms land | | `references/research.md` | Stage 2e; Stage 3 on research | AFK cited notes under `docs/research/` | | `references/prototype.md` | Stage 3 on prototype | Cheap artifact to react to | | `references/scratch.md` | Stage 1, exit 3 only | Local map when GitHub writes fail |
Ships with 10 supporting files:
- references/archmage.md
- references/domain.md
- references/github-ops.md
- references/handoff.md
- references/interrogate.md
- references/map-shape.md
- references/prototype.md
- references/research.md
- references/scratch.md
- scripts/map.sh
Mirrored from the author's public source. Install counts from the open skills registry.