#155 by GitHub stars
backnotprop/plannotator
The workspace to stay in the loop and on top of agents - shape, decide, plan, annotate, review code, share with team, and send all feedback to agents with one click.
History
Review weekly changes to SKILL.md before updating. Dates mark the weeks in which we observed each version; checks apply to the recorded commits.
View weekly changes
apps/kiro-cli/skills/plannotator-annotate/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/kiro-cli/skills/plannotator-review/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/qwen-code/skills/plannotator-annotate/SKILL.md
Week of Nov 2, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 748c27a7de08
No earlier version was observed for comparison.
apps/qwen-code/skills/plannotator-last/SKILL.md
Week of Nov 2, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 748c27a7de08
No earlier version was observed for comparison.
apps/qwen-code/skills/plannotator-review/SKILL.md
Week of Nov 2, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 748c27a7de08
No earlier version was observed for comparison.
apps/skills/claude/plannotator-annotate/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/claude/plannotator-inbox/SKILL.md
Week of Nov 2, 2026 · +18 / −2 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
- 3 description: Open the Plannotator Inbox in the browser (starting it if needed) and say its address.
+ 3 description: Open the Plannotator Inbox in the browser (starting it if needed), say its address, and learn how to use the Inbox for the rest of the session.
+ 14 ## Using the Inbox
+ 15
+ 16 The Plannotator Inbox is one window on this computer where you leave the person messages, `:::question` blocks they answer with a click, and files. They answer when they can. Nothing blocks: you send, then keep working or end your turn.
+ 17
+ 18 - Use it for a decision only they can make (a :::question block; go on with other work), finished long work (a short summary with its pictures inline, files in `attachments`), or when they ask.
+ 19 - One thread per work stream, unless the person says otherwise.
+ 20 - Send with a `plannotator_inbox` tool when you have one (it can be listed with a prefix and may need loading through tool search first): `action` `send_message`, with a markdown `body`. Otherwise call `send_message` on the Inbox's MCP server, `plannotator inbox mcp`.
+ 21 - send_message's result says whether the person's reply arrives in this session by itself. When it does, do not wait or poll for it: end your turn or go on with other work. When it does not, go on with your work and read the thread later with read_thread.
+ 22 - A decision in the Inbox stays there: when the person writes in the chat, say what waits and link its thread, but never also ask it in the chat with a blocking question tool (AskUserQuestion or similar). Ask in the chat only about something new they raised there that needs no pictures or files, or when they ask.
+ 23 - Be proactive about Inbox updates and about replying to the person through the Inbox when you think they would want you to. Don't withhold important updates or decisions, and don't batch updates to send later: proactivity is better than procrastination.
+ 24 - Never run `plannotator inbox` just to send: send_message starts a stopped Inbox itself, and bare `plannotator inbox` opens the window for the person.
+ 25 - Before your first send, run `plannotator inbox --help` and read it: every field, the full question syntax, and how to connect the MCP server.
+ 26 - The `plannotator` skill, where you have it, has more.
+ 27
- 16 The output above is the Plannotator Inbox's address; it opened in the person's browser unless the output says why not. Tell them the address in one sentence, with that reason when there is one, and stop. Do not begin any work.
+ 30 The output above is the Plannotator Inbox's address; it opened in the person's browser unless the output says why not. Tell them the address in one sentence, with that reason when there is one. If the output is an error, tell them what it says; `Unknown inbox option: --open` means their Plannotator is older than this command (update with `plannotator update`, or run `plannotator inbox` in a terminal).
+ 31
+ 32 This command starts no new work and resumes none: do anything else the person asked in the same message, otherwise stop there. For the rest of this session, use the Inbox as above: for a decision the person is not here to make, and to hand over long work you finished.
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/claude/plannotator-last/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/claude/plannotator-review/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/core/plannotator/SKILL.md
Week of Nov 2, 2026 · +25 / −15 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
- 69 - `--no-git-remote-check` stops the session contacting the git remote at all: no `git ls-remote` for the default branch or the "behind GitHub" baseline check. The compare target then comes from local refs only and the staleness banner never shows, which also takes away its one-click Fetch button (the `/api/fetch-base` endpoint stays available); fetching from a terminal is unaffected. Use it when a remote probe is expensive or intrusive — most sharply when SSH authentication is backed by a hardware token, where each probe is a physical touch prompt. The same opt-out is available session-wide as `PLANNOTATOR_GIT_REMOTE_CHECK=0` or `{ "gitRemoteCheck": false }` in `~/.plannotator/config.json` (the flag beats the env var, which beats the config key). Without it the remote is queried when the review opens, on diff load, on a diff-type/base switch, and on Fetch — never on a timer.
+ 69 - `--no-git-remote-check` stops the session contacting the git remote at all: no `git ls-remote` for the default branch or the "behind GitHub" baseline check. The compare target then comes from local refs only and the staleness banner never shows, which also takes away its one-click Fetch button (the `/api/fetch-base` endpoint stays available); fetching from a terminal is unaffected. Use it when a remote probe is expensive or intrusive — most sharply when SSH authentication is backed by a hardware token, where each probe is a physical touch prompt. The same opt-out is available session-wide as `PLANNOTATOR_GIT_REMOTE_CHECK=0` or `{ "gitRemoteCheck": false }` in `config.json` in the data directory (`plannotator data-dir` prints it) (the flag beats the env var, which beats the config key). Without it the remote is queried when the review opens, on diff load, on a diff-type/base switch, and on Fetch — never on a timer.
+ 88 - AsciiDoc files: `.adoc`, `.asciidoc`.
+ 179 plannotator inbox call [--session <id>] <action> [<json> | -]
+ 180 plannotator inbox status [--json] | stop | restart
- 182 - Use it for a decision only they can make (a `:::question` block, then go on with work that does not depend on it), long work you finished (one short summary, with the files to look at in `attachments`), or when they ask. A decision you sent to the Inbox stays there: when the person writes in the chat, say there what waits (a short summary and the thread's link), but never also ask it in the chat with a blocking question tool (AskUserQuestion or similar). Ask in the chat only about something new they raised there that needs no pictures or files, or when they ask. Do not send routine progress. Use a review (plan review, `annotate`, `review`) when you need a decision on this document or diff before you go on.
- 183 - If you have a `plannotator_inbox` tool, use it; otherwise use the stdio MCP server `plannotator inbox mcp`. With the tool, the person's reply arrives in your session by itself, so end your turn instead of waiting.
+ 185 - Use it for a decision only they can make (a `:::question` block, then go on with work that does not depend on it), long work you finished (one short summary with its pictures in place, `` in the body where you write about each, and the files to look at in `attachments`), or when they ask. One thread per work stream, unless the person says otherwise. A decision you sent to the Inbox stays there: when the person writes in the chat, say there what waits (a short summary and the thread's link), but never also ask it in the chat with a blocking question tool (AskUserQuestion or similar). Ask in the chat only about something new they raised there that needs no pictures or files, or when they ask. Be proactive about Inbox updates and about replying to the person through the Inbox when you think they would want you to. Don't withhold important updates or decisions, and don't batch updates to send later: proactivity is better than procrastination. Use a review (plan review, `annotate`, `review`) when you need a decision on this document or diff before you go on.
+ 186 - If you have a `plannotator_inbox` tool, use it; otherwise use the stdio MCP server `plannotator inbox mcp`. When send_message says the person's reply arrives in this session by itself, end your turn instead of waiting; otherwise go on with your work and read the thread later with read_thread.
+ 187 - For many Inbox calls in a row (a tidy above all), `plannotator inbox call` runs any action from a script and prints its result as JSON; `plannotator inbox --help` says how.
- 185 - Never run `plannotator inbox` just to send: calls start a stopped Inbox in the background, and bare `plannotator inbox` opens the window for the person. `--tailscale` is the person's choice; never add it.
+ 189 - Never run `plannotator inbox` just to send: calls start a stopped Inbox in the background, and bare `plannotator inbox` opens the window for the person. `--tailscale` is the person's choice; never add it. `plannotator inbox status` only reads; never run `plannotator inbox stop` or `restart` unless the person asks.
- 194 Only while the person has turned the Inbox's Board on (Settings → Capabilities); it is off by default, and then every call answers `board_off` and writes nothing, so use it only when your inbox tool lists `card` or the person asks. The Board holds one card per piece of work that outlasts a reply, in the column of its stage (backlog, designing, your_look, building, your_review, shipped). Use the `card` action of a `plannotator_inbox` tool when you have one; this CLI is the same call from a shell. `plannotator card --help` gives the arguments, and `plannotator inbox --help` its card section while the Board is on. The icebox is the person's only. A title is 2–5 words naming the work ("Pi update fix"), never a sentence; where it stands goes in `say`. When a card waits on the person, link the Inbox thread where they make the call (`thread_id`), so "You: …" opens it.
+ 198 Only while the person has turned the Inbox's Board on (Settings → Capabilities); it is off by default, and then every call answers `board_off` and writes nothing, so use it only when your inbox tool lists `card` or the person asks. The Board holds one card per piece of work that outlasts a reply, in the column of where the work stands (todo, in_progress, in_review, done; backlog for what nobody asked for yet). Use the `card` action of a `plannotator_inbox` tool when you have one; this CLI is the same call from a shell. `plannotator card --help` gives the arguments, and `plannotator inbox --help` its card section while the Board is on. A card the person put in backlog is theirs to move. A title is 2–5 words naming the work ("Pi update fix"), never a sentence; where it stands goes in `say`. Move a card to in_review yourself when you hand your part over, with `you` and the Inbox thread where the person makes the call (`thread_id`), so "You: …" opens it. Ship a card when you see its PR merge (the Board may also move it to done once every PR linked with `--pr` merged).
+ 204 plannotator data-dir
+ 205 plannotator feedback --stdin [--category <bug|idea|other>] [--contact '<text>'] <<'PLANNOTATOR_FEEDBACK_END'
+ 206 <the message, exactly as the person approved it>
+ 207 PLANNOTATOR_FEEDBACK_END
+ 214 - `data-dir` prints the absolute path of Plannotator's data directory (plans, history, drafts, `config.json`, `hooks/`) and creates nothing. Run it whenever you need a file in that folder, and use the path it prints. Never write a path such as `~/.plannotator/...` from memory: an install can keep its data under `$XDG_DATA_HOME/plannotator`, and a new `~/.plannotator` can hide that data from Plannotator. If it prints nothing or fails (an older Plannotator, before 0.28.41), use `$PLANNOTATOR_DATA_DIR` when it is set; otherwise the home folder's `.plannotator` if it exists, else `$XDG_DATA_HOME/plannotator` when `XDG_DATA_HOME` is set, else the home folder's `.plannotator`.
+ 215 - `feedback` sends the person's feedback about Plannotator to its maintainers and prints `Sent` (the message, the category and contact if given, the version, the OS name and that it came from the CLI; nothing else). Only when the person asks you to send feedback: show them the exact text first and run it only after they say yes. Pass the message on stdin with a quoted heredoc (`<<'PLANNOTATOR_FEEDBACK_END'`, quotes included; pick another end word if a line of the message is exactly that), never inside double quotes in any shell, where `$VAR`, backticks and `$(...)` are expanded and change the approved text. Fill in or leave out the bracketed options (`--category idea`), and put a contact in single quotes. In PowerShell, set `$OutputEncoding = [Text.UTF8Encoding]::new($false)` and pipe a single-quoted here-string (`@'` … `'@ | plannotator feedback --stdin`). Exit 0 sent, 1 not sent, 2 usage.
- 209 - Additional host-internal subcommands (the `opencode-*` and `copilot-plan` family) are invoked by their plugins, not by you.
+ 219 - Additional host-internal subcommands (the `opencode-*` family, `copilot-plan` and `dsh-plan`) are invoked by their plugins, not by you.
- 217 | `PLANNOTATOR_ORIGIN` | Override agent-origin detection (`claude-code`, `codex`, `opencode`, `pi`, `oh-my-pi`, `amp`, `droid`, `copilot-cli`, `gemini-cli`, `kiro-cli`, `mistral-vibe`). Set it when launching Plannotator from a wrapper the detection cannot see through. |
+ 227 | `PLANNOTATOR_ORIGIN` | Override agent-origin detection (`claude-code`, `codex`, `opencode`, `pi`, `oh-my-pi`, `amp`, `droid`, `copilot-cli`, `gemini-cli`, `kiro-cli`, `mistral-vibe`, `qwen-code`, `dsh`). Set it when launching Plannotator from a wrapper the detection cannot see through. |
- 220 | `PLANNOTATOR_DATA_DIR` | Move the data directory (default `~/.plannotator`): plans, history, drafts, config. |
+ 230 | `PLANNOTATOR_DATA_DIR` | Move the data directory: plans, history, drafts, config. Unset, the default is `~/.plannotator` or `$XDG_DATA_HOME/plannotator`; `plannotator data-dir` prints which one this install uses. |
- 236 When two devices edit one note offline, the later save wins and the other edit is lost. Local storage keeps it with no server work.
- 237
- 238 - [ ] Local only, purged after 30 days — cheap, no server change
+ 246 When two devices edit one note offline, the later save wins and the other is lost. Local storage keeps it with no server work.
+ 247
+ 248 - [ ] Nowhere — silent loss, as today
+ 249 - [ ] Local only, purged after 30 days — cheap
- 240 - [ ] Nowhere — accept silent loss for v1
- 252 - Choices: `- [ ] label`, optionally `- [ ] label — why`. The reviewer can also answer "Other", add a note, or skip.
- 253 - `Recommended: <label>` marks yours (`A, B and C` on `:::question-multi`); other text shows as one more answer, tagged Recommended.
- 254 - Ask only what you cannot decide alone, about 8 a round at most. Do not ask rhetorical questions or questions the codebase answers.
+ 262 - Choices: `- [ ] label`, optionally `- [ ] label — why`, in natural order. The reviewer can also answer "Other", add a note, or skip.
+ 263 - `Recommended: <label>` marks yours (`A, B and C` on `:::question-multi`); other text is one more answer, tagged Recommended. Never move yours first.
+ 264 - Ask only what you cannot decide alone, about 8 a round. Do not ask rhetorical questions or questions the codebase answers.
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/core/plannotator-annotate/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/core/plannotator-inbox/SKILL.md
Week of Nov 2, 2026 · +21 / −3 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
- 3 description: Open the Plannotator Inbox in the browser (starting it if needed) and tell the person its address.
+ 3 description: Open the Plannotator Inbox in the browser (starting it if needed), tell the person its address, and learn how to use the Inbox for the rest of the session.
- 9 Use this skill when the person wants their Plannotator Inbox: they closed its tab, or ask where it is.
+ 9 Use this skill when the person wants their Plannotator Inbox (they closed its tab, or ask where it is), or wants you to use it.
- 20 2. Tell the person the address in one sentence and stop. Do not begin any work. When it also says no browser opened (a remote session), pass on how it says to reach the Inbox.
+ 20 2. Tell the person the address in one sentence. When it also says no browser opened (a remote session), pass on how it says to reach the Inbox.
+ 24
+ 25 ## Using the Inbox
+ 26
+ 27 The Plannotator Inbox is one window on this computer where you leave the person messages, `:::question` blocks they answer with a click, and files. They answer when they can. Nothing blocks: you send, then keep working or end your turn.
+ 28
+ 29 - Use it for a decision only they can make (a :::question block; go on with other work), finished long work (a short summary with its pictures inline, files in `attachments`), or when they ask.
+ 30 - One thread per work stream, unless the person says otherwise.
+ 31 - Send with a `plannotator_inbox` tool when you have one (it can be listed with a prefix and may need loading through tool search first): `action` `send_message`, with a markdown `body`. Otherwise call `send_message` on the Inbox's MCP server, `plannotator inbox mcp`.
+ 32 - send_message's result says whether the person's reply arrives in this session by itself. When it does, do not wait or poll for it: end your turn or go on with other work. When it does not, go on with your work and read the thread later with read_thread.
+ 33 - A decision in the Inbox stays there: when the person writes in the chat, say what waits and link its thread, but never also ask it in the chat with a blocking question tool (AskUserQuestion or similar). Ask in the chat only about something new they raised there that needs no pictures or files, or when they ask.
+ 34 - Be proactive about Inbox updates and about replying to the person through the Inbox when you think they would want you to. Don't withhold important updates or decisions, and don't batch updates to send later: proactivity is better than procrastination.
+ 35 - Never run `plannotator inbox` just to send: send_message starts a stopped Inbox itself, and bare `plannotator inbox` opens the window for the person.
+ 36 - Before your first send, run `plannotator inbox --help` and read it: every field, the full question syntax, and how to connect the MCP server.
+ 37 - The `plannotator` skill, where you have it, has more.
+ 38
+ 39 ## After the address
+ 40
+ 41 This command starts no new work and resumes none: do anything else the person asked in the same message, otherwise stop there. For the rest of this session, use the Inbox as above: for a decision the person is not here to make, and to hand over long work you finished.
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/core/plannotator-last/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/core/plannotator-review/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/extra/plannotator-compound/SKILL.md
Week of Nov 2, 2026 · +35 / −11 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
- 24 1. **Plannotator mode (first-class)** — Determine the Plannotator data directory:
- 25 use `$PLANNOTATOR_DATA_DIR` if set, otherwise `~/.plannotator`. Check the
- 26 `plans/` subdirectory there. If it exists and contains `*-denied.md` files,
- 27 use this mode. The entire workflow below is written for Plannotator data.
+ 24 1. **Plannotator mode (first-class)** — Find the Plannotator data directory,
+ 25 called `<data-dir>` from here on. Run:
+ 26
+ 27 ```
+ 28 plannotator data-dir
+ 29 ```
+ 30
+ 31 It prints the folder's absolute path and creates nothing; use what it
+ 32 prints. If it prints nothing or fails (an older Plannotator), use `$PLANNOTATOR_DATA_DIR` if
+ 33 set, else whichever of `$XDG_DATA_HOME/plannotator` and the home folder's
+ 34 `.plannotator` holds `history/` or `sessions/` (the home one if both do),
+ 35 and ask the user if neither does.
+ 36
+ 37 Never write into any other folder than `<data-dir>`. In particular, do not
+ 38 create a `.plannotator` folder in the home folder unless `<data-dir>` is
+ 39 that folder: on an install that keeps its data under `$XDG_DATA_HOME`, a
+ 40 new one can make Plannotator lose sight of the person's plans and history.
+ 41 Leave any other Plannotator folder you find alone, and do not suggest
+ 42 deleting it: it may hold older data.
+ 43
+ 44 Check the `plans/` subdirectory of `<data-dir>`. If it exists and contains
+ 45 `*-denied.md` files, use this mode. The entire workflow below is written for
+ 46 Plannotator data.
- 58 ls ${PLANNOTATOR_DATA_DIR:-~/.plannotator}/plans/compound-planning-report*.html
- 59 ```
+ 77 ls <data-dir>/plans/compound-planning-report*.html
+ 78 ```
+ 79
+ 80 (`<data-dir>` is the folder from Source Selection; put its real path in the command.)
- 364 the user's plans directory with a versioned filename:
+ 385 `<data-dir>/plans/` (the folder from Source Selection) with a versioned filename:
- 522 ${PLANNOTATOR_DATA_DIR:-~/.plannotator}/hooks/compound/enterplanmode-improve-hook.txt
- 523 ```
- 524
- 525 Create the `hooks/compound/` directory inside the data directory if it doesn't exist.
+ 543 <data-dir>/hooks/compound/enterplanmode-improve-hook.txt
+ 544 ```
+ 545
+ 546 `<data-dir>` is the folder from Source Selection (`plannotator data-dir`
+ 547 prints it). If you have not found it yet, find it now the same way; never
+ 548 guess it. Create the `hooks/compound/` directory inside `<data-dir>` if it
+ 549 doesn't exist.
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/extra/plannotator-setup-goal/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/skills/extra/plannotator-visual-explainer/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/vibe/skills/plannotator-annotate/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/vibe/skills/plannotator-last/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
apps/vibe/skills/plannotator-review/SKILL.md
Week of Nov 2, 2026 · +0 / −0 lines
Before Network or broad shell → After Network or broad shell
6a6263ddaa89 → 748c27a7de08
Week of Oct 26, 2026 · Line counts unavailable
Before Not checked yet → After Network or broad shell
First observation → 6a6263ddaa89
No earlier version was observed for comparison.
Verified commit 748c27a7de085444de509ad8c1f8a9cd0859e3a2
git clone --filter=blob:none --no-checkout https://github.com/backnotprop/plannotator.git .hotskills/backnotprop-plannotator && git -C .hotskills/backnotprop-plannotator checkout --detach 748c27a7de085444de509ad8c1f8a9cd0859e3a2
# Copy each selected skill directory from .hotskills/backnotprop-plannotator into .claude/skills/<skill-name>/git clone --filter=blob:none --no-checkout https://github.com/backnotprop/plannotator.git .hotskills/backnotprop-plannotator && git -C .hotskills/backnotprop-plannotator checkout --detach 748c27a7de085444de509ad8c1f8a9cd0859e3a2
# Copy each selected skill directory from .hotskills/backnotprop-plannotator into .agents/skills/<skill-name>/Heat
7.0- Star growth, last 7 daysAhead of 81% of tracked repositories
- Star growth, last 24 hoursAhead of 74% of tracked repositories
- Rank movement, last 7 daysAhead of 69% of tracked repositories
- Commits, last 30 daysAhead of 100% of tracked repositories
- Accounts asking about it through MCP, last 7 daysNot available
- Hot votes this weekAhead of 0% of tracked repositories
Heat never changes the order by stars, and sponsorship never touches it. How heat works
Stars over time
Individual skills in this repository
- plannotator-annotate
apps/kiro-cli/skills/plannotator-annotate - plannotator-review
apps/kiro-cli/skills/plannotator-review - plannotator-annotate
apps/qwen-code/skills/plannotator-annotate - plannotator-last
apps/qwen-code/skills/plannotator-last - plannotator-review
apps/qwen-code/skills/plannotator-review - plannotator-annotate
apps/skills/claude/plannotator-annotate - plannotator-inbox
apps/skills/claude/plannotator-inbox - plannotator-last
apps/skills/claude/plannotator-last - plannotator-review
apps/skills/claude/plannotator-review - plannotator
apps/skills/core/plannotator - plannotator-annotate
apps/skills/core/plannotator-annotate - plannotator-inbox
apps/skills/core/plannotator-inbox - plannotator-last
apps/skills/core/plannotator-last - plannotator-review
apps/skills/core/plannotator-review - plannotator-compound
apps/skills/extra/plannotator-compound - plannotator-setup-goal
apps/skills/extra/plannotator-setup-goal - plannotator-visual-explainer
apps/skills/extra/plannotator-visual-explainer - plannotator-annotate
apps/vibe/skills/plannotator-annotate - plannotator-last
apps/vibe/skills/plannotator-last - plannotator-review
apps/vibe/skills/plannotator-review
How it works
plannotator-annotate
When your agent uses it
Open Plannotator's annotation UI for a file, folder, or URL, then address the returned annotations.
What it loads into context
Frontmatter
41 tokensAlways available to the agent
SKILL.md
217 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Scripts executed separately
../../../hook/hooks/mod/bridge.test.ts../../../hook/hooks/mod/bridge.ts../../../hook/hooks/mod/controller.test.ts../../../hook/hooks/mod/controller.ts../../../hook/hooks/mod/delivery.test.ts../../../hook/hooks/mod/delivery.ts../../../hook/hooks/mod/enabled.test.ts../../../hook/hooks/mod/enabled.ts../../../hook/hooks/mod/globals.d.ts../../../hook/hooks/mod/host.ts../../../hook/hooks/mod/inbox-ask.test.ts../../../hook/hooks/mod/inbox-contract.test.ts../../../hook/hooks/mod/inbox-contract.ts../../../hook/hooks/mod/inbox-default-tools.test.ts../../../hook/hooks/mod/inbox-default-tools.ts../../../hook/hooks/mod/inbox-loaded.test.ts../../../hook/hooks/mod/inbox-reminder-custom.test.ts../../../hook/hooks/mod/inbox-reminder.test.ts../../../hook/hooks/mod/inbox-session-label.test.ts../../../hook/hooks/mod/inbox-session-project.test.ts../../../hook/hooks/mod/inbox-session-threads.test.ts../../../hook/hooks/mod/inbox.test.ts../../../hook/hooks/mod/inbox.ts../../../hook/hooks/mod/launch.test.ts../../../hook/hooks/mod/launch.ts../../../hook/hooks/mod/plan.ts../../../hook/hooks/mod/register.test.ts../../../hook/hooks/mod/register.ts../../../hook/hooks/mod/send-now-engine.test.ts../../../hook/hooks/mod/shell-words.ts../../../hook/hooks/mod/tailscale.test.ts../../../hook/hooks/mod/take-over.test.ts../../../hook/hooks/mod/take-over.ts../../../hook/hooks/mod/targets.test.ts../../../hook/hooks/mod/testing/claude-session.ts../../../hook/hooks/mod/testing/fake-host.ts../../../hook/hooks/mod/tool.test.ts../../../hook/hooks/mod/tool.ts../../../hook/hooks/mod/turns.test.ts../../../hook/hooks/mod/turns.ts
Files
../../../../.claude-plugin/marketplace.jsonasset338 bytes../../../copilot/hooks.jsonasset366 bytes../../../hook/.claude-plugin/plugin.jsonasset410 bytes../../../hook/hooks/hooks.jsonasset1,474 bytes../../../hook/hooks/mod/bridge.test.tsruns17,001 bytes../../../hook/hooks/mod/bridge.tsruns15,839 bytes../../../hook/hooks/mod/controller.test.tsruns75,234 bytes../../../hook/hooks/mod/controller.tsruns82,743 bytes../../../hook/hooks/mod/delivery.test.tsruns10,260 bytes../../../hook/hooks/mod/delivery.tsruns13,019 bytes../../../hook/hooks/mod/enabled.test.tsruns6,832 bytes../../../hook/hooks/mod/enabled.tsruns7,691 bytes../../../hook/hooks/mod/globals.d.tsruns782 bytes../../../hook/hooks/mod/host.tsruns4,597 bytes../../../hook/hooks/mod/inbox-ask.test.tsruns23,204 bytes../../../hook/hooks/mod/inbox-contract.test.tsruns988 bytes../../../hook/hooks/mod/inbox-contract.tsruns71,460 bytes../../../hook/hooks/mod/inbox-default-tools.test.tsruns2,043 bytes../../../hook/hooks/mod/inbox-default-tools.tsruns26,512 bytes../../../hook/hooks/mod/inbox-loaded.test.tsruns4,608 bytes../../../hook/hooks/mod/inbox-reminder-custom.test.tsruns3,895 bytes../../../hook/hooks/mod/inbox-reminder.test.tsruns7,332 bytes../../../hook/hooks/mod/inbox-session-label.test.tsruns21,193 bytes../../../hook/hooks/mod/inbox-session-project.test.tsruns8,663 bytes../../../hook/hooks/mod/inbox-session-threads.test.tsruns3,403 bytes../../../hook/hooks/mod/inbox.test.tsruns67,484 bytes../../../hook/hooks/mod/inbox.tsruns59,605 bytes../../../hook/hooks/mod/launch.test.tsruns10,003 bytes../../../hook/hooks/mod/launch.tsruns30,610 bytes../../../hook/hooks/mod/plan.tsruns6,741 bytes../../../hook/hooks/mod/register.test.tsruns3,306 bytes../../../hook/hooks/mod/register.tsruns48,203 bytes../../../hook/hooks/mod/send-now-engine.test.tsruns1,817 bytes../../../hook/hooks/mod/shell-words.tsruns1,687 bytes../../../hook/hooks/mod/tailscale.test.tsruns9,823 bytes../../../hook/hooks/mod/take-over.test.tsruns6,254 bytes../../../hook/hooks/mod/take-over.tsruns2,092 bytes../../../hook/hooks/mod/targets.test.tsruns11,296 bytes../../../hook/hooks/mod/testing/claude-session.tsruns11,393 bytes../../../hook/hooks/mod/testing/fake-host.tsruns4,782 bytes../../../hook/hooks/mod/tool.test.tsruns946 bytes../../../hook/hooks/mod/tool.tsruns41,561 bytes../../../hook/hooks/mod/tsconfig.jsonasset308 bytes../../../hook/hooks/mod/turns.test.tsruns21,384 bytes../../../hook/hooks/mod/turns.tsruns21,219 bytesSKILL.mdcore855 bytesSKILL.mdcore855 bytes../../../qwen-code/extension/hooks/hooks.jsonasset1,101 bytes
Read SKILL.md
# Plannotator Annotate (Kiro)
Run:
```bash
PLANNOTATOR_ORIGIN=kiro-cli plannotator annotate $ARGUMENTS
```
`$ARGUMENTS` should be a markdown or plain-text config file path (.md, .txt, .yaml, .json, .toml, .ini, .csv, .log, …), folder path, html file path, or URL.
If the command reports that the arguments could not be resolved to a file, URL, or folder, work out which target the user means and re-run the command yourself with that concrete path or URL.
If the session closes without feedback (the output is empty, or a JSON object with `"decision": "dismissed"`), acknowledge it in one sentence and stop. Do not begin any work: closing the session is not approval.View the complete source on GitHubplannotator-review
When your agent uses it
Open Plannotator's browser-based code review UI and address the returned feedback.
What it loads into context
Frontmatter
33 tokensAlways available to the agent
SKILL.md
247 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore1,047 bytesSKILL.mdcore1,047 bytesSKILL.mdcore1,047 bytesSKILL.mdcore1,047 bytes
Read SKILL.md
# Plannotator Review (Kiro)
Run:
```bash
PLANNOTATOR_ORIGIN=kiro-cli plannotator review
```
You may append one directory or PR URL:
```bash
PLANNOTATOR_ORIGIN=kiro-cli plannotator review <pr-url>
PLANNOTATOR_ORIGIN=kiro-cli plannotator review ../feature-worktree
```View the complete source on GitHubplannotator-annotate
When your agent uses it
Open Plannotator's annotation UI for a markdown file, plain-text config file (.yaml, .json, .toml, .ini, .csv, .log, …), HTML file, URL, or folder and then respond to the returned annotations.
What it loads into context
Frontmatter
70 tokensAlways available to the agent
SKILL.md
514 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore2,227 bytesSKILL.mdcore2,227 bytesSKILL.mdcore2,227 bytes
Read SKILL.md
# Plannotator Annotate (Qwen Code)
Use this skill when the user wants to annotate a document in Plannotator instead of reviewing it inline in chat.
Run for ordinary annotation/feedback:
```bash
plannotator annotate <path-or-url>
```
Run when the user asks to review, approve, accept, or gate a generated plan/spec/document:
```bash
plannotator annotate <path-or-url> --gate --jsonView the complete source on GitHubplannotator-last
When your agent uses it
Open Plannotator on the latest rendered assistant message and use the returned annotations to revise that message or continue.
What it loads into context
Frontmatter
38 tokensAlways available to the agent
SKILL.md
346 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore1,620 bytesSKILL.mdcore1,620 bytes
Read SKILL.md
# Plannotator Last (Qwen Code)
Use this skill when the user wants to annotate the latest assistant response in Plannotator.
Do not send a commentary/status message before running the command. The command
targets the latest rendered assistant response, so a preamble can mistakenly become the
thing being annotated.
Run:
```bash
plannotator last
```
View the complete source on GitHubplannotator-review
When your agent uses it
Open Plannotator's browser-based code review UI for the current worktree, another directory, or a pull request URL, then act on the feedback that comes back.
What it loads into context
Frontmatter
50 tokensAlways available to the agent
SKILL.md
418 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore1,931 bytesSKILL.mdcore1,931 bytes
Read SKILL.md
# Plannotator Review (Qwen Code)
Use this skill when the user wants to review current code changes in Plannotator instead of reading a diff inline.
Run:
```bash
plannotator review [--base <ref>] [--diff-type <type>] [directory-or-pr-url]
```
Run it with the shell tool's `is_background: true`, and no trailing `&`. The command waits until the person finishes the review in the browser, which often takes longer than the shell tool's foreground limit (2 minutes by default, 10 at most); a foreground run would be stopped and the review lost. Then end your turn without stopping the task. When the task finishes, read its output (the tool result names the output file) and act on it.
Reviewing one layer of a stacked branch? Pass `--base <the branch immediately below yours>` so the review shows only what this layer adds, instead of everything since `main`. Both flags are session-only (the reviewer can change either in the UI; nothing is persisted) and git-only.
View the complete source on GitHubplannotator-annotate
When your agent uses it
Open Plannotator's annotation UI for a markdown file, HTML file, URL, or folder and then respond to the returned annotations.
What it loads into context
Frontmatter
54 tokensAlways available to the agent
SKILL.md
372 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Markdown annotations
- Your task
Files
SKILL.mdcore1,654 bytes
Read SKILL.md
# Plannotator Annotate
## Markdown annotations
!`plannotator annotate $ARGUMENTS`
## Your task
The output above will be one of:
1. The exact text `The user approved.`, an "Approved with Notes" message, OR a JSON object with `"decision": "approved"`. The user approved the markdown file(s). If it is the Approved with Notes message, or that object also carries a `"feedback"` field, the user approved *with notes*: read them and carry them into subsequent work — they are non-blocking guidance, not a request to revise the file. Otherwise acknowledge with a single sentence ("Approved.") and stop. Either way, do not begin any work.
2. Empty, OR a JSON object with `"decision": "dismissed"`. The user closed the session without requesting changes. Acknowledge with a single sentence ("Annotation session closed.") and stop. Do not begin any work.
3. Plaintext annotation feedback, OR a JSON object with `"decision": "annotated"` and a `"feedback"` field. Address the feedback. The user has reviewed the markdown file(s) and provided specific annotations and comments.
4. A message that the arguments could not be resolved to a file, URL, or folder. The user described what to annotate in natural language: work out which file, URL, or folder they mean, run `plannotator annotate <path-or-url>` yourself with that concrete target (keeping any flags the message echoes), then handle its output per cases 1-3.View the complete source on GitHubplannotator-inbox
When your agent uses it
Open the Plannotator Inbox in the browser (starting it if needed), say its address, and learn how to use the Inbox for the rest of the session.
What it loads into context
Frontmatter
59 tokensAlways available to the agent
SKILL.md
680 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Inbox address
- Using the Inbox
- Your task
Files
SKILL.mdcore2,977 bytes
Read SKILL.md
# Plannotator Inbox
## Inbox address
!`plannotator inbox --open`
## Using the Inbox
The Plannotator Inbox is one window on this computer where you leave the person messages, `:::question` blocks they answer with a click, and files. They answer when they can. Nothing blocks: you send, then keep working or end your turn.
- Use it for a decision only they can make (a :::question block; go on with other work), finished long work (a short summary with its pictures inline, files in `attachments`), or when they ask.
- One thread per work stream, unless the person says otherwise.
- Send with a `plannotator_inbox` tool when you have one (it can be listed with a prefix and may need loading through tool search first): `action` `send_message`, with a markdown `body`. Otherwise call `send_message` on the Inbox's MCP server, `plannotator inbox mcp`.
- send_message's result says whether the person's reply arrives in this session by itself. When it does, do not wait or poll for it: end your turn or go on with other work. When it does not, go on with your work and read the thread later with read_thread.View the complete source on GitHubplannotator-last
When your agent uses it
Open Plannotator on the latest rendered assistant message and use the returned annotations to revise that message or continue.
What it loads into context
Frontmatter
47 tokensAlways available to the agent
SKILL.md
285 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Message annotations
- Your task
Files
SKILL.mdcore1,309 bytes
Read SKILL.md
# Plannotator Last
## Message annotations
!`plannotator annotate-last $ARGUMENTS`
## Your task
The output above will be one of:
1. The exact text `The user approved.`, an "Approved with Notes" message, OR a JSON object with `"decision": "approved"`. The user approved your last message. If it is the Approved with Notes message, or that object also carries a `"feedback"` field, the user approved *with notes*: read them and carry them into subsequent work — they are non-blocking guidance, not a request to revise the message. Otherwise acknowledge with a single sentence ("Approved.") and stop. Either way, do not begin any work.
2. Empty, OR a JSON object with `"decision": "dismissed"`. The user closed the session without requesting changes. Acknowledge with a single sentence ("Annotation session closed.") and stop. Do not begin any work.
3. Plaintext annotation feedback, OR a JSON object with `"decision": "annotated"` and a `"feedback"` field. Address the feedback. The user has reviewed your last message and provided specific annotations and comments.View the complete source on GitHubplannotator-review
When your agent uses it
Open Plannotator's browser-based code review UI for the current worktree, another directory, or a pull request URL, then act on the feedback that comes back.
What it loads into context
Frontmatter
59 tokensAlways available to the agent
SKILL.md
367 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Code review feedback
- Your task
Files
SKILL.mdcore1,631 bytes
Read SKILL.md
# Plannotator Review
Arguments pass through to `plannotator review`: one directory or PR/MR URL, `--git` / `--gitbutler`, and the session-only open-state flags `--base <ref>` / `--diff-type <type>` (git-only; for a stacked branch, `--base <the branch below yours>` reviews just that layer).
For another repository or worktree, pass its path relative to this session or an absolute path, e.g. `/plannotator-review ../feature-worktree`. Quote paths containing spaces. Supply a target, not prose; feedback names the directory where changes belong.
## Code review feedback
!`plannotator review $ARGUMENTS`
## Your task
If the review above contains feedback or annotations, address them in the same conversation. If no changes were requested (an approval/LGTM-style result), acknowledge that review passed and continue.
View the complete source on GitHubplannotator
When your agent uses it
Reference for using Plannotator (its `plannotator` tool when you have one, otherwise the CLI): plan review, code review, annotating files, URLs, folders, and running local apps, annotating the last assistant message, browsing archived plan decisions, exporting or sharing Guided Reviews, and the Plannotator Inbox (messages and questions the person answers later, without blocking you). Invoke when asked to use Plannotator for anything not covered by a more specific plannotator-* skill, and before you leave the person a decision, a question or finished work in the Plannotator Inbox (if another agent started you, report to it instead).
What it loads into context
Frontmatter
142 tokensAlways available to the agent
SKILL.md
7,505 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- If you have a `plannotator` tool, always use it
- Choose the command
- Session model
- plannotator review
- plannotator annotate
- plannotator annotate-last
- plannotator copilot-last
- plannotator archive
- plannotator guide
- plannotator sessions
- plannotator inbox
- plannotator card
- Other subcommands
- Environment variables that change behavior
- Posting annotations into a live session
- Asking the reviewer questions
- Do not
Files
SKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesSKILL.mdcore30,897 bytesagents/openai.yamlasset467 bytes
Read SKILL.md
# Plannotator CLI Reference
Plannotator is a local, browser-based review layer for agent workflows: it opens plans, diffs, and documents in an annotation UI, the human marks them up, and the structured feedback comes back to you on stdout. It installs as a single `plannotator` binary plus per-host hooks, so plan review fires automatically when you exit plan mode; every other surface is launched explicitly, with the `plannotator` tool when you have one and with the CLI otherwise. A session runs on a random localhost port (fixed port 19432 in remote mode) and blocks until the reviewer submits feedback, approves, or closes the tab.
This skill is the knowledge layer. The `plannotator-review`, `plannotator-annotate`, and `plannotator-last` skills are thin launchers for the three most common actions; use this reference when you need to pick the right command or flags yourself.
## If you have a `plannotator` tool, always use it
Check your tools before you run any command below. If you have a tool named `plannotator` (it can be listed with a prefix, for example `mcp__plannotator__plannotator` in Claude Code, and can need to be loaded through tool search before you call it), always call it instead of running `plannotator annotate`, `plannotator review`, or `plannotator last`. This includes approvals: call it with `{ "action": "annotate", "target": "<file>", "gate": true }`, not `--gate --json`.
The tool returns at once. End your turn after you call it and wait: the reviewer's decision arrives later as a message. Do not also run the CLI, poll, or reopen the session.
Use the CLI only when you have no such tool, or for what the tool does not do: `archive`, `guide`, `sessions`, review flags other than `--base` and `--gate`, annotate flags other than `--gate` and `--markdown`, and strict gates that a script checks by exit code (`--require-approval`, `--result-file`). If your tool offers `tailscale`, pass `tailscale: true` instead of `--tailscale`.
View the complete source on GitHubplannotator-annotate
When your agent uses it
Open Plannotator's annotation UI for a markdown file, plain-text config file (.yaml, .json, .toml, .ini, .csv, .log, …), HTML file, URL, or folder and then respond to the returned annotations.
What it loads into context
Frontmatter
70 tokensAlways available to the agent
SKILL.md
434 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore1,855 bytesSKILL.mdcore1,855 bytesSKILL.mdcore1,855 bytesagents/openai.yamlasset173 bytes
Read SKILL.md
# Plannotator Annotate
Use this skill when the user wants to annotate a document in Plannotator instead of reviewing it inline in chat.
Run for ordinary annotation/feedback:
```bash
plannotator annotate <path-or-url>
```
Run when the user asks to review, approve, accept, or gate a generated plan/spec/document:
```bash
plannotator annotate <path-or-url> --gate --jsonView the complete source on GitHubplannotator-inbox
When your agent uses it
Open the Plannotator Inbox in the browser (starting it if needed), tell the person its address, and learn how to use the Inbox for the rest of the session.
What it loads into context
Frontmatter
52 tokensAlways available to the agent
SKILL.md
748 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Using the Inbox
- After the address
Files
SKILL.mdcore3,272 bytesSKILL.mdcore3,272 bytesagents/openai.yamlasset171 bytes
Read SKILL.md
# Plannotator Inbox
Use this skill when the person wants their Plannotator Inbox (they closed its tab, or ask where it is), or wants you to use it.
Run:
```bash
plannotator inbox --open
```
Behavior:
1. Run the command. It opens the Inbox in the person's browser, starting it in the background when it is not running, prints the address and returns at once.
2. Tell the person the address in one sentence. When it also says no browser opened (a remote session), pass on how it says to reach the Inbox.View the complete source on GitHubplannotator-last
When your agent uses it
Open Plannotator on the latest rendered assistant message and use the returned annotations to revise that message or continue.
What it loads into context
Frontmatter
38 tokensAlways available to the agent
SKILL.md
266 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore1,252 bytesSKILL.mdcore1,252 bytesagents/openai.yamlasset166 bytes
Read SKILL.md
# Plannotator Last
Use this skill when the user wants to annotate the latest assistant response in Plannotator.
Do not send a commentary/status message before running the command. The command
targets the latest rendered assistant response, so a preamble can mistakenly become the
thing being annotated.
Run:
```bash
plannotator last
```
View the complete source on GitHubplannotator-review
When your agent uses it
Open Plannotator's browser-based code review UI for the current worktree, another directory, or a pull request URL, then act on the feedback that comes back.
What it loads into context
Frontmatter
50 tokensAlways available to the agent
SKILL.md
334 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore1,537 bytesSKILL.mdcore1,537 bytesagents/openai.yamlasset170 bytes
Read SKILL.md
# Plannotator Review
Use this skill when the user wants to review current code changes in Plannotator instead of reading a diff inline.
Run:
```bash
plannotator review [--base <ref>] [--diff-type <type>] [directory-or-pr-url]
```
Reviewing one layer of a stacked branch? Pass `--base <the branch immediately below yours>` so the review shows only what this layer adds, instead of everything since `main`. Both flags are session-only (the reviewer can change either in the UI; nothing is persisted) and git-only.
To review another repository or worktree, pass its directory (relative to the current session or absolute), e.g. `plannotator review ../feature-worktree`. Quote paths containing spaces. Feedback names the selected directory; apply changes there.
View the complete source on GitHubplannotator-compound
When your agent uses it
Analyze a user's Plannotator plan archive to extract denial patterns, feedback taxonomy, evolution over time, and actionable prompt improvements — then produce a polished HTML dashboard report. Falls back to Claude Code ExitPlanMode denial reasons when Plannotator data is unavailable.
What it loads into context
Frontmatter
77 tokensAlways available to the agent
SKILL.md
6,210 tokensWhen the skill is activated
Reference documents
2,058 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Source Selection
- Phase 0: Locate Plans & Check for Previous Reports
- Phase 1: Inventory
- Phase 2: Map — Parallel Extraction
- Phase 3: Reduce — Pattern Analysis
- Phase 4: Generate the HTML Dashboard
- Phase 5: Summary
- Phase 6: Improvement Hook
- Important Notes
Scripts executed separately
scripts/extract_exit_plan_mode_outcomes.py
Files
SKILL.mdcore27,793 bytesSKILL.mdcore27,793 bytesSKILL.mdcore27,793 bytesSKILL.mdcore27,793 bytesSKILL.mdcore27,793 bytesassets/report-template.htmlasset30,799 bytesreferences/claude-code-fallback.mddoc9,379 bytesscripts/extract_exit_plan_mode_outcomes.pyruns26,634 bytes
Read SKILL.md
# Compound Planning Analysis
You are conducting a comprehensive research analysis of a user's Plannotator plan
archive. The goal: extract patterns from their denied plans, reduce
them into actionable insights, and produce an elegant HTML dashboard report.
This is a multi-phase process. Each phase must complete fully before the next begins.
Research integrity is paramount — every file must be read, no skipping.
## Source Selection
Before starting the analysis, determine which data source is available.
1. **Plannotator mode (first-class)** — Find the Plannotator data directory,View the complete source on GitHubplannotator-setup-goal
When your agent uses it
Turn an idea or objective into a goal package for /goal. Interviews the user, builds a reviewed fact sheet via Plannotator, then explores the codebase to produce an execution plan.
What it loads into context
Frontmatter
58 tokensAlways available to the agent
SKILL.md
2,126 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Phases
Scripts executed separately
SKILL.test.ts
Files
SKILL.mdcore9,602 bytesSKILL.mdcore9,602 bytesSKILL.mdcore9,602 bytesSKILL.mdcore9,602 bytesSKILL.mdcore9,602 bytesSKILL.mdcore9,602 bytesSKILL.mdcore9,602 bytesSKILL.test.tsruns2,021 bytesagents/openai.yamlasset193 bytes
Read SKILL.md
# Setup Goal
Turn an idea into a goal package at `goals/<slug>/` through structured discovery, user interview, and codebase exploration.
## Phases
### 1. Rearticulate
State back what the user wants in your own words. If the conversation already has rich context, summarize it. If the goal is bare or vague, do minimal shallow exploration of the codebase to ground your understanding. Keep it to 2-3 sentences. Wait for the user to confirm or correct before continuing.
Create the goal directory once the slug is clear:
```bash
mkdir -p goals/<slug>View the complete source on GitHubplannotator-visual-explainer
When your agent uses it
Generate self-contained HTML visualizations with Plannotator theming. Use for implementation plans, PR explainers, architecture diagrams, data tables, slide decks, and any visual explanation of technical concepts. Plans and PR explainers follow Plannotator's prescriptive approach; all other visual content delegates to nicobailon/visual-explainer.
What it loads into context
Frontmatter
98 tokensAlways available to the agent
SKILL.md
1,658 tokensWhen the skill is activated
Reference documents
16,628 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
- Route by content type
- Delivery
- Plan path
- PR path
- Visual explainer path
- Design philosophy (all paths)
Scripts executed separately
SKILL.test.ts
Files
SKILL.mdcore7,300 bytesSKILL.mdcore7,300 bytesSKILL.mdcore7,300 bytesSKILL.test.tsruns8,845 bytesreferences/design-system.mddoc13,200 bytesreferences/diagram-shell.mddoc4,051 bytesreferences/pr-components.mddoc15,984 bytesreferences/svg-patterns.mddoc13,518 bytesreferences/theme-override.mddoc7,964 bytes
Read SKILL.md
# Plannotator Visual Explainer
Three paths depending on content type. Each has its own references and structure.
## Route by content type
**Implementation plan, design doc, or proposal** → Follow the [Plan path](#plan-path). Read `references/design-system.md` and `references/svg-patterns.md`. Prescriptive structure.
**PR explainer, diff review, or code change walkthrough** → Follow the [PR path](#pr-path). Read `references/design-system.md` and `references/pr-components.md`. Prescriptive structure.
**Everything else** (architecture diagrams, data tables, slide decks, project recaps, general visual explanations) → Follow the [Visual explainer path](#visual-explainer-path). Delegates to nicobailon/visual-explainer with Plannotator theme tokens.
## Delivery
View the complete source on GitHubplannotator-annotate
When your agent uses it
Open Plannotator's annotation UI for a file, folder, or URL, then address the returned annotations.
What it loads into context
Frontmatter
41 tokensAlways available to the agent
SKILL.md
221 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore867 bytesSKILL.mdcore867 bytes
Read SKILL.md
# Plannotator Annotate (Mistral Vibe)
Run:
```bash
PLANNOTATOR_ORIGIN=mistral-vibe plannotator annotate $ARGUMENTS
```
`$ARGUMENTS` should be a markdown or plain-text config file path (.md, .txt, .yaml, .json, .toml, .ini, .csv, .log, …), folder path, html file path, or URL.
If the command reports that the arguments could not be resolved to a file, URL, or folder, work out which target the user means and re-run the command yourself with that concrete path or URL.
If the session closes without feedback (the output is empty, or a JSON object with `"decision": "dismissed"`), acknowledge it in one sentence and stop. Do not begin any work: closing the session is not approval.View the complete source on GitHubplannotator-last
When your agent uses it
Open Plannotator on the latest rendered assistant message and use the returned annotations to revise that message or continue.
What it loads into context
Frontmatter
39 tokensAlways available to the agent
SKILL.md
280 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore1,286 bytesSKILL.mdcore1,286 bytes
Read SKILL.md
# Plannotator Last (Mistral Vibe)
Use this skill when the user wants to annotate the latest assistant response in Plannotator.
Do not send a commentary/status message before running the command. The command
targets the latest rendered assistant response, so a preamble can mistakenly become the
thing being annotated.
Run:
```bash
PLANNOTATOR_ORIGIN=mistral-vibe plannotator last
```
View the complete source on GitHubplannotator-review
When your agent uses it
Open Plannotator's browser-based code review UI and address the returned feedback.
What it loads into context
Frontmatter
33 tokensAlways available to the agent
SKILL.md
185 tokensWhen the skill is activated
Reference documents
0 tokensLoaded on request
Token counts are estimates. Scripts run separately; they are not counted as reference context.
The playbook
Files
SKILL.mdcore809 bytesSKILL.mdcore809 bytesSKILL.mdcore809 bytes
Read SKILL.md
# Plannotator Review (Mistral Vibe)
Run:
```bash
PLANNOTATOR_ORIGIN=mistral-vibe plannotator review
```
You may append one directory or PR URL:
```bash
PLANNOTATOR_ORIGIN=mistral-vibe plannotator review <pr-url>
PLANNOTATOR_ORIGIN=mistral-vibe plannotator review ../feature-worktree
```View the complete source on GitHubSkills included
- plannotator-annotate
- plannotator-review
- plannotator-annotate
- plannotator-last
- plannotator-review
- plannotator-annotate
- plannotator-inbox
- plannotator-last
- plannotator-review
- plannotator
- plannotator-annotate
- plannotator-inbox
- plannotator-last
- plannotator-review
- plannotator-compound
- plannotator-setup-goal
- plannotator-visual-explainer
- plannotator-annotate
- plannotator-last
- plannotator-review
Repository facts
- License
- Apache-2.0
- Created
- Dec 28, 2025
- Last pushed
- Nov 7, 2026
- Forks
- 745
- Open issues
- 77
- Project activity
- Active
Rank over the last 12 weeks
Now #155 · best #145 · down 7 in 30 days
- #152 on Oct 30
- #153 from Oct 31 to Nov 1
- #154 on Nov 2
- #155 on Nov 3
- #154 from Nov 4 to Nov 6
- #155 since Nov 7
49 earlier periods
- #143 on Aug 2
- #144 on Aug 8
- #143 on Aug 9
- #147 from Aug 10 to Aug 12
- #148 from Aug 13 to Aug 15
- #147 on Aug 16
- #148 from Aug 17 to Aug 20
- #147 on Aug 21
- #146 on Aug 22
- #148 from Aug 23 to Aug 26
- #147 from Aug 27 to Aug 29
- #146 from Aug 30 to Aug 31
- #147 on Sep 1
- #145 on Sep 2
- #146 on Sep 3
- #145 on Sep 4
- #146 on Sep 5
- #145 on Sep 6
- #146 from Sep 7 to Sep 10
- #145 on Sep 11
- #146 from Sep 12 to Sep 14
- #148 on Sep 15
- #147 on Sep 16
- #148 from Sep 17 to Sep 18
- #147 on Sep 19
- #148 from Sep 20 to Sep 21
- #149 from Sep 22 to Sep 23
- #148 on Sep 24
- #149 on Sep 25
- #148 from Sep 26 to Sep 27
- #149 on Sep 28
- #148 from Sep 29 to Sep 30
- #149 from Oct 1 to Oct 2
- #148 on Oct 3
- #147 on Oct 4
- #149 on Oct 5
- #147 on Oct 6
- #149 on Oct 7
- #148 from Oct 8 to Oct 11
- #149 on Oct 12
- #150 on Oct 13
- #151 on Oct 14
- #149 on Oct 15
- #148 on Oct 16
- #149 on Oct 17
- #150 from Oct 18 to Oct 23
- #151 from Oct 24 to Oct 25
- #150 on Oct 28
- #151 on Oct 29
Before you install
Network or broad shellAutomated signals, not a guarantee
Checked Nov 3, 2026
Not fully analyzed: some files were too long, unreadable or missing. This never lowers the level.
Show 41 notes
apps/kiro-cli/skills/plannotator-annotate/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/kiro-cli/skills/plannotator-review/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/kiro-cli/skills/plannotator-review/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/kiro-cli/skills/plannotator-review/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/qwen-code/skills/plannotator-annotate/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/qwen-code/skills/plannotator-annotate/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/qwen-code/skills/plannotator-last/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/qwen-code/skills/plannotator-review/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzedapps/skills/core/plannotator/SKILL.md:1Analysis incomplete: Referenced executable target unavailable; not analyzed
- No broad tool permissions
- 5 dangerous shell commandsin 3 files: apps/hook/hooks/mod/launch.ts:243 apps/hook/hooks/mod/inbox.ts:426 apps/hook/hooks/mod/plan.ts:142
- 320 network referencesin 28 files: apps/hook/hooks/mod/inbox.test.ts:137 apps/hook/hooks/mod/controller.test.ts:21 apps/hook/hooks/mod/bridge.test.ts:74 and 25 more
- No hidden or obfuscated text
- 1 instruction override signalin 1 file: plannotator/SKILL.md:81
- 43 executable scriptsin 43 files: apps/hook/hooks/mod/bridge.test.ts:1 apps/hook/hooks/mod/bridge.ts:1 apps/hook/hooks/mod/controller.test.ts:1 and 40 more
- 4 references to secretsin 4 files: apps/hook/hooks/mod/controller.test.ts:99 apps/hook/hooks/mod/inbox-contract.ts:437 apps/hook/hooks/mod/inbox-default-tools.ts:69 and 1 more
- No requests to vote in Hot
Show all 373 signals by file
apps/hook/.claude-plugin/plugin.json
- Network accessline 6
"name": "backnotprop" }, "repository": "https://github.com/backnotprop/plannotator", - Network accessline 7
}, "repository": "https://github.com/backnotprop/plannotator", "keywords": ["planning", "review", "hooks", "ExitPlanMode", "collaboration"] - Network accessline 8
"repository": "https://github.com/backnotprop/plannotator",
apps/hook/hooks/mod/bridge.test.ts
- Executable scriptline 1
Executable file - Network accessline 74
[Credential-related source omitted] - Network accessline 75
[Credential-related source omitted] - Network accessline 76
[Credential-related source omitted] - Network accessline 107
[Credential-related source omitted] - Network accessline 108
[Credential-related source omitted] - Network accessline 109
[Credential-related source omitted] - Network accessline 135
[Credential-related source omitted] - Network accessline 136
[Credential-related source omitted] - Network accessline 137
[Credential-related source omitted] - Network accessline 160
turns.onPromptEntered({ text: 'Review PR 12.', fromUs: false, originKind: 'plugin' }) turns.onTurnStart('plugin-turn', 'The workspaces plugin sent a message: Review PR 12.') const client = createBridge({ host, baseUrl: 'http://127.0 - Network accessline 161
[Credential-related source omitted] - Network accessline 162
[Credential-related source omitted] - Network accessline 180
[Credential-related source omitted] - Network accessline 181
[Credential-related source omitted] - Network accessline 182
[Credential-related source omitted] - Network accessline 210
[Credential-related source omitted] - Network accessline 211
[Credential-related source omitted] - Network accessline 212
[Credential-related source omitted] - Network accessline 237
[Credential-related source omitted] - Network accessline 238
[Credential-related source omitted] - Network accessline 239
[Credential-related source omitted] - Network accessline 277
[Credential-related source omitted] - Network accessline 278
[Credential-related source omitted] - Network accessline 279
[Credential-related source omitted] - Network accessline 306
[Credential-related source omitted] - Network accessline 307
[Credential-related source omitted] - Network accessline 308
[Credential-related source omitted] - Network accessline 316
describe('how a bridge loop ends', () => { const POLL = 'http://127.0.0.1:4321/api/ai/bridge/poll' - Network accessline 317
const POLL = 'http://127.0.0.1:4321/api/ai/bridge/poll' - Network accessline 319
[Credential-related source omitted] - Network accessline 320
[Credential-related source omitted]
apps/hook/hooks/mod/bridge.ts
- Executable scriptline 1
Executable file - Network accessline 93
/** e.g. `http://127.0.0.1:4321`; always the loopback literal. */ - Network accessline 102
export function bridgeBaseUrl(port: number): string { return `http://127.0.0.1:${port}` - Network accessline 103
return `http://127.0.0.1:${port}` - Network accessline 163
if (events.length === 0) return try { const response = await host.fetch(`${base}${BRIDGE_EVENT_PATH}`, { - Network accessline 164
try { const response = await host.fetch(`${base}${BRIDGE_EVENT_PATH}`, { method: 'POST', - Network accessline 165
const response = await host.fetch(`${base}${BRIDGE_EVENT_PATH}`, { - Network accessline 312
let response try { response = await host.fetch(`${base}${BRIDGE_POLL_PATH}`, { - Network accessline 313
try { response = await host.fetch(`${base}${BRIDGE_POLL_PATH}`, { method: 'POST', - Network accessline 314
response = await host.fetch(`${base}${BRIDGE_POLL_PATH}`, {
apps/hook/hooks/mod/controller.test.ts
- Executable scriptline 1
Executable file - Network accessline 21
function serveOnLaunch(host: FakeHost, port = 4321) { host.onRun = (call) => { if (isLaunch(call)) host.files.set(`${launchDirOf(call)}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port })}\n`) - Network accessline 22
host.onRun = (call) => { if (isLaunch(call)) host.files.set(`${launchDirOf(call)}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port })}\n`) } - Network accessline 23
if (isLaunch(call)) host.files.set(`${launchDirOf(call)}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port })}\n`) - Access to secretsline 99
[Credential-related source omitted] - Network accessline 406
const text = await mod.runCommand('review', 'https://github.com/o/r/pull/412 --base "feature one"') - Network accessline 408
expect(text).toContain('PR #412') expect(text).toContain('http://localhost:5555') - Network accessline 409
expect(text).toContain('http://localhost:5555') - Network accessline 410
expect(launches(host)[0]?.argv.slice(5)).toEqual(['plannotator', 'review', 'https://github.com/o/r/pull/412', '--base', 'feature one']) - Network accessline 587
expect(byTool?.argv.slice(5)).toEqual(byCommand?.argv.slice(5)) expect(Object.keys(byTool?.env ?? {}).sort()).toEqual(Object.keys(byCommand?.env ?? {}).sort()) expect('text' in answer && answer.text).toContain('http://localhost:6060 - Network accessline 588
expect(Object.keys(byTool?.env ?? {}).sort()).toEqual(Object.keys(byCommand?.env ?? {}).sort()) expect('text' in answer && answer.text).toContain('http://localhost:6060') expect('text' in answer && answer.text).toContain('End your t - Network accessline 589
expect('text' in answer && answer.text).toContain('http://localhost:6060') - Network accessline 674
serveOnLaunch(host) const mod = new PlannotatorMod(host, SESSION) await mod.runTool({ action: 'review', target: 'https://github.com/o/r/pull/7', gate: true }) - Network accessline 675
const mod = new PlannotatorMod(host, SESSION) await mod.runTool({ action: 'review', target: 'https://github.com/o/r/pull/7', gate: true }) await mod.runTool({ action: 'review', target: 'https://github.com/o/r/pull/8' }) - Network accessline 676
await mod.runTool({ action: 'review', target: 'https://github.com/o/r/pull/7', gate: true }) - Network accessline 677
await mod.runTool({ action: 'review', target: 'https://github.com/o/r/pull/8' }) - Network accessline 678
const [gated, plain] = launches(host) const status = (n: number) => ({ surface: 'review', decision: 'annotated', noop: true, platform: true, message: `Pull request approved on GitHub: https://github.com/o/r/pull/${n}` }) decide(host - Network accessline 679
const status = (n: number) => ({ surface: 'review', decision: 'annotated', noop: true, platform: true, message: `Pull request approved on GitHub: https://github.com/o/r/pull/${n}` }) - Network accessline 684
expect(host.submits).toHaveLength(1) expect(host.submits[0]).toMatch(/^Plannotator: .+ \(pn-[0-9a-f]{6}\) — Review posted\./) expect(host.submits[0]).toContain('Pull request approved on GitHub: https://github.com/o/r/pull/7') - Network accessline 685
expect(host.submits[0]).toMatch(/^Plannotator: .+ \(pn-[0-9a-f]{6}\) — Review posted\./) expect(host.submits[0]).toContain('Pull request approved on GitHub: https://github.com/o/r/pull/7') expect(host.logs.some((line) => line.includ - Network accessline 686
expect(host.submits[0]).toContain('Pull request approved on GitHub: https://github.com/o/r/pull/7') - Network accessline 1088
' a.md -> /r/a.md', ' b.md -> /r/b.md', 'Re-run with exactly one target: plannotator annotate <file.md | file.txt | file.html | https://... | folder/>', - Network accessline 1089
' b.md -> /r/b.md', 'Re-run with exactly one target: plannotator annotate <file.md | file.txt | file.html | https://... | folder/>', ].join('\n') - Network accessline 1090
'Re-run with exactly one target: plannotator annotate <file.md | file.txt | file.html | https://... | folder/>', - Network accessline 1118
} const mod = new PlannotatorMod(host, SESSION) const answer = await mod.runTool({ action: 'annotate', target: ['a.md', 'https://example.com'] }) - Network accessline 1119
const mod = new PlannotatorMod(host, SESSION) const answer = await mod.runTool({ action: 'annotate', target: ['a.md', 'https://example.com'] }) expect('deny' in answer && answer.deny).toContain(PLANNOTATOR_BUNDLE_HINT_LINE) - Network accessline 1120
const answer = await mod.runTool({ action: 'annotate', target: ['a.md', 'https://example.com'] }) - Network accessline 1633
const host = fakeHost() host.onRun = (call) => call.argv[1] === 'inbox' ? { exitCode: 0, stdout: 'http://localhost:59812/\n', stderr: '' } : undefined - Network accessline 1634
host.onRun = (call) => call.argv[1] === 'inbox' ? { exitCode: 0, stdout: 'http://localhost:59812/\n', stderr: '' } : undefined const mod = new PlannotatorMod(host, SESSION) - Network accessline 1635
call.argv[1] === 'inbox' ? { exitCode: 0, stdout: 'http://localhost:59812/\n', stderr: '' } : undefined - Network accessline 1643
expect(call?.argv).toEqual(['plannotator', 'inbox', '--open']) expect(call?.env?.PLANNOTATOR_DATA_DIR).toBe('/data') expect(text).toContain('http://localhost:59812/') - Network accessline 1645
expect(text).toContain('http://localhost:59812/') - Network accessline 1650
test('over SSH the CLI opens no browser and says how to reach the Inbox: the answer passes that on', async () => { const host = fakeHost() host.onRun = () => ({ exitCode: 0, stdout: 'http://localhost:59812/\n', stderr: 'No browser o - Network accessline 1651
const host = fakeHost() host.onRun = () => ({ exitCode: 0, stdout: 'http://localhost:59812/\n', stderr: 'No browser opened: this is a remote session. Forward the port (ssh -L 59812:127.0.0.1:59812 <this host>) and open the URL, or run p - Network accessline 1652
host.onRun = () => ({ exitCode: 0, stdout: 'http://localhost:59812/\n', stderr: 'No browser opened: this is a remote session. Forward the port (ssh -L 59812:127.0.0.1:59812 <this host>) and open the URL, or run plannotator inbox --tailscale - Network accessline 1653
const { text } = await new PlannotatorMod(host, SESSION).openInbox() expect(text).toContain('http://localhost:59812/') expect(text).toContain('ssh -L 59812:127.0.0.1:59812') - Network accessline 1654
expect(text).toContain('http://localhost:59812/')
apps/hook/hooks/mod/controller.ts
- Executable scriptline 1
Executable file - Network accessline 1016
if (!launch.port || !launch.bridgeToken) return null try { const response = await this.host.fetch(`${bridgeBaseUrl(launch.port)}${HOST_STATUS_PATH}`, { - Network accessline 1017
try { const response = await this.host.fetch(`${bridgeBaseUrl(launch.port)}${HOST_STATUS_PATH}`, { method: 'GET', - Network accessline 1018
const response = await this.host.fetch(`${bridgeBaseUrl(launch.port)}${HOST_STATUS_PATH}`, { - Network accessline 1077
} const response = await this.host .fetch(`${bridgeBaseUrl(launch.port)}${HOST_CLOSE_PATH}`, { - Network accessline 1078
const response = await this.host .fetch(`${bridgeBaseUrl(launch.port)}${HOST_CLOSE_PATH}`, { method: 'POST', - Network accessline 1079
.fetch(`${bridgeBaseUrl(launch.port)}${HOST_CLOSE_PATH}`, {
apps/hook/hooks/mod/delivery.test.ts
- Executable scriptline 1
Executable file - Network accessline 40
test('a review posted to the PR platform logs and suggests the follow-up', () => { const delivery = deliveryFor( record({ surface: 'review', noop: true, platform: true, message: 'Pull request reviewed on GitHub: https://x/pull/412 - Network accessline 41
const delivery = deliveryFor( record({ surface: 'review', noop: true, platform: true, message: 'Pull request reviewed on GitHub: https://x/pull/412' }), { ...CONTEXT, subject: 'PR #412' }, - Network accessline 42
record({ surface: 'review', noop: true, platform: true, message: 'Pull request reviewed on GitHub: https://x/pull/412' }), - Network accessline 50
test('a gated review posted to the PR platform is a turn with its status line; ungated it logs', () => { const status = 'Pull request approved on GitHub: https://x/pull/412' - Network accessline 51
const status = 'Pull request approved on GitHub: https://x/pull/412' - Network accessline 63
const lines = [ ...['Pull request', 'Merge request'].flatMap((kind) => ['approved', 'reviewed'].map((verb) => `${kind} ${verb} on GitLab: https://x/-/merge_requests/9`), - Network accessline 64
...['Pull request', 'Merge request'].flatMap((kind) => ['approved', 'reviewed'].map((verb) => `${kind} ${verb} on GitLab: https://x/-/merge_requests/9`), ), - Network accessline 65
['approved', 'reviewed'].map((verb) => `${kind} ${verb} on GitLab: https://x/-/merge_requests/9`), - Network accessline 66
), 'Changes requested on GitHub: https://x/pull/412', 'Pull request reviewed on Bitbucket', - Network accessline 67
'Changes requested on GitHub: https://x/pull/412',
apps/hook/hooks/mod/delivery.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/enabled.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/enabled.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/globals.d.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/host.ts
apps/hook/hooks/mod/inbox-ask.test.ts
- Executable scriptline 1
Executable file - Network accessline 55
servers.push(server) const client = new Client({ name: 'mod-inbox-ask-test', version: '1.0.0' }) await client.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${server.port}/mcp`))) - Network accessline 56
const client = new Client({ name: 'mod-inbox-ask-test', version: '1.0.0' }) await client.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${server.port}/mcp`))) clients.push(client) - Network accessline 57
await client.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${server.port}/mcp`))) - Network accessline 398
[Credential-related source omitted] - Network accessline 399
[Credential-related source omitted] - Network accessline 400
const ASK_POLL = `http://127.0.0.1:4321${inboxAskBridgeBase(SESSION)}${BRIDGE_POLL_PATH}` - Network accessline 502
[Credential-related source omitted] - Network accessline 504
[Credential-related source omitted]
apps/hook/hooks/mod/inbox-contract.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/inbox-contract.ts
apps/hook/hooks/mod/inbox-default-tools.test.ts
- Executable scriptline 1
Executable file - Network accessline 29
test("is exactly what a real Inbox's /mcp tools/list answers (run scripts/sync-mod-inbox-tools.ts when it is not)", async () => { const response = await fetch(`http://127.0.0.1:${inbox.port}/mcp`, { - Network accessline 30
const response = await fetch(`http://127.0.0.1:${inbox.port}/mcp`, {
apps/hook/hooks/mod/inbox-default-tools.ts
- Executable scriptline 1
Executable file - Network accessline 13
"inputSchema": { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 14
"type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { - Network accessline 15
"$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 18
"type": "string", "minLength": 1, "description": "The message, markdown. Question blocks render as answerable cards. Blocks fenced as `mermaid` or `dot` draw as diagrams; one fenced as `html` draws as a live, sandboxed p - Network accessline 19
"minLength": 1, "description": "The message, markdown. Question blocks render as answerable cards. Blocks fenced as `mermaid` or `dot` draw as diagrams; one fenced as `html` draws as a live, sandboxed page in the message (chart, S - Network accessline 20
"description": "The message, markdown. Question blocks render as answerable cards. Blocks fenced as `mermaid` or `dot` draw as diagrams; one fenced as `html` draws as a live, sandboxed page in the message (chart, SVG, mock; https libraries - Access to secretsline 69
[Credential-related source omitted] - Network accessline 85
"inputSchema": { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 86
"type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { - Network accessline 87
"$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 166
"inputSchema": { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 167
"type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { - Network accessline 168
"$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 199
"inputSchema": { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 200
"type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { - Network accessline 201
"$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 221
"inputSchema": { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 222
"type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { - Network accessline 223
"$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 316
"inputSchema": { "type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", - Network accessline 317
"type": "object", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": {}, - Network accessline 318
"$schema": "https://json-schema.org/draft/2020-12/schema",
apps/hook/hooks/mod/inbox-loaded.test.ts
apps/hook/hooks/mod/inbox-reminder-custom.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/inbox-reminder.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/inbox-session-label.test.ts
apps/hook/hooks/mod/inbox-session-project.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/inbox-session-threads.test.ts
- Executable scriptline 1
Executable file - Network accessline 12
[Credential-related source omitted] - Network accessline 13
[Credential-related source omitted] - Network accessline 49
} expect(await readSessionThreads(host, DATA, 'sess-1', '/work', TOOL)).toBeNull() expect(urls).toEqual(['http://127.0.0.1:4100/api/inbox/health']) - Network accessline 50
expect(await readSessionThreads(host, DATA, 'sess-1', '/work', TOOL)).toBeNull() expect(urls).toEqual(['http://127.0.0.1:4100/api/inbox/health']) }) - Network accessline 51
expect(urls).toEqual(['http://127.0.0.1:4100/api/inbox/health']) - Network accessline 61
} expect(await readSessionThreads(host, DATA, 'sess-1', '/work', TOOL)).toBeNull() expect(urls).toEqual(['http://127.0.0.1:4100/api/inbox/health']) - Network accessline 62
expect(await readSessionThreads(host, DATA, 'sess-1', '/work', TOOL)).toBeNull() expect(urls).toEqual(['http://127.0.0.1:4100/api/inbox/health']) }) - Network accessline 63
expect(urls).toEqual(['http://127.0.0.1:4100/api/inbox/health'])
apps/hook/hooks/mod/inbox.test.ts
- Executable scriptline 1
Executable file - Network accessline 137
async function thread(w: World, threadId: string): Promise<{ subject: string; thread_name: string | null; project: { root: string }; messages: ThreadMessage[] }> { const response = await fetch(`http://127.0.0.1:${registry(w).port}/api/inb - Network accessline 138
const response = await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${threadId}`) - Network accessline 151
async function personSends(w: World, messageId: string, words: string): Promise<string> { const { port } = registry(w) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 152
const { port } = registry(w) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${messageId}/re - Network accessline 153
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 154
const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${messageId}/reply`, { - Network accessline 155
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession, idempotency_key: `window-${messageId}-${words.length}`, words }), - Network accessline 156
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 201
const listed = await fetch(`http://127.0.0.1:${registry(w).port}/mcp`, { - Network accessline 294
const delivered = await waitFor('the delivery record', async () => (await thread(w, asked.thread_id)).messages.find((m) => m.id === replyId)?.delivery) expect(delivered).toMatchObject({ state: 'delivered', host: 'claude-code', session: - Network accessline 295
expect(delivered).toMatchObject({ state: 'delivered', host: 'claude-code', session: 'session-wake' }) const list = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads`)).json()) as { sections: { id: string; threa - Network accessline 296
const list = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads`)).json()) as { sections: { id: string; threads: { thread_id: string; sent: { checked_at: string | null } | null }[] }[] } - Network accessline 313
const sent = await send(session, w, 'Merged the refund fix. CI is green on main; nothing needs you here.') const { port } = registry(w) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { se - Network accessline 314
const { port } = registry(w) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } const pressed = Date.now() - Network accessline 315
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 316
const pressed = Date.now() const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${sent.message_id}/ack`, { method: 'POST', - Network accessline 317
const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${sent.message_id}/ack`, { - Network accessline 318
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession }), - Network accessline 319
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 407
const poll = await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/bridge/poll`, { - Network accessline 540
[Credential-related source omitted] - Network accessline 541
[Credential-related source omitted] - Network accessline 542
[Credential-related source omitted] - Network accessline 566
const { port } = registry(w) const live = await waitFor('both sessions live', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { - Network accessline 567
const live = await waitFor('both sessions live', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { sessions: { session: string; host: string - Network accessline 568
const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { - Network accessline 579
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 580
const post = (session: string, body: string, key: string) => fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/message`, { method: 'POST', - Network accessline 581
fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/message`, { - Network accessline 582
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession, session, body, idempotency_key: key }), - Network accessline 583
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 617
const before = (await thread(w, asked.thread_id)).messages.length await waitFor('session-other no longer live', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/session - Network accessline 618
await waitFor('session-other no longer live', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { sessions: { session: string }[] } return model - Network accessline 619
const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { sessions: { session: string }[] } - Network accessline 636
const { port } = registry(w) await waitFor('the other session live', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { sessions: { session: stri - Network accessline 637
await waitFor('the other session live', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { sessions: { session: string }[] } return model.sessi - Network accessline 638
const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions`)).json()) as { sessions: { session: string }[] } - Network accessline 639
return model.sessions.some((s) => s.session === 'session-taker') ? true : null }) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 640
}) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } const words = 'Retry with the same key.' - Network accessline 641
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 642
const words = 'Retry with the same key.' const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${asked.message_id}/reply`, { method: 'POST', - Network accessline 643
const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${asked.message_id}/reply`, { - Network accessline 644
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession, idempotency_key: 'ended-1', words, to: { host: 'claude-code', sessi - Network accessline 645
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 676
await waitFor('the tagged session taggable', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/taggable`)).json()) as { sessions: { session: string; taggable: boolean }[] } - Network accessline 677
const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/taggable`)).json()) as { sessions: { session: string; taggable: boolean }[] } - Network accessline 681
await owner.startTurn('Refactor the webhook handler.') const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 682
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 683
const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${asked.message_id}/reply`, { - Network accessline 684
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ - Network accessline 685
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 736
const listed = await waitFor('the session in the live list', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/sessions`)).json()) as { - Network accessline 737
const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/sessions`)).json()) as { - Network accessline 745
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 746
const words = 'Idea: show which session wrote each thread.\n\nA small chip on each row would do.' const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages`, { method: 'POST', - Network accessline 747
const response = await fetch(`http://127.0.0.1:${port}/api/inbox/messages`, { - Network accessline 748
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession, to: { host: 'claude-code', session: 'session-compose' }, body: word - Network accessline 749
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 790
const connection = await waitFor('the busy connection', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-send-now`)).json()) as { - Network accessline 791
const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-send-now`)).json()) as { - Network accessline 803
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 804
const pressed = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${replyId}/send-now`, { - Network accessline 805
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession }), - Network accessline 806
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 837
const replyId = await personSends(w, asked.message_id, 'Fail the job and alert.') await waitFor('the busy connection', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/ - Network accessline 838
await waitFor('the busy connection', async () => { const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-late`)).json()) as { asker: { connection: { busy: boole - Network accessline 839
const model = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-late`)).json()) as { - Network accessline 842
return model.asker.connection?.busy === true }) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 843
}) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } expect( - Network accessline 844
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 845
expect( ( await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${replyId}/send-now`, { - Network accessline 846
( await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${replyId}/send-now`, { method: 'POST', - Network accessline 847
await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${replyId}/send-now`, { - Network accessline 848
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession }), - Network accessline 849
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 865
async function pressSendNow(w: World, replyId: string): Promise<void> { const { port } = registry(w) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 866
const { port } = registry(w) const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } const pressed = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${replyId}/s - Network accessline 867
const health = (await (await fetch(`http://127.0.0.1:${port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 868
const pressed = await fetch(`http://127.0.0.1:${port}/api/inbox/messages/${replyId}/send-now`, { - Network accessline 869
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, body: JSON.stringify({ serverSession: health.serverSession }), - Network accessline 870
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${port}` }, - Network accessline 877
async function busyKnown(w: World, threadId: string, session: string): Promise<void> { await waitFor('the busy connection', async () => { const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${ - Network accessline 878
await waitFor('the busy connection', async () => { const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${threadId}/sessions?asker=${session}`)).json()) as { asker: { connection: { busy: bo - Network accessline 879
const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${threadId}/sessions?asker=${session}`)).json()) as { - Network accessline 939
await waitFor('the busy connection without Send now', async () => { const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-ask`)).json()) as { - Network accessline 940
const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-ask`)).json()) as { - Network accessline 943
return model.asker.connection?.busy === true && model.asker.connection.send_now === false }) const health = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 944
}) const health = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/health`)).json()) as { serverSession: string } const refused = await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/messages/${replyId}/sen - Network accessline 945
const health = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 946
const refused = await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/messages/${replyId}/send-now`, { - Network accessline 947
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${registry(w).port}` }, body: JSON.stringify({ serverSession: health.serverSession }), - Network accessline 948
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${registry(w).port}` }, - Network accessline 976
const replyId = await personSends(w, asked.message_id, 'Retry with the same key.') await waitFor('the busy connection without Send now', async () => { const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inb - Network accessline 977
await waitFor('the busy connection without Send now', async () => { const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-other-plugin`)).json()) as { - Network accessline 978
const model = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/threads/${asked.thread_id}/sessions?asker=session-other-plugin`)).json()) as { - Network accessline 981
return model.asker.connection?.busy === true && model.asker.connection.send_now === false }) const health = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 982
}) const health = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/health`)).json()) as { serverSession: string } const refused = await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/messages/${replyId}/sen - Network accessline 983
const health = (await (await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/health`)).json()) as { serverSession: string } - Network accessline 984
const refused = await fetch(`http://127.0.0.1:${registry(w).port}/api/inbox/messages/${replyId}/send-now`, { - Network accessline 985
method: 'POST', headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${registry(w).port}` }, body: JSON.stringify({ serverSession: health.serverSession }), - Network accessline 986
headers: { 'Content-Type': 'application/json', Origin: `http://127.0.0.1:${registry(w).port}` },
apps/hook/hooks/mod/inbox.ts
- Executable scriptline 1
Executable file - Network accessline 275
const health = await host.fetch(`http://127.0.0.1:${registry.port}/api/inbox/health`, { method: 'GET', headers: {} }).catch(() => null) - Dangerous shell operationline 426
'rm -rf "$d"', - Network accessline 449
async function mcpCall(host: Host, port: number, method: string, params: Record<string, unknown>): Promise<{ result?: unknown; error?: { message?: string } } | null> { const response = await host.fetch(`http://127.0.0.1:${port}/mcp`, { - Network accessline 450
const response = await host.fetch(`http://127.0.0.1:${port}/mcp`, { - Network accessline 757
private async isRunning(registry: InboxRegistryView): Promise<boolean> { const response = await this.host .fetch(`http://127.0.0.1:${registry.port}/api/inbox/health`, { method: 'GET', headers: {} }) - Network accessline 758
const response = await this.host .fetch(`http://127.0.0.1:${registry.port}/api/inbox/health`, { method: 'GET', headers: {} }) .catch(() => null) - Network accessline 759
.fetch(`http://127.0.0.1:${registry.port}/api/inbox/health`, { method: 'GET', headers: {} }) - Network accessline 927
if (!registry) return null return this.host .fetch(`http://127.0.0.1:${registry.port}${path}`, { - Network accessline 928
return this.host .fetch(`http://127.0.0.1:${registry.port}${path}`, { method: 'POST', - Network accessline 929
.fetch(`http://127.0.0.1:${registry.port}${path}`, {
apps/hook/hooks/mod/launch.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/launch.ts
- Executable scriptline 1
Executable file - Dangerous shell operationline 243
'for f in "$@"; do rm -f "$dir/$f"; done', - Dangerous shell operationline 244
`if [ ! -e "$dir/${LAUNCH_FILES.overflow}" ]; then rm -f "$dir/${SETTLED_BY}" "$dir/${SETTLED_DIR}/delivered" "$dir/${SETTLED_DIR}/reported"; rmdir "$dir/${SETTLED_DIR}" 2>/dev/null; rmdir "$dir" 2>/dev/null; fi`, - Dangerous shell operationline 412
return ['/bin/sh', '-c', 'rm -f "$1"', 'plannotator-rm', path]
apps/hook/hooks/mod/plan.ts
- Executable scriptline 1
Executable file - Network accessline 141
export const CLASSIC_PLAN_REVIEW_TEXT = 'Your plannotator CLI is older than the Plannotator plugin and has no non-blocking plan review, so plans open in the classic review, which holds this session until you decide. Update the CLI (curl - - Dangerous shell operationline 142
'Your plannotator CLI is older than the Plannotator plugin and has no non-blocking plan review, so plans open in the classic review, which holds this session until you decide. Update the CLI (curl -fsSL https://plannotator.ai/install.sh | b - Network accessline 142
'Your plannotator CLI is older than the Plannotator plugin and has no non-blocking plan review, so plans open in the classic review, which holds this session until you decide. Update the CLI (curl -fsSL https://plannotator.ai/install.sh | b
apps/hook/hooks/mod/register.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/register.ts
- Executable scriptline 1
Executable file - Network accessline 235
})) }, fetch: (url, init) => $.http.fetch(url, init), - Network accessline 236
}, fetch: (url, init) => $.http.fetch(url, init), abortTurn: (turnId) => $.turn.abort({ turnId }), - Network accessline 237
fetch: (url, init) => $.http.fetch(url, init),
apps/hook/hooks/mod/send-now-engine.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/shell-words.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/tailscale.test.ts
- Executable scriptline 1
Executable file - Network accessline 39
const TAILNET_URL = 'https://studio.tail0000.ts.net:6060/' - Network accessline 74
for (const url of [TAILNET_URL, 'http://localhost:6060']) { - Network accessline 123
expect('text' in answer && answer.text).toContain('Plannotator is starting') const dir = launchDirOf(launches(host)[0]!) host.files.set(`${dir}/ready`, `${JSON.stringify({ url: 'http://localhost:6060', isRemote: false, port: 6060 }) - Network accessline 124
const dir = launchDirOf(launches(host)[0]!) host.files.set(`${dir}/ready`, `${JSON.stringify({ url: 'http://localhost:6060', isRemote: false, port: 6060 })}\n`) await host.tick() - Network accessline 125
host.files.set(`${dir}/ready`, `${JSON.stringify({ url: 'http://localhost:6060', isRemote: false, port: 6060 })}\n`) - Network accessline 133
serveWith(host, { url: 'http://localhost:6060', isRemote: false, port: 6060 }) - Network accessline 147
test('the slash command passes --tailscale on, for last too, and checks nothing', async () => { const host = fakeHost() serveWith(host, { url: 'http://localhost:6060', isRemote: false, port: 6060 }) - Network accessline 148
const host = fakeHost() serveWith(host, { url: 'http://localhost:6060', isRemote: false, port: 6060 }) host.transcript = [{ role: 'assistant', text: 'Hi.' }] - Network accessline 149
serveWith(host, { url: 'http://localhost:6060', isRemote: false, port: 6060 })
apps/hook/hooks/mod/take-over.test.ts
- Executable scriptline 1
Executable file - Network accessline 12
function serveOnLaunch(host: FakeHost, port = 4321) { host.onRun = (call) => { if (isLaunch(call)) host.files.set(`${call.argv[4]}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port })}\n`) - Network accessline 13
host.onRun = (call) => { if (isLaunch(call)) host.files.set(`${call.argv[4]}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port })}\n`) } - Network accessline 14
if (isLaunch(call)) host.files.set(`${call.argv[4]}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port })}\n`) - Access to secretsline 40
[Credential-related source omitted] - Network accessline 46
const bashText = 'result' in answer ? answer.result.stdout : '' expect(withoutSession(bashText)).toBe(withoutSession('text' in viaTool ? viaTool.text : '')) expect(JSON.stringify(answer)).toContain('http://localhost:7070') - Network accessline 47
expect(withoutSession(bashText)).toBe(withoutSession('text' in viaTool ? viaTool.text : '')) expect(JSON.stringify(answer)).toContain('http://localhost:7070') }) - Network accessline 48
expect(JSON.stringify(answer)).toContain('http://localhost:7070')
apps/hook/hooks/mod/take-over.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/targets.test.ts
- Executable scriptline 1
Executable file - Network accessline 31
host.files.set( `${dirOf(call)}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port, ...(target ? { target } : {}) })}\n`, - Network accessline 32
`${dirOf(call)}/ready`, `${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port, ...(target ? { target } : {}) })}\n`, ) - Network accessline 33
`${JSON.stringify({ url: `http://localhost:${port}`, isRemote: false, port, ...(target ? { target } : {}) })}\n`, - Network accessline 128
test('a review switched in place to another PR is headed and targeted as that PR', async () => { const host = fakeHost() serve(host, ['https://github.com/o/r/pull/12']) - Network accessline 129
const host = fakeHost() serve(host, ['https://github.com/o/r/pull/12']) const mod = new PlannotatorMod(host, SESSION) - Network accessline 130
serve(host, ['https://github.com/o/r/pull/12']) - Network accessline 133
await mod.runTool({ action: 'review', target: 'https://github.com/o/r/pull/12' }) - Network accessline 137
message: 'fix the handler', noop: false, target: 'https://github.com/o/r/pull/13', - Network accessline 138
noop: false, target: 'https://github.com/o/r/pull/13', }) - Network accessline 139
target: 'https://github.com/o/r/pull/13', - Network accessline 143
expect(host.submits[0]?.split('\n').slice(0, 2)).toEqual([ expect.stringContaining('Plannotator: PR #13 ('), 'Target: https://github.com/o/r/pull/13', - Network accessline 144
expect.stringContaining('Plannotator: PR #13 ('), 'Target: https://github.com/o/r/pull/13', ]) - Network accessline 145
'Target: https://github.com/o/r/pull/13',
apps/hook/hooks/mod/testing/claude-session.ts
- Executable scriptline 1
Executable file - Network accessline 135
fetch: async (url, init) => { host.fetches.push(`${init.method} ${url}`) const response = await fetch(url, { method: init.method, headers: init.headers, ...(init.body !== undefined ? { body: init.body } : {}) }) - Network accessline 136
host.fetches.push(`${init.method} ${url}`) const response = await fetch(url, { method: init.method, headers: init.headers, ...(init.body !== undefined ? { body: init.body } : {}) }) return { status: response.status, ok: response - Network accessline 137
const response = await fetch(url, { method: init.method, headers: init.headers, ...(init.body !== undefined ? { body: init.body } : {}) })
apps/hook/hooks/mod/testing/fake-host.ts
apps/hook/hooks/mod/tool.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/tool.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/turns.test.ts
- Executable scriptline 1
Executable file
apps/hook/hooks/mod/turns.ts
- Executable scriptline 1
Executable file
apps/skills/core/plannotator/SKILL.md
- Network accessline 28
| Annotate a markdown, text, config, or HTML file | `plannotator annotate <file>` | | Annotate a web page | `plannotator annotate <https-url>` | | Annotate a running local app (dev server) | `plannotator annotate <http://localhost:PORT/>` | - Network accessline 29
| Annotate a web page | `plannotator annotate <https-url>` | | Annotate a running local app (dev server) | `plannotator annotate <http://localhost:PORT/>` | | Pick a file to annotate from a folder | `plannotator annotate <folder/>` | - Network accessline 30
| Annotate a running local app (dev server) | `plannotator annotate <http://localhost:PORT/>` | - Network accessline 66
- `--patch-file <path>` reviews a static caller-supplied unified diff with no repository at all (use `-` to read it from stdin): the session serves the patch as-is with no file-system affordances that need a worktree. It cannot be combined - Network accessline 67
- Pass a directory to review another repo or worktree: `plannotator review ../feature-worktree` or `plannotator review ./backend --diff-type last-commit`. Paths resolve relative to the invoking directory; quote paths containing spaces. A di - Network accessline 68
- PR review (`plannotator review https://github.com/owner/repo/pull/123`, GitLab MR and Bitbucket Cloud PR URLs too) needs an authenticated `gh` or `glab` CLI; Bitbucket Cloud (`https://bitbucket.org/<workspace>/<repo>/pull-requests/<id>`) - Instruction override signalline 81
Plain `annotate` is feedback-only: it shows **Close** but no **Approve** button. When the user asks to review, approve, accept, or gate a generated plan/spec/document saved as a file, call the `plannotator` tool with `"gate": true` if you h - Network accessline 88
- AsciiDoc files: `.adoc`, `.asciidoc`. - HTML files (`.html`, `.htm`): rendered as the raw page by default; `--markdown` converts to markdown instead. `--render-html` is accepted for compatibility; raw rendering is already the default. - U - Network accessline 89
- HTML files (`.html`, `.htm`): rendered as the raw page by default; `--markdown` converts to markdown instead. `--render-html` is accepted for compatibility; raw rendering is already the default. - URLs (`https://...`): fetched and convert - Network accessline 90
- URLs (`https://...`): fetched and converted via Jina Reader by default; `--no-jina` uses plain fetch plus Turndown instead. - Network accessline 91
- Running local apps: a loopback `http://localhost:PORT/` URL whose probe returns HTML opens in live-app mode (annotate the real running page). `--app` forces live mode and fails loudly when it cannot apply; `--static` forces the classic co
apps/skills/extra/plannotator-compound/assets/report-template.html
- Network accessline 5
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Compound Planning — What 370 Files Reveal</title> <link rel="preconnect" href="https://fonts.googleapis.com"> - Network accessline 6
<title>Compound Planning — What 370 Files Reveal</title> <link rel="preconnect" href="https://fonts.googleapis.com"> <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400 - Network accessline 7
<link rel="preconnect" href="https://fonts.googleapis.com"> - Network accessline 8
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> - Network accessline 675
<div class="prompt-header"> <span class="prompt-header-label"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="roun - Network accessline 676
<span class="prompt-header-label"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5">< - Network accessline 677
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19" - Network accessline 679
</span> <button class="copy-btn" onclick="copyPrompt(this)"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" - Network accessline 680
<button class="copy-btn" onclick="copyPrompt(this)"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="r - Network accessline 681
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></re - Network accessline 783
const text = document.getElementById('prompt-content').textContent; navigator.clipboard.writeText(text).then(() => { btn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" strok - Network accessline 784
navigator.clipboard.writeText(text).then(() => { btn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejo - Network accessline 785
btn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.1 - Network accessline 786
btn.classList.add('copied'); setTimeout(() => { btn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-l - Network accessline 787
setTimeout(() => { btn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" - Network accessline 788
btn.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" r
apps/skills/extra/plannotator-compound/scripts/extract_exit_plan_mode_outcomes.py
- Executable scriptline 1
#!/usr/bin/env python3
apps/skills/extra/plannotator-setup-goal/SKILL.md
- Network accessline 29
<!-- Grilling protocol below adapted verbatim from the /grill-me skill by Matt Pocock (MIT-licensed): https://github.com/mattpocock/skills/blob/main/skills/productivity/grill-me/SKILL.md --> - Network accessline 30
https://github.com/mattpocock/skills/blob/main/skills/productivity/grill-me/SKILL.md -->
apps/skills/extra/plannotator-setup-goal/SKILL.test.ts
- Executable scriptline 1
Executable file
apps/skills/extra/plannotator-visual-explainer/SKILL.test.ts
- Executable scriptline 1
Executable file
apps/skills/extra/plannotator-visual-explainer/references/design-system.md
apps/skills/extra/plannotator-visual-explainer/references/pr-components.md
apps/skills/extra/plannotator-visual-explainer/references/svg-patterns.md
How the signals fit together
Facts from a static read of the files at the pinned commit. They describe what the code does, not why.
Some files could not be read; the facts below still hold.
Declared and executed: 3 facts
- Contacts json-schema.org, which SKILL.md, the README and the plugin manifest do not mentionapps/hook/hooks/mod/inbox-default-tools.ts:15High confidence
- Contacts vercel.com, which SKILL.md, the README and the plugin manifest do not mentionapps/hook/hooks/mod/inbox-default-tools.ts:20High confidence
- Contacts plannotator.ai, which SKILL.md, the README and the plugin manifest do not mentionapps/hook/hooks/mod/plan.ts:142High confidence
Signal confidence: 354 facts
- Executable script in a comment of a testapps/hook/hooks/mod/bridge.test.ts:1Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:74Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:75Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:76Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:107Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:108Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:109Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:135Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:136Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:137Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:160Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:161Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:162Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:180Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:181Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:182Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:210Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:211Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:212Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:237Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:238Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:239Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:277Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:278Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:279Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:306Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:307Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:308Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:316Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:317Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:319Low confidence
- Network access in code of a testapps/hook/hooks/mod/bridge.test.ts:320Low confidence
- Executable script in a comment of a file that runsapps/hook/hooks/mod/bridge.ts:1Low confidence
- Network access in a comment of a file that runsapps/hook/hooks/mod/bridge.ts:93Low confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:102High confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:103High confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:163High confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:164High confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:165High confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:312High confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:313High confidence
- Network access in code of a file that runsapps/hook/hooks/mod/bridge.ts:314High confidence
- Executable script in code of a testapps/hook/hooks/mod/controller.test.ts:1Low confidence
- Network access in code of a testapps/hook/hooks/mod/controller.test.ts:21Low confidence
- Network access in code of a testapps/hook/hooks/mod/controller.test.ts:22Low confidence
- Network access in code of a testapps/hook/hooks/mod/controller.test.ts:23Low confidence
- Access to secrets in code of a test: a variable, placeholder or call, not a stored valueapps/hook/hooks/mod/controller.test.ts:99Low confidence
- Network access in code of a testapps/hook/hooks/mod/controller.test.ts:406Low confidence
- Network access in code of a testapps/hook/hooks/mod/controller.test.ts:408Low confidence
- Network access in code of a testapps/hook/hooks/mod/controller.test.ts:409Low confidence
and 304 more
Works with
| Agent | Status | Evidence | Install to |
|---|---|---|---|
| Claude Code | Native | Manifest .claude-plugin/marketplace.json | .claude/skills/<skill-name>/ |
| Codex | Native | Manifest AGENTS.md | .agents/skills/<skill-name>/ |
| Cursor | Compatible | Standard SKILL.md apps/kiro-cli/skills/plannotator-annotate/SKILL.md | .cursor/skills/<skill-name>/ |
| Gemini CLI | Compatible | Standard SKILL.md apps/kiro-cli/skills/plannotator-annotate/SKILL.md | .gemini/skills/<skill-name>/ |
| GitHub Copilot | Compatible | Standard SKILL.md apps/kiro-cli/skills/plannotator-annotate/SKILL.md | .github/skills/<skill-name>/ |
| OpenCode | Compatible | Standard SKILL.md apps/kiro-cli/skills/plannotator-annotate/SKILL.md | .opencode/skills/<skill-name>/ |
- Native The repository ships a manifest, folder or frontmatter field for this agent.
- Compatible A standard SKILL.md that this agent can read.
- Unknown No evidence either way.
Derived automatically from paths, manifests and frontmatter. Not tested on each agent.
Add this badge to your README
It updates every night and links to this page.
[](https://hotskills.dev/skill/backnotprop-plannotator/)