
Plannotator
- 227 installs
- 40 repo stars
- Updated August 4, 2026
- akillness/oh-my-skills
Annotate implementation plans with assumptions, risks, dependencies, and acceptance notes before coding so scope stays explicit and agents execute against a reviewed blueprint.
About
plannotator adds structured annotations to PRDs and agent execution plans in oh-my-skills, marking assumptions, risks, dependencies, and done definitions so builders validate scope before implementation begins.
- Assumption callouts on plans
- Risk and dependency tags
- Acceptance criteria notes
- Scope boundary markers
- Agent-readable plan markup
Plannotator by the numbers
- 227 all-time installs (skills.sh)
- Ranked #995 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/akillness/oh-my-skills --skill plannotatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 227 |
|---|---|
| repo stars | ★ 40 |
| Last updated | August 4, 2026 |
| Repository | akillness/oh-my-skills ↗ |
What it does
Annotate implementation plans with assumptions, risks, dependencies, and acceptance notes before coding so scope stays explicit and agents execute against a reviewed blueprint.
Files
plannotator
Use this skill when the job is to classify one review packet, open the smallest honest visual review path, and leave broad planning / PR policy / UI critique work outside the front door.
plannotator is not the planner. It is the human approval gate that sits between:
- plan/spec creation (
task-planning,ralph) - orchestration/runtime ownership (
jeo,vibe-kanban,bmad) - broader PR/code judgment (
code-review) - rendered-UI bug markup (
agentation) - clean browser verification (
browser-harness)
Read these support docs first:
- references/intake-packets-and-route-outs.md
- references/platform-setup.md
- references/notes-and-troubleshooting.md
When to use this skill
- A coding agent already produced an implementation plan and a human must approve or request changes before coding starts.
- A concrete git diff, commit range, or PR exists and the reviewer wants browser-based line-targeted feedback.
- A markdown artifact such as a spec, PRD, architecture note, or generated plan package needs visual review and revision feedback.
- The user needs to connect
plannotatorto Claude Code, Gemini CLI, Codex CLI, or OpenCode and the main job is setup for the review loop. - The review flow exists but remote mode, stable URLs/ports, or platform-specific behavior is flaky and needs targeted troubleshooting.
When not to use this skill
- The main job is writing or refining the plan/spec itself →
task-planning,ralph, orsurvey - The main job is broad PR policy, merge criteria, risk judgment, or code-owner approval →
code-review - The main job is exact rendered-UI critique that should drive frontend fixes →
agentation - The main job is clean disposable browser automation or deterministic website verification →
browser-harness - The main job is task orchestration, board state, or multi-agent routing →
jeo,vibe-kanban,bmad - The main job is note taxonomy, wiki curation, or long-term note-system management →
obsidian,llm-wiki
Instructions
Step 1: Classify the review packet first
Normalize the request into one primary packet before discussing commands.
plannotator_intake:
primary_packet: plan-review | diff-review | markdown-review | platform-setup | troubleshooting
artifact_ready: yes | no
artifact_type: plan | git-diff | pr | markdown-spec | generated-response | unknown
platform: claude | gemini | codex | opencode | mixed | unknown
trigger_mode: native-hook | manual-review | unknown
feedback_goal: approve | request-changes | annotate | archive | unknown
repo_context: git-repo | markdown-only | remote-container | unknown
confidence: high | medium | lowDefault to the smallest obvious interpretation:
- existing implementation plan →
plan-review - existing code changes / PR / commit range →
diff-review - existing spec or markdown artifact →
markdown-review - install/integration question →
platform-setup - flaky remote/browser/status issue →
troubleshooting
Step 2: Verify the concrete artifact exists
plannotator only helps once something concrete can be reviewed.
Checklist: 1. A plan, diff, PR, markdown file, or generated response already exists. 2. The user wants review, not plan generation. 3. For diff review, a git repo, PR URL, or explicit commit range exists. 4. For markdown/spec review, the file or generated artifact is identifiable. 5. For note export, save/integration is configured; treat it as secondary, not the main packet.
If the artifact is missing, route out instead of forcing the review tool.
Step 3: Choose exactly one review packet
Use the router in references/intake-packets-and-route-outs.md and pick one primary packet:
plan-reviewdiff-reviewmarkdown-reviewplatform-setuptroubleshooting
List anything else as follow-up, not as a co-owner.
Step 4: Run the chosen packet
- Plan review → confirm the runtime can hand the plan into
plannotator, use the native/hook path when real, annotate one issue per step, and end with approve, request changes, or archive/save. - Diff review → use a concrete target and launch the smallest diff packet:
bash scripts/review.sh
bash scripts/review.sh HEAD~1
bash scripts/review.sh main...HEAD- Markdown review → confirm the spec/PRD/architecture file exists, use annotation/review mode directly, and be explicit when the runtime only supports annotation rather than a stronger approval path.
- Platform setup → start with:
bash scripts/install.sh
bash scripts/check-status.shthen use references/platform-setup.md.
- Troubleshooting → start with:
bash scripts/check-status.sh
bash scripts/configure-remote.shthen use references/notes-and-troubleshooting.md.
Step 5: Keep manual-vs-hook reality explicit
- Claude and Gemini are the clearest native/hook-driven plan-review fits.
- Codex has public hooks, but upstream
plannotatorstill documents the practical path as manual diff/markdown review or partial setup. - OpenCode users explicitly asked for more manual control when auto-invocation is too eager.
Do not flatten this into “all platforms work the same.”
Step 6: Route adjacent work aggressively
- planning/spec creation or refinement →
task-planning,ralph,survey - orchestration state or multi-agent routing →
jeo,vibe-kanban,bmad - broad PR policy, merge gating, or risk judgment →
code-review - rendered UI bug markup →
agentation - clean disposable browser verification →
browser-harness - note/vault/wiki administration beyond saving reviewed artifacts →
obsidian,llm-wiki
Step 7: Use a short output contract
Preferred output:
# plannotator Review Packet
- Primary packet:
- Artifact:
- Platform + trigger mode:
- Next action:
- Outcome or limitation:
- Route-outs:For setup-heavy asks, use a short setup brief with:
- platform
- native-hook vs manual-review status
- install commands
- verification steps
- caveats
Examples
Example 1: Approve a concrete plan
Input
The agent already proposed a 6-step implementation plan. I want to inspect it visually and either approve it or send corrections back before coding starts.
Good output direction
- choose
plan-review - verify the plan already exists
- use the runtime's real review surface
- annotate one issue per step
- end with approve vs request-changes
- route plan creation back out if the plan is still immature
Example 2: Review a diff
Input
The agent already changed three files. Open the visual diff review for main...HEAD and let me leave targeted feedback.Good output direction
- choose
diff-review - verify git context / diff range
- use
bash scripts/review.sh main...HEAD - keep broader PR-policy review routed to
code-review
Example 3: Review a PRD/spec artifact
Input
I want to mark up this architecture note and either accept it as-is or send revision feedback before we continue.
Good output direction
- choose
markdown-review - verify the markdown artifact exists
- explain whether the current platform supports native approval or manual annotation only
- keep note export secondary and route wiki/vault management outward
Example 4: Codex setup reality check
Input
Set up plannotator for Codex so I can review plans before code runs.
Good output direction
- choose
platform-setup - start with install + status verification
- explain the current Codex manual/partial reality honestly instead of promising parity that upstream docs do not show
- route broad hook/platform policy work outward if needed
Best practices
1. Treat plannotator as a visual approval gate, not the planning engine. 2. Review one concrete artifact at a time. 3. Keep manual-review vs native-hook differences explicit. 4. Use one annotation per issue whenever possible. 5. End with a clear outcome: approve, request changes, annotate only, or archive. 6. Keep note export secondary to the review packet. 7. Route PR policy, orchestration, and rendered-UI critique to neighboring skills instead of stretching plannotator.
References
- GitHub: backnotprop/plannotator
- Official site: plannotator.ai
- references/intake-packets-and-route-outs.md
- references/platform-setup.md
- references/notes-and-troubleshooting.md
- references/review-modes-and-boundaries.md
{
"skill_name": "plannotator",
"evals": [
{
"id": 1,
"prompt": "The agent already proposed a plan. I want to inspect it visually, mark up two risky steps, and either approve it or send the corrections back before implementation starts.",
"expected_output": "The skill activates in plan-review mode, verifies the plan already exists, identifies native-hook vs manual-review reality, and describes an approve vs request-changes flow with structured annotations.",
"assertions": [
"Response identifies plan-review as the primary packet or equivalent",
"Response requires a concrete existing plan before opening review",
"Response names whether the runtime path is native-hook or manual-review",
"Response ends with an explicit approve vs request-changes outcome"
]
},
{
"id": 2,
"prompt": "The agent already changed three files. Open the visual diff review for main...HEAD and help me leave targeted feedback.",
"expected_output": "The skill activates in diff-review mode, uses the diff review launcher, and keeps broader PR-review policy routed away.",
"assertions": [
"Response identifies diff-review as the primary packet or equivalent",
"Response uses or recommends `bash scripts/review.sh main...HEAD` or an equivalent targeted diff review command",
"Response routes broad approval-policy work to `code-review` rather than absorbing it into plannotator"
]
},
{
"id": 3,
"prompt": "I want to mark up this architecture note and either accept it or send revision feedback before we continue. If the real job is note-system organization, don't pretend this skill owns that.",
"expected_output": "The skill activates in markdown-review mode, confirms the artifact exists, explains any platform approval limitation honestly, and routes broader note management away.",
"assertions": [
"Response identifies markdown-review as the primary packet or equivalent",
"Response requires a concrete markdown/spec artifact before review",
"Response is explicit about approval vs annotation-only limitations when relevant",
"Response routes broader note/vault/wiki management to `obsidian` or `llm-wiki`"
]
},
{
"id": 4,
"prompt": "Set up plannotator for Codex so I can review plans before code runs, but don't claim capabilities the upstream docs don't currently support.",
"expected_output": "The skill activates in platform-setup mode, starts with install/status checks, and explains the current Codex manual/partial review reality honestly.",
"assertions": [
"Response identifies platform-setup as the primary packet or equivalent",
"Response starts with install and/or status verification commands",
"Response explicitly describes Codex plan-review support as manual, partial, or gap-constrained rather than guaranteed parity",
"Response keeps broader runtime ownership routed to adjacent platform skills when needed"
]
}
]
}
plannotator Intake Packets and Route-Outs
Use this file after the request is classified. The goal is to pick one primary review packet and keep planning, policy, browser verification, and UI-critique work outside the answer unless they are truly primary.
Packet router
| Packet | Use when | First decisions | Common route-outs |
|---|---|---|---|
plan-review | A concrete implementation plan already exists and a human must approve or request changes before execution | artifact exists, native-hook vs manual trigger, approve vs request-changes outcome, whether the plan is mature enough to review | task-planning / ralph if the plan still needs shaping; jeo / vibe-kanban if the real job is orchestration state |
diff-review | Code already changed and the reviewer wants browser-based markup on a commit range, branch diff, or PR | diff target, repo context, whether the review is artifact-specific vs broad PR policy | code-review for merge criteria / broader risk judgment; debugging if root-cause isolation is the real job |
markdown-review | The artifact is a spec, PRD, architecture note, generated plan package, or other markdown file | exact artifact path, annotation vs approval expectations, native vs manual review reality on the runtime | task-planning / ralph if the markdown is still being authored; obsidian / llm-wiki if durable note management is the real job |
platform-setup | The main job is installing or connecting plannotator to Claude, Gemini, Codex, or OpenCode | CLI install, status check, native-hook vs manual-review support, remote-mode needs | omc / omx / ohmg when the issue is really broader runtime ownership rather than plannotator setup |
troubleshooting | The review flow concept is correct but setup, browser opening, port stability, remote mode, or runtime behavior is failing | current status output, platform, remote mode, stable URL/port needs, whether the failure is actually upstream/runtime-specific | system-environment-setup for machine/runtime provisioning; neighboring platform skills when the blocker is outside plannotator |
Selection rules
1. Pick the packet that answers the current review job, not every downstream concern. 2. If both plan review and platform setup are present, choose whichever is blocking progress now and list the other as follow-up. 3. If the artifact does not exist yet, do not fake review — route out to planning or artifact creation. 4. If the user really wants merge policy, CODEOWNERS, reviewer assignment, or broad PR governance, route to code-review. 5. If the user wants exact rendered-UI critique or clean disposable browser automation, route to agentation or browser-harness instead of stretching plannotator.
Manual-vs-hook reality
- Claude / Gemini: strongest native or hook-driven plan-review story.
- Codex: treat manual review and partial setup as the honest default until upstream
plannotatordocuments stronger plan-review parity. - OpenCode: keep manual control visible because users explicitly asked for less eager auto-invocation.
Invariants
plannotatorreviews concrete artifacts, not vague ideas.- One packet per run is better than a mixed setup/review/policy lecture.
- Note export is secondary to the review packet.
- Stable ports/URLs matter in remote and multi-reviewer loops.
- The strongest distinct value is the visual approval gate before silent workflow continuation.
Output reminder
A good answer ends with:
- primary packet
- artifact and platform
- native-hook vs manual-review status
- next command/trigger
- explicit outcome or limitation
- route-outs for adjacent work
Notes and troubleshooting
Secondary note export
Treat note export as a secondary follow-up, not the primary packet.
Obsidian / Bear export
- Saving reviewed artifacts is optional; review/approval can still happen without it.
- Save reviewed plans or specs when the goal is team reference, auditability, or lightweight archiving.
- If the user needs broader vault taxonomy, wiki curation, or ongoing note automation, route to
obsidianorllm-wiki.
Current caveats that should stay visible
- Diff review requires a git repo, PR URL, or explicit commit range.
- Markdown/spec review may not have the same approve/request-changes semantics as native plan-review flows on every runtime.
- Codex setup currently has more manual/partial edges than Claude or Gemini in upstream
plannotatordocs. - OpenCode users may prefer manual review control when auto-invocation is too eager.
- Remote/container/WSL flows often need explicit port and environment setup before the browser UI behaves predictably.
Useful commands
# verify installation + integrations
bash scripts/check-status.sh
# review current working tree diff
bash scripts/review.sh
# review a specific commit
bash scripts/review.sh HEAD~1
# configure remote mode / stable port behavior
bash scripts/configure-remote.shTroubleshooting ladder
1. Nothing opens / review fails to launch
- run
bash scripts/check-status.sh - confirm the platform-specific integration is actually configured
- confirm the artifact exists (plan, diff, PR, or markdown file)
2. The wrong review mode is triggering
- confirm whether the runtime is using native hooks or a manual review path
- if auto-review is too eager, switch to the smallest manual trigger the platform supports
3. Diff review is failing
- confirm you are inside a git repo or have an explicit PR/commit target
- try a specific commit or diff range instead of an ambiguous working tree
4. Markdown/spec review is awkward
- confirm the artifact path and the platform's current approval limitations
- be explicit if the workflow is annotation-only rather than true approve/request-changes
5. Remote session is flaky
- run
bash scripts/configure-remote.sh - verify the expected port/environment settings
- prefer stable ports/URLs when another human or agent must revisit the review session
6. Notes are not saving
- confirm note integration is configured
- treat note export as secondary to the review flow; if review itself is broken, fix that first
Decision rule
If troubleshooting turns into platform ownership, environment setup, merge policy, or a wider note-management task, hand off to the specialized neighboring skill instead of stretching plannotator further.
Platform setup
Use this reference when the main job is connecting plannotator to a specific runtime or explaining the current platform reality honestly.
Universal first step
bash scripts/install.sh
bash scripts/check-status.shIf the CLI is not installed or status is unclear, start there.
Platform support summary
| Platform | Current honest story | Best first move |
|---|---|---|
| Claude Code | Strongest native/hook-driven plan-review fit | install CLI, configure Claude hook/plugin path, restart, verify with a real plan |
| Gemini CLI | Strong hook-driven fit for plan review and review commands | install CLI, configure Gemini hook path, verify with /plan and a real artifact |
| Codex CLI | Manual/partial review story is still the safest documented default in upstream plannotator; diff and markdown review are easier than full plan interception | install CLI, run status, configure Codex support, and explain any remaining manual-review limitations honestly |
| OpenCode | Good plugin/event story, but user feedback shows auto-invocation can feel too eager | install CLI, configure plugin, verify manual and plan-review behavior, and keep manual control visible |
Claude Code
Best fit
- strongest plan-gating flow when plan mode / exit-plan hooks are available
- best default when the user wants approval before execution
Setup path
bash scripts/setup-hook.shIf you are using the upstream plugin path, use the current plugin/hook instructions and then restart Claude Code.
Verification:
bash scripts/check-status.sh- trigger a real plan-review flow
- confirm the browser review opens at the right checkpoint
Gemini CLI
Best fit
- strong hook-driven plan review and review-command story
- good fit when the user already works in
/plan
Setup path
bash scripts/setup-gemini-hook.shVerification:
bash scripts/check-status.sh- trigger plan mode or the relevant review command
- confirm the browser review opens with the expected artifact
Codex CLI
Current reality
- upstream docs still frame Codex as the place for manual diff review, markdown annotation, and partial setup, not full native plan-review parity
- public Codex hooks exist, but the
plannotatorskill should not over-promise support the upstream docs do not currently claim
Setup path
bash scripts/setup-codex-hook.sh
bash scripts/check-status.shVerification:
- confirm the CLI is installed
- confirm the Codex-side integration files exist
- test a manual review path on a real diff or markdown artifact
- if the user wants plan interception parity, label it as a current gap or partial path rather than a guaranteed feature
OpenCode
Current reality
- plugin/event integration is available
- user feedback shows that auto-invocation can be annoying when the wrong agent triggers review
Setup path
bash scripts/setup-opencode-plugin.sh
bash scripts/check-status.shVerification:
- confirm plugin registration
- restart OpenCode
- test whether the desired review flow is manual, plan-triggered, or both
- keep a manual "review this artifact now" path visible when auto-review is too eager
Remote / devcontainer / WSL setups
bash scripts/configure-remote.sh
bash scripts/check-status.shUse remote mode when the review server runs in a container, SSH session, WSL environment, or another remote shell where browser opening and port stability need extra handling.
Verification checklist
plannotatorCLI is installed- the runtime-specific integration is in place
bash scripts/check-status.shreports the expected integration- a real plan, diff, PR, or markdown artifact can trigger the intended review path
- remote mode and stable URL/port behavior are verified when applicable
When setup is the wrong problem
If the real issue is:
- machine provisioning / runtimes / devcontainers →
system-environment-setup - execution orchestration or task ledgers →
jeo,vibe-kanban,bmad - platform-level runtime ownership →
omc,omx,ohmg - note-system management beyond save integration →
obsidian,llm-wiki
Review modes and boundaries
Core rule
plannotator is for reviewing a concrete plan, markdown artifact, or diff in a visual browser UI. It should not quietly absorb planning, orchestration, broad PR-policy review, or rendered-UI bug triage.
Mode boundaries
1) Plan review
Use when:
- an implementation plan already exists
- a human wants to approve or request changes before execution
- the real value is the approval gate, not plan generation
Route out when:
- the plan is still being written or re-scoped →
task-planning,ralph,survey - the real blocker is orchestration state or handoff sequencing →
jeo,vibe-kanban,bmad
2) Diff review
Use when:
- code already changed
- the reviewer wants visual markup on a commit range, branch diff, or PR
- feedback should attach to a concrete diff rather than a general policy discussion
Route out when:
- the main need is merge policy, risk judgment, or reviewer criteria →
code-review - the main need is debugging/root-cause isolation →
debugging
3) Markdown review
Use when:
- the artifact is a spec, PRD, architecture note, generated plan package, or other markdown file
- a human wants to annotate or approve the concrete document before work continues
Route out when:
- the artifact is still being authored rather than reviewed →
task-planning,ralph - the real job is note taxonomy or durable wiki management →
obsidian,llm-wiki
4) Platform setup / troubleshooting
Use when:
- the review job is conceptually correct but runtime hookup, browser launching, remote mode, or stable URL/port behavior is the blocker
Route out when:
- the real job is platform ownership or environment provisioning →
omc,omx,ohmg,system-environment-setup
Manual-vs-hook reminder
- Claude and Gemini are the clearest native/hook-driven plan-review fits.
- Codex should still be described honestly as manual/partial where upstream docs remain limited.
- OpenCode users may prefer manual control when auto-review feels too eager.
Neighboring skills
| Skill | Owns | Do not steal from it |
|---|---|---|
task-planning | Turning goals into execution-ready plans | The core planning/spec creation step |
ralph | Spec-first / interview-first planning loops | Requirement shaping and spec refinement |
jeo | Orchestration and execution gating across tools | Ledger/state/orchestration logic |
vibe-kanban | Kanban/task movement and decomposition | Board management and work tracking |
code-review | Risk/correctness/approval judgment on code changes | Broad PR-review policy |
agentation | UI screenshot annotation → targeted code fixes | Rendered UI bug markup |
browser-harness | Clean disposable browser verification | Fresh-session browser evidence |
obsidian / llm-wiki | Durable note/wiki management | General note-system administration |
Review quality heuristics
Good feedback:
- names the exact step, file, or diff range
- asks for a concrete change
- includes acceptance criteria when requesting changes
- separates distinct issues into separate annotations
Weak feedback:
- bundles many issues into one comment
- asks the reviewer to invent the plan during review
- mixes UI, architecture, merge policy, and setup in one note
- uses diff review when no code exists yet
#!/bin/bash
# plannotator - Status Check Script
# Verifies CLI install, hook configuration for all AI tools, and environment variables
#
# Usage: ./check-status.sh
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
PASS=0
WARN=0
FAIL=0
check_pass() { echo -e " ${GREEN}✓${NC} $1"; PASS=$((PASS+1)); }
check_warn() { echo -e " ${YELLOW}⚠${NC} $1"; WARN=$((WARN+1)); }
check_fail() { echo -e " ${RED}✗${NC} $1"; FAIL=$((FAIL+1)); }
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator Status Report ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
# ── 1. CLI ─────────────────────────────────────────
echo -e "${BLUE}CLI Installation${NC}"
if command -v plannotator &>/dev/null; then
VERSION=$(plannotator --version 2>/dev/null || echo "unknown")
check_pass "plannotator CLI installed (version: ${VERSION})"
check_pass "Location: $(which plannotator)"
else
check_fail "plannotator CLI not found in PATH"
echo -e " ${GRAY}Fix: run ./install.sh${NC}"
fi
echo ""
# ── 2. Hook Configuration ──────────────────────────
echo -e "${BLUE}Hook Configuration${NC}"
SETTINGS_FILE="$HOME/.claude/settings.json"
HOOK_CONFIGURED=false
if [ -f "$SETTINGS_FILE" ]; then
if grep -q "plannotator" "$SETTINGS_FILE" 2>/dev/null; then
check_pass "plannotator hook found in ~/.claude/settings.json"
HOOK_CONFIGURED=true
# Check hook is for ExitPlanMode
if grep -q "ExitPlanMode" "$SETTINGS_FILE" 2>/dev/null; then
check_pass "Hook is bound to ExitPlanMode (plan review enabled)"
else
check_warn "Hook found but not bound to ExitPlanMode"
fi
else
check_warn "No plannotator hook in ~/.claude/settings.json"
echo -e " ${GRAY}Fix: run ./setup-hook.sh${NC}"
fi
else
check_warn "~/.claude/settings.json not found"
echo -e " ${GRAY}Fix: run ./setup-hook.sh to create it${NC}"
fi
# Check for plugin install (alternative to manual hook)
PLUGIN_DIR="$HOME/.claude/plugins"
if [ -d "$PLUGIN_DIR" ] && ls "$PLUGIN_DIR" 2>/dev/null | grep -qi plannotator; then
check_pass "plannotator Claude Code plugin detected"
HOOK_CONFIGURED=true
fi
if [ "$HOOK_CONFIGURED" = false ]; then
check_fail "No hook configuration found — plan review won't trigger automatically"
echo -e " ${GRAY}Fix: run ./setup-hook.sh${NC}"
fi
echo ""
# ── 3. Environment Variables ───────────────────────
echo -e "${BLUE}Environment Variables${NC}"
if [ -n "$PLANNOTATOR_REMOTE" ]; then
check_pass "PLANNOTATOR_REMOTE=${PLANNOTATOR_REMOTE} (remote mode active)"
else
echo -e " ${GRAY}-${NC} PLANNOTATOR_REMOTE not set (local mode — browser opens automatically)"
fi
if [ -n "$PLANNOTATOR_PORT" ]; then
check_pass "PLANNOTATOR_PORT=${PLANNOTATOR_PORT}"
else
echo -e " ${GRAY}-${NC} PLANNOTATOR_PORT not set (random port in local mode, 19432 in remote mode)"
fi
if [ -n "$PLANNOTATOR_BROWSER" ]; then
check_pass "PLANNOTATOR_BROWSER=${PLANNOTATOR_BROWSER}"
else
echo -e " ${GRAY}-${NC} PLANNOTATOR_BROWSER not set (uses system default)"
fi
if [ -n "$PLANNOTATOR_SHARE_URL" ]; then
check_pass "PLANNOTATOR_SHARE_URL=${PLANNOTATOR_SHARE_URL}"
else
echo -e " ${GRAY}-${NC} PLANNOTATOR_SHARE_URL not set (uses share.plannotator.ai)"
fi
echo ""
# ── 4. Review Command ──────────────────────────────
echo -e "${BLUE}Code Review (/plannotator-review)${NC}"
if command -v plannotator &>/dev/null; then
# Try to check if review subcommand exists
if plannotator review --help &>/dev/null 2>&1; then
check_pass "plannotator review command available"
else
check_warn "plannotator review command may not be available (check CLI version)"
fi
else
check_fail "Cannot check review command — CLI not installed"
fi
echo ""
# ── 3b. Gemini CLI Hook ─────────────────────────────────────
echo -e "${BLUE}Gemini CLI Hook${NC}"
GEMINI_SETTINGS="$HOME/.gemini/settings.json"
if [ -f "$GEMINI_SETTINGS" ]; then
if grep -q "plannotator" "$GEMINI_SETTINGS" 2>/dev/null; then
check_pass "plannotator hook found in ~/.gemini/settings.json"
if grep -q "ExitPlanMode" "$GEMINI_SETTINGS" 2>/dev/null; then
check_pass "Hook bound to ExitPlanMode"
else
check_warn "Hook found but not bound to ExitPlanMode"
fi
else
check_warn "No plannotator hook in ~/.gemini/settings.json"
echo -e " ${GRAY}Fix: run ./setup-gemini-hook.sh${NC}"
fi
else
echo -e " ${GRAY}-${NC} ~/.gemini/settings.json not found (run ./setup-gemini-hook.sh to configure)"
fi
GEMINI_MD="$HOME/.gemini/GEMINI.md"
if [ -f "$GEMINI_MD" ] && grep -q "plannotator" "$GEMINI_MD" 2>/dev/null; then
check_pass "plannotator instructions found in ~/.gemini/GEMINI.md"
else
echo -e " ${GRAY}-${NC} No plannotator instructions in GEMINI.md (run ./setup-gemini-hook.sh)"
fi
echo ""
# ── 3c. Codex CLI Configuration ────────────────────────────
echo -e "${BLUE}Codex CLI Configuration${NC}"
CODEX_CONFIG="$HOME/.codex/config.toml"
if [ -f "$CODEX_CONFIG" ]; then
if grep -q "plannotator" "$CODEX_CONFIG" 2>/dev/null; then
check_pass "plannotator found in ~/.codex/config.toml developer_instructions"
else
check_warn "No plannotator reference in ~/.codex/config.toml"
echo -e " ${GRAY}Fix: run ./setup-codex-hook.sh${NC}"
fi
else
echo -e " ${GRAY}-${NC} ~/.codex/config.toml not found (run ./setup-codex-hook.sh to configure)"
fi
CODEX_PROMPT="$HOME/.codex/prompts/plannotator.md"
if [ -f "$CODEX_PROMPT" ]; then
check_pass "plannotator prompt file found at ~/.codex/prompts/plannotator.md"
else
echo -e " ${GRAY}-${NC} No plannotator prompt at ~/.codex/prompts/ (run ./setup-codex-hook.sh)"
fi
echo ""
# ── 3d. OpenCode Plugin ─────────────────────────────────────
echo -e "${BLUE}OpenCode Plugin${NC}"
OPENCODE_COMMAND_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/command"
OPENCODE_JSON_FOUND=false
for candidate in "${PWD}/opencode.json" "$HOME/.config/opencode/opencode.json" "$HOME/opencode.json"; do
if [ -f "$candidate" ] && grep -q "plannotator" "$candidate" 2>/dev/null; then
check_pass "plannotator plugin found in ${candidate}"
OPENCODE_JSON_FOUND=true
break
fi
done
if [ "$OPENCODE_JSON_FOUND" = false ]; then
echo -e " ${GRAY}-${NC} No plannotator plugin in opencode.json (run ./setup-opencode-plugin.sh)"
fi
if [ -f "${OPENCODE_COMMAND_DIR}/plannotator-review.md" ]; then
check_pass "/plannotator-review slash command registered"
else
echo -e " ${GRAY}-${NC} /plannotator-review not found (run ./setup-opencode-plugin.sh)"
fi
if [ -f "${OPENCODE_COMMAND_DIR}/plannotator-annotate.md" ]; then
check_pass "/plannotator-annotate slash command registered"
else
echo -e " ${GRAY}-${NC} /plannotator-annotate not found (run ./setup-opencode-plugin.sh)"
fi
echo ""
# ── 3e. Obsidian ────────────────────────────────────────────
echo -e "${BLUE}Obsidian (Optional — for plan auto-save)${NC}"
if command -v obsidian &>/dev/null 2>&1 || [ -d "/Applications/Obsidian.app" ] || [ -d "$HOME/Applications/Obsidian.app" ]; then
check_pass "Obsidian detected"
else
echo -e " ${GRAY}-${NC} Obsidian not found (install: ${BLUE}https://obsidian.md/download${NC})"
echo -e " ${GRAY} Enable vault sync in plannotator UI → gear icon → Obsidian Integration${NC}"
fi
echo ""
echo -e "${BLUE}Bear Notes (Optional — for plan auto-save)${NC}"
if [ -d "/Applications/Bear.app" ] || [ -d "$HOME/Applications/Bear.app" ]; then
check_pass "Bear.app detected"
echo -e " ${GRAY}-${NC} Quick check: ${GREEN}open \"bear://x-callback-url/create?title=Plannotator%20Check&text=ok\"${NC}"
else
echo -e " ${GRAY}-${NC} Bear.app not found (install from App Store)"
echo -e " ${GRAY} Bear export uses ${BLUE}bear://x-callback-url/create${NC} in system browser${NC}"
fi
echo ""
# ── 5. Git Status ──────────────────────────────────────────
echo -e "${BLUE}Git Repository${NC}"
if git rev-parse --git-dir &>/dev/null 2>&1; then
BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
check_pass "Git repository detected (branch: ${BRANCH})"
DIFF_COUNT=$(git diff --shortstat 2>/dev/null | grep -oE '[0-9]+ file' | head -1 || echo "0 file")
if [ "$DIFF_COUNT" != "0 file" ]; then
check_pass "Uncommitted changes found — ready for /plannotator-review"
else
echo -e " ${GRAY}-${NC} No uncommitted changes (commit some code first for diff review)"
fi
else
check_warn "Not in a git repository — diff review won't work"
fi
echo ""
# ── Summary ────────────────────────────────────────
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e " ${GREEN}Passed:${NC} ${PASS}"
[ $WARN -gt 0 ] && echo -e " ${YELLOW}Warnings:${NC} ${WARN}"
[ $FAIL -gt 0 ] && echo -e " ${RED}Failed:${NC} ${FAIL}"
echo ""
if [ $FAIL -eq 0 ] && [ $WARN -eq 0 ]; then
echo -e "${GREEN}All checks passed — plannotator is ready!${NC}"
elif [ $FAIL -eq 0 ]; then
echo -e "${YELLOW}Setup is mostly complete — check warnings above${NC}"
else
echo -e "${RED}Setup incomplete — fix the failures above before using plannotator${NC}"
fi
echo ""
echo -e "${BLUE}Setup scripts available:${NC}"
echo -e " ${GREEN}./setup-hook.sh${NC} Claude Code hook"
echo -e " ${GREEN}./setup-gemini-hook.sh${NC} Gemini CLI hook"
echo -e " ${GREEN}./setup-codex-hook.sh${NC} Codex CLI"
echo -e " ${GREEN}./setup-opencode-plugin.sh${NC} OpenCode plugin"
echo -e " ${GREEN}./install.sh --all${NC} All integrations at once"
echo ""
#!/bin/bash
# plannotator - Remote / Devcontainer Configuration Script
# Sets up environment variables for SSH, devcontainer, or WSL usage.
#
# Usage:
# ./configure-remote.sh # Interactive
# ./configure-remote.sh --port 9999 # Set port only
# ./configure-remote.sh --show # Show current config
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
SHOW_ONLY=false
PORT=""
SHELL_PROFILE=""
for arg in "$@"; do
case $arg in
--show) SHOW_ONLY=true ;;
--port) PORT="$2"; shift ;;
--port=*) PORT="${arg#*=}" ;;
-h|--help)
echo "Usage: $0 [--show] [--port <number>]"
echo ""
echo "Configures plannotator for remote/devcontainer environments."
echo ""
echo "Options:"
echo " --show Display current plannotator environment variables"
echo " --port <n> Set PLANNOTATOR_PORT to <n>"
echo " -h, --help Show this help"
exit 0
;;
esac
done
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator Remote Configuration ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
# ── Show current config ────────────────────────────
show_config() {
echo -e "${BLUE}Current plannotator environment:${NC}"
echo ""
if [ -n "$PLANNOTATOR_REMOTE" ]; then
echo -e " PLANNOTATOR_REMOTE = ${GREEN}${PLANNOTATOR_REMOTE}${NC}"
else
echo -e " PLANNOTATOR_REMOTE = ${GRAY}(not set — local mode)${NC}"
fi
if [ -n "$PLANNOTATOR_PORT" ]; then
echo -e " PLANNOTATOR_PORT = ${GREEN}${PLANNOTATOR_PORT}${NC}"
else
echo -e " PLANNOTATOR_PORT = ${GRAY}(not set — random in local, 19432 in remote)${NC}"
fi
if [ -n "$PLANNOTATOR_BROWSER" ]; then
echo -e " PLANNOTATOR_BROWSER = ${GREEN}${PLANNOTATOR_BROWSER}${NC}"
else
echo -e " PLANNOTATOR_BROWSER = ${GRAY}(not set — system default)${NC}"
fi
if [ -n "$PLANNOTATOR_SHARE_URL" ]; then
echo -e " PLANNOTATOR_SHARE_URL= ${GREEN}${PLANNOTATOR_SHARE_URL}${NC}"
else
echo -e " PLANNOTATOR_SHARE_URL= ${GRAY}(not set — share.plannotator.ai)${NC}"
fi
echo ""
}
show_config
if [ "$SHOW_ONLY" = true ]; then
exit 0
fi
# ── Detect shell profile ───────────────────────────
detect_profile() {
if [ -n "$ZSH_VERSION" ] || [ "$(basename "$SHELL")" = "zsh" ]; then
echo "$HOME/.zshrc"
elif [ -n "$BASH_VERSION" ] || [ "$(basename "$SHELL")" = "bash" ]; then
if [ -f "$HOME/.bash_profile" ]; then
echo "$HOME/.bash_profile"
else
echo "$HOME/.bashrc"
fi
else
echo "$HOME/.profile"
fi
}
SHELL_PROFILE=$(detect_profile)
echo -e "${BLUE}Shell profile detected:${NC} ${SHELL_PROFILE}"
echo ""
# ── Interactive prompts ────────────────────────────
echo -e "${BLUE}Configure plannotator for remote use?${NC}"
echo ""
echo -e " ${YELLOW}Remote mode${NC} disables auto browser open and uses a fixed port."
echo -e " Use this when running Claude Code via SSH, devcontainer, or WSL."
echo ""
read -rp "Enable remote mode? [y/N]: " ENABLE_REMOTE
echo ""
LINES_TO_ADD=""
if [[ "$ENABLE_REMOTE" =~ ^[Yy]$ ]]; then
LINES_TO_ADD="${LINES_TO_ADD}export PLANNOTATOR_REMOTE=1\n"
echo -e "${GREEN}✓ Remote mode will be enabled${NC}"
# Port
if [ -z "$PORT" ]; then
read -rp "Port to use [default: 19432]: " PORT
PORT="${PORT:-19432}"
fi
LINES_TO_ADD="${LINES_TO_ADD}export PLANNOTATOR_PORT=${PORT}\n"
echo -e "${GREEN}✓ Port set to ${PORT}${NC}"
echo ""
echo -e "${BLUE}Port forwarding setup:${NC}"
echo ""
echo -e " ${GRAY}SSH config (~/.ssh/config):${NC}"
echo -e " Host your-server"
echo -e " LocalForward ${PORT} localhost:${PORT}"
echo ""
echo -e " ${GRAY}VS Code devcontainer: check the 'Ports' tab (auto-forwarded)${NC}"
echo ""
else
# Local mode — optionally set custom browser
read -rp "Custom browser path/app? (leave empty for default): " CUSTOM_BROWSER
if [ -n "$CUSTOM_BROWSER" ]; then
LINES_TO_ADD="${LINES_TO_ADD}export PLANNOTATOR_BROWSER=\"${CUSTOM_BROWSER}\"\n"
echo -e "${GREEN}✓ Browser set to: ${CUSTOM_BROWSER}${NC}"
fi
fi
# Share URL
read -rp "Custom share URL? (leave empty for share.plannotator.ai): " CUSTOM_SHARE
if [ -n "$CUSTOM_SHARE" ]; then
LINES_TO_ADD="${LINES_TO_ADD}export PLANNOTATOR_SHARE_URL=\"${CUSTOM_SHARE}\"\n"
echo -e "${GREEN}✓ Share URL set to: ${CUSTOM_SHARE}${NC}"
fi
echo ""
if [ -z "$LINES_TO_ADD" ]; then
echo -e "${YELLOW}No changes to make.${NC}"
exit 0
fi
# ── Write to shell profile ─────────────────────────
echo -e "${BLUE}Adding to ${SHELL_PROFILE}:${NC}"
echo ""
printf " %b" "$LINES_TO_ADD" | sed 's/^/ /'
echo ""
read -rp "Write to ${SHELL_PROFILE}? [Y/n]: " CONFIRM
if [[ "$CONFIRM" =~ ^[Nn]$ ]]; then
echo ""
echo -e "${YELLOW}Not written. Add these lines manually to your shell profile:${NC}"
echo ""
printf "%b" "$LINES_TO_ADD"
exit 0
fi
{
echo ""
echo "# plannotator configuration"
printf "%b" "$LINES_TO_ADD"
} >> "$SHELL_PROFILE"
echo ""
echo -e "${GREEN}✓ Configuration written to ${SHELL_PROFILE}${NC}"
echo ""
echo -e "${BLUE}Apply now with:${NC}"
echo -e " source ${SHELL_PROFILE}"
echo ""
echo -e "${BLUE}Verify with:${NC}"
echo -e " ./check-status.sh"
echo ""
#!/bin/bash
# plannotator - Installation Script
# Installs the plannotator CLI and optionally sets up AI tool integrations
#
# Usage:
# ./install.sh # CLI only
# ./install.sh --with-plugin # CLI + Claude Code plugin
# ./install.sh --with-gemini # CLI + Gemini CLI hook
# ./install.sh --with-codex # CLI + Codex CLI setup
# ./install.sh --with-opencode # CLI + OpenCode plugin
# ./install.sh --all # CLI + all integrations
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
WITH_PLUGIN=false
WITH_GEMINI=false
WITH_CODEX=false
WITH_OPENCODE=false
for arg in "$@"; do
case $arg in
--with-plugin) WITH_PLUGIN=true ;;
--with-gemini) WITH_GEMINI=true ;;
--with-codex) WITH_CODEX=true ;;
--with-opencode) WITH_OPENCODE=true ;;
--all)
WITH_PLUGIN=true
WITH_GEMINI=true
WITH_CODEX=true
WITH_OPENCODE=true
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --with-plugin Also output Claude Code plugin install commands"
echo " --with-gemini Configure Gemini CLI hook (runs setup-gemini-hook.sh)"
echo " --with-codex Configure Codex CLI (runs setup-codex-hook.sh)"
echo " --with-opencode Register OpenCode plugin (runs setup-opencode-plugin.sh)"
echo " --all All of the above"
echo " -h, --help Show this help"
echo ""
echo "Prerequisites:"
echo " Obsidian (for plan/review auto-save): https://obsidian.md/download"
exit 0
;;
esac
done
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator Installer ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${BLUE}━━ Prerequisites ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if command -v obsidian &>/dev/null 2>&1 || [ -d "/Applications/Obsidian.app" ] || [ -d "$HOME/Applications/Obsidian.app" ]; then
echo -e " ${GREEN}✓ Obsidian detected${NC}"
else
echo -e " ${YELLOW}⚠ Obsidian not detected${NC}"
echo -e " ${GRAY} plannotator can auto-save approved plans to your Obsidian vault.${NC}"
echo -e " ${GRAY} Install Obsidian: ${BLUE}https://obsidian.md/download${NC}"
echo -e " ${GRAY} (You can skip this and enable later via plannotator UI → gear icon)${NC}"
fi
echo ""
OS=""
case "$(uname -s)" in
Darwin) OS="macos" ;;
Linux)
if grep -qi microsoft /proc/version 2>/dev/null; then
OS="wsl"
else
OS="linux"
fi
;;
CYGWIN*|MINGW*|MSYS*) OS="windows" ;;
*) OS="unknown" ;;
esac
echo -e "${BLUE}━━ Installing plannotator CLI ━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e "${BLUE}Detected OS:${NC} ${OS}"
echo ""
if command -v plannotator &>/dev/null; then
CURRENT_VERSION=$(plannotator --version 2>/dev/null || echo "unknown")
echo -e "${YELLOW}plannotator is already installed (version: ${CURRENT_VERSION})${NC}"
echo -e "${GRAY}Re-running install to update to latest version...${NC}"
echo ""
fi
case "$OS" in
macos|linux|wsl)
if curl -fsSL https://plannotator.ai/install.sh | bash; then
echo ""
echo -e "${GREEN}✓ plannotator CLI installed successfully${NC}"
else
echo -e "${RED}✗ Installation failed${NC}"
echo -e "${YELLOW}Try manual install: curl -fsSL https://plannotator.ai/install.sh | bash${NC}"
exit 1
fi
;;
windows)
echo -e "${YELLOW}Windows detected. Run in PowerShell:${NC}"
echo ""
echo " irm https://plannotator.ai/install.ps1 | iex"
echo ""
echo -e "${GRAY}Or for CMD:${NC}"
echo " curl -fsSL https://plannotator.ai/install.cmd -o install.cmd && install.cmd && del install.cmd"
echo ""
exit 0
;;
*)
echo -e "${RED}Unsupported OS. Visit https://plannotator.ai for manual install instructions.${NC}"
exit 1
;;
esac
# Verify installation
echo ""
echo -e "${BLUE}Verifying installation...${NC}"
# Reload PATH in case plannotator was added to a new location
export PATH="$HOME/.local/bin:$HOME/bin:$PATH"
if command -v plannotator &>/dev/null; then
VERSION=$(plannotator --version 2>/dev/null || echo "unknown")
echo -e "${GREEN}✓ plannotator ${VERSION} is ready${NC}"
echo -e "${GRAY} Location: $(which plannotator)${NC}"
else
echo -e "${YELLOW}⚠ plannotator installed but not in PATH${NC}"
echo -e "${YELLOW} Restart your terminal or run: source ~/.bashrc (or ~/.zshrc)${NC}"
fi
if [ "$WITH_PLUGIN" = true ]; then
echo ""
echo -e "${BLUE}━━ Claude Code Plugin Setup ━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo -e "Run these commands inside Claude Code:"
echo ""
echo -e " ${GREEN}/plugin marketplace add backnotprop/plannotator${NC}"
echo -e " ${GREEN}/plugin install plannotator@plannotator${NC}"
echo ""
echo -e "${YELLOW}⚠ IMPORTANT: Restart Claude Code after plugin install${NC}"
echo ""
echo -e "${GRAY}Alternative (manual hook): run ./setup-hook.sh${NC}"
fi
if [ "$WITH_GEMINI" = true ]; then
echo ""
echo -e "${BLUE}━━ Gemini CLI Integration ━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if [ -f "${SCRIPT_DIR}/setup-gemini-hook.sh" ]; then
bash "${SCRIPT_DIR}/setup-gemini-hook.sh"
else
echo -e "${YELLOW}⚠ setup-gemini-hook.sh not found at ${SCRIPT_DIR}${NC}"
echo -e "${GRAY} Run it manually from the scripts/ directory${NC}"
fi
fi
if [ "$WITH_CODEX" = true ]; then
echo ""
echo -e "${BLUE}━━ Codex CLI Integration ━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if [ -f "${SCRIPT_DIR}/setup-codex-hook.sh" ]; then
bash "${SCRIPT_DIR}/setup-codex-hook.sh"
else
echo -e "${YELLOW}⚠ setup-codex-hook.sh not found at ${SCRIPT_DIR}${NC}"
echo -e "${GRAY} Run it manually from the scripts/ directory${NC}"
fi
fi
if [ "$WITH_OPENCODE" = true ]; then
echo ""
echo -e "${BLUE}━━ OpenCode Plugin Integration ━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if [ -f "${SCRIPT_DIR}/setup-opencode-plugin.sh" ]; then
bash "${SCRIPT_DIR}/setup-opencode-plugin.sh"
else
echo -e "${YELLOW}⚠ setup-opencode-plugin.sh not found at ${SCRIPT_DIR}${NC}"
echo -e "${GRAY} Run it manually from the scripts/ directory${NC}"
fi
fi
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${GREEN}Installation complete!${NC}"
echo ""
echo -e "${GRAY}Next steps:${NC}"
if [ "$WITH_PLUGIN" = false ] && [ "$WITH_GEMINI" = false ] && [ "$WITH_CODEX" = false ] && [ "$WITH_OPENCODE" = false ]; then
echo -e " ${BLUE}1.${NC} Run ${GREEN}./setup-hook.sh${NC} to configure Claude Code hooks"
echo -e " ${BLUE} ${NC} Or run ${GREEN}./install.sh --all${NC} to set up all AI tool integrations"
echo -e " ${BLUE}2.${NC} Run ${GREEN}./check-status.sh${NC} to verify everything is working"
echo -e " ${BLUE}3.${NC} Install Obsidian for plan auto-save: ${BLUE}https://obsidian.md/download${NC}"
else
echo -e " ${BLUE}1.${NC} Run ${GREEN}./check-status.sh${NC} to verify all integrations"
echo -e " ${BLUE}2.${NC} Restart any AI tools that were configured above"
if ! command -v obsidian &>/dev/null 2>&1 && [ ! -d "/Applications/Obsidian.app" ]; then
echo -e " ${BLUE}3.${NC} Install Obsidian for plan auto-save: ${BLUE}https://obsidian.md/download${NC}"
fi
fi
echo ""
#!/bin/bash
# plannotator - Code Review (Diff Review) Script
# Opens a visual diff review of current git changes in the plannotator UI.
#
# Usage:
# ./review.sh # Review all uncommitted changes
# ./review.sh HEAD~1 # Review last commit
# ./review.sh main...HEAD # Review changes from main to HEAD
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
DIFF_REF="${1:-}"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator Code Review ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
# Check CLI
if ! command -v plannotator &>/dev/null; then
echo -e "${RED}✗ plannotator CLI not found${NC}"
echo -e "${YELLOW} Run ./install.sh first${NC}"
exit 1
fi
# Check git repo
if ! git rev-parse --git-dir &>/dev/null 2>&1; then
echo -e "${RED}✗ Not inside a git repository${NC}"
exit 1
fi
# Show diff summary
echo -e "${BLUE}Repository:${NC} $(git rev-parse --show-toplevel 2>/dev/null)"
echo -e "${BLUE}Branch:${NC} $(git branch --show-current 2>/dev/null)"
echo ""
if [ -n "$DIFF_REF" ]; then
echo -e "${BLUE}Diff target:${NC} ${DIFF_REF}"
STAT=$(git diff --stat "$DIFF_REF" 2>/dev/null || git diff --stat "${DIFF_REF}..HEAD" 2>/dev/null)
else
echo -e "${BLUE}Diff target:${NC} uncommitted changes (staged + unstaged)"
STAT=$(git diff --stat HEAD 2>/dev/null)
if [ -z "$STAT" ]; then
STAT=$(git diff --stat 2>/dev/null)
fi
fi
if [ -z "$STAT" ]; then
echo -e "${YELLOW}⚠ No changes found to review${NC}"
echo ""
echo -e "${GRAY}Tips:${NC}"
echo -e " • Make some changes and run again"
echo -e " • Review a specific commit: ./review.sh HEAD~1"
echo -e " • Review branch diff: ./review.sh main...HEAD"
exit 0
fi
echo ""
echo -e "${BLUE}Changes to review:${NC}"
echo "$STAT" | sed 's/^/ /'
echo ""
# Launch plannotator review
echo -e "${BLUE}Opening plannotator diff review UI...${NC}"
echo ""
if [ -n "$DIFF_REF" ]; then
plannotator review "$DIFF_REF"
else
plannotator review
fi
EXIT_CODE=$?
echo ""
if [ $EXIT_CODE -eq 0 ]; then
echo -e "${GREEN}Review session complete${NC}"
else
echo -e "${YELLOW}Review exited with code ${EXIT_CODE}${NC}"
echo ""
echo -e "${GRAY}If the browser didn't open, check:${NC}"
echo -e " • Is PLANNOTATOR_REMOTE=1 set? Access at http://localhost:${PLANNOTATOR_PORT:-19432}"
echo -e " • Run ${GREEN}./check-status.sh${NC} to diagnose"
fi
echo ""
#!/bin/bash
# plannotator - Codex CLI Setup Script
# Configures plannotator for Codex CLI by:
# 1. Adding developer_instructions to ~/.codex/config.toml
# 2. Creating a plannotator prompt at ~/.codex/prompts/plannotator.md
#
# Usage: ./setup-codex-hook.sh [--dry-run]
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
DRY_RUN=false
for arg in "$@"; do
case $arg in
--dry-run) DRY_RUN=true ;;
-h|--help)
echo "Usage: $0 [--dry-run]"
echo ""
echo "Configures plannotator for Codex CLI:"
echo " 1. Adds plannotator instructions to ~/.codex/config.toml developer_instructions"
echo " 2. Creates ~/.codex/prompts/plannotator.md for agent role"
echo ""
echo "Options:"
echo " --dry-run Show what would change without writing"
echo " -h, --help Show this help"
exit 0
;;
esac
done
CODEX_DIR="$HOME/.codex"
CODEX_CONFIG="$CODEX_DIR/config.toml"
CODEX_PROMPTS="$CODEX_DIR/prompts"
PLANNOTATOR_PROMPT="$CODEX_PROMPTS/plannotator.md"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator × Codex CLI Setup ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
if ! command -v plannotator &>/dev/null; then
echo -e "${RED}✗ plannotator CLI not found${NC}"
echo -e "${YELLOW} Run ./install.sh first${NC}"
exit 1
fi
echo -e "${GREEN}✓ plannotator CLI is installed${NC}"
echo ""
if ! command -v codex &>/dev/null; then
echo -e "${YELLOW}⚠ codex CLI not found in PATH${NC}"
echo -e "${GRAY} Install via: npm install -g @openai/codex${NC}"
echo -e "${GRAY} Continuing setup anyway...${NC}"
echo ""
fi
mkdir -p "$CODEX_DIR" "$CODEX_PROMPTS"
# ════════════════════════════════════════════════════════════
# PART 1: developer_instructions in config.toml
# ════════════════════════════════════════════════════════════
echo -e "${BLUE}━━ Step 1: config.toml developer_instructions ━━━━${NC}"
echo ""
PLANNOTATOR_INSTRUCTION='Before implementing any plan, write the plan markdown to /tmp/plan.md and run: `python3 -c "import json; print(json.dumps({\"tool_input\": {\"plan\": open(\"/tmp/plan.md\").read(), \"permission_mode\": \"acceptEdits\"}}))" | plannotator > /tmp/pn_out.txt 2>&1 & sleep 5; cat /tmp/pn_out.txt`. Wait for user approval in plannotator UI. After coding, run `plannotator review` to open code review.'
if [ -f "$CODEX_CONFIG" ] && grep -q "plannotator" "$CODEX_CONFIG" 2>/dev/null; then
echo -e "${YELLOW}⚠ plannotator already referenced in ${CODEX_CONFIG}${NC}"
echo -e "${GRAY} No changes made to config.toml.${NC}"
else
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would add to developer_instructions in ${CODEX_CONFIG}:${NC}"
echo " $PLANNOTATOR_INSTRUCTION"
else
if [ ! -f "$CODEX_CONFIG" ]; then
cat > "$CODEX_CONFIG" <<EOF
developer_instructions = "${PLANNOTATOR_INSTRUCTION}"
EOF
echo -e "${GREEN}✓ Created ${CODEX_CONFIG} with plannotator instructions${NC}"
else
BACKUP="${CODEX_CONFIG}.bak.$(date +%Y%m%d%H%M%S)"
cp "$CODEX_CONFIG" "$BACKUP"
echo -e "${GRAY} Backup saved: ${BACKUP}${NC}"
if grep -q "^developer_instructions" "$CODEX_CONFIG"; then
if command -v python3 &>/dev/null; then
python3 - "$CODEX_CONFIG" "$PLANNOTATOR_INSTRUCTION" <<'PYEOF'
import sys, re
path = sys.argv[1]
addition = sys.argv[2]
with open(path) as f:
content = f.read()
pattern = r'^(developer_instructions\s*=\s*")(.+?)(")'
match = re.search(pattern, content, re.MULTILINE)
if match:
current = match.group(2)
if "plannotator" not in current:
new_val = current + " " + addition
content = content[:match.start()] + f'developer_instructions = "{new_val}"' + content[match.end():]
with open(path, "w") as f:
f.write(content)
print("Appended to developer_instructions.")
else:
print("plannotator already in developer_instructions — no change.")
else:
with open(path, "a") as f:
f.write(f'\ndeveloper_instructions = "{addition}"\n')
print("Added developer_instructions line.")
PYEOF
else
echo "developer_instructions = \"${PLANNOTATOR_INSTRUCTION}\"" >> "$CODEX_CONFIG"
fi
echo -e "${GREEN}✓ Updated developer_instructions in ${CODEX_CONFIG}${NC}"
else
printf '\ndeveloper_instructions = "%s"\n' "$PLANNOTATOR_INSTRUCTION" >> "$CODEX_CONFIG"
echo -e "${GREEN}✓ Added developer_instructions to ${CODEX_CONFIG}${NC}"
fi
fi
fi
fi
echo ""
# ════════════════════════════════════════════════════════════
# PART 2: plannotator prompt file
# ════════════════════════════════════════════════════════════
echo -e "${BLUE}━━ Step 2: plannotator prompt file ━━━━━━━━━━━━━━━${NC}"
echo ""
PROMPT_CONTENT='# plannotator — Plan Review Agent
Use this prompt to do a plan review session with plannotator before implementation.
## How to Use
```bash
# In Codex, invoke with:
/prompts:plannotator "Review my plan for [feature]"
```
## Workflow
1. Create your implementation plan in markdown format
2. Pipe it to plannotator for human review:
```bash
cat > /tmp/plan.md << '"'"'PLAN
# Implementation Plan: [Feature Name]
## Steps
1. ...
2. ...
PLAN
python3 -c "import json; print(json.dumps({\"tool_input\": {\"plan\": open(\"/tmp/plan.md\").read(), \"permission_mode\": \"acceptEdits\"}}))" | plannotator > /tmp/plannotator_feedback.txt 2>&1 &
```
3. User reviews and annotates in browser UI
4. If approved → proceed with implementation
5. If changes requested → revise plan and resubmit
## After Coding
```bash
# Review all uncommitted changes
plannotator review
# Review a specific commit
plannotator review HEAD~1
# Review branch diff
plannotator review main...HEAD
```
## Environment Variables
| Variable | Description |
|----------|-------------|
| `PLANNOTATOR_REMOTE` | Set to `1` for remote/SSH mode |
| `PLANNOTATOR_PORT` | Fixed port (default: random) |
| `PLANNOTATOR_BROWSER` | Custom browser path |
## Obsidian Integration
Approved plans auto-save to Obsidian when enabled in plannotator UI settings.
Install Obsidian: https://obsidian.md/download
'
if [ -f "$PLANNOTATOR_PROMPT" ]; then
echo -e "${YELLOW}⚠ ${PLANNOTATOR_PROMPT} already exists${NC}"
echo -e "${GRAY} Skipping (delete file to recreate).${NC}"
elif [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would create ${PLANNOTATOR_PROMPT}${NC}"
else
printf '%s\n' "$PROMPT_CONTENT" > "$PLANNOTATOR_PROMPT"
echo -e "${GREEN}✓ Created ${PLANNOTATOR_PROMPT}${NC}"
fi
echo ""
echo -e "${GREEN}Codex CLI setup complete!${NC}"
echo ""
echo -e "${BLUE}How to use plannotator in Codex:${NC}"
echo ""
echo -e " ${BLUE}Plan review:${NC}"
echo -e " ${GREEN}cat > /tmp/plan.md << 'PLAN'${NC}"
echo -e " ${GREEN}# ...your markdown...${NC}"
echo -e " ${GREEN}PLAN${NC}"
echo -e " ${GREEN}python3 -c \"import json; print(json.dumps({\\\"tool_input\\\": {\\\"plan\\\": open(\\\"/tmp/plan.md\\\").read(), \\\"permission_mode\\\": \\\"acceptEdits\\\"}}))\" | plannotator > /tmp/plannotator_feedback.txt 2>&1 &${NC}"
echo ""
echo -e " ${BLUE}Code review after coding:${NC}"
echo -e " ${GREEN}plannotator review${NC}"
echo ""
echo -e " ${BLUE}Use plannotator agent prompt:${NC}"
echo -e " ${GREEN}/prompts:plannotator${NC} (inside Codex interactive session)"
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo -e " ${BLUE}1.${NC} Run ${GREEN}./check-status.sh${NC} to verify configuration"
echo -e " ${BLUE}2.${NC} Start a Codex session and use plannotator review"
echo ""
#!/bin/bash
# plannotator - Gemini CLI Hook Setup Script
# Adds the ExitPlanMode hook to ~/.gemini/settings.json
# and plannotator instructions to ~/.gemini/GEMINI.md
#
# Usage: ./setup-gemini-hook.sh [--dry-run] [--md-only] [--hook-only]
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
DRY_RUN=false
MD_ONLY=false
HOOK_ONLY=false
for arg in "$@"; do
case $arg in
--dry-run) DRY_RUN=true ;;
--md-only) MD_ONLY=true ;;
--hook-only) HOOK_ONLY=true ;;
-h|--help)
echo "Usage: $0 [--dry-run] [--md-only] [--hook-only]"
echo ""
echo "Configures plannotator for Gemini CLI:"
echo " 1. Adds ExitPlanMode hook to ~/.gemini/settings.json"
echo " 2. Adds plannotator instructions to ~/.gemini/GEMINI.md"
echo ""
echo "Options:"
echo " --dry-run Show what would change without writing"
echo " --md-only Only update GEMINI.md (skip settings.json hook)"
echo " --hook-only Only update settings.json (skip GEMINI.md)"
echo " -h, --help Show this help"
exit 0
;;
esac
done
GEMINI_DIR="$HOME/.gemini"
SETTINGS_FILE="$GEMINI_DIR/settings.json"
GEMINI_MD="$GEMINI_DIR/GEMINI.md"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator × Gemini CLI Setup ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
# ── Check plannotator CLI ─────────────────────────────────
if ! command -v plannotator &>/dev/null; then
echo -e "${RED}✗ plannotator CLI not found${NC}"
echo -e "${YELLOW} Run ./install.sh first${NC}"
exit 1
fi
echo -e "${GREEN}✓ plannotator CLI is installed${NC}"
echo ""
# ── Check Gemini CLI ──────────────────────────────────────
if ! command -v gemini &>/dev/null; then
echo -e "${YELLOW}⚠ gemini CLI not found in PATH${NC}"
echo -e "${GRAY} Install via: npm install -g @google/gemini-cli${NC}"
echo -e "${GRAY} Continuing setup anyway (settings will be ready when gemini is installed)${NC}"
echo ""
fi
mkdir -p "$GEMINI_DIR"
# ════════════════════════════════════════════════════════════
# PART 1: Hook in ~/.gemini/settings.json
# ════════════════════════════════════════════════════════════
if [ "$MD_ONLY" = false ]; then
echo -e "${BLUE}━━ Step 1: settings.json hook ━━━━━━━━━━━━━━━━━━${NC}"
echo ""
if [ -f "$SETTINGS_FILE" ] && grep -q "plannotator" "$SETTINGS_FILE" 2>/dev/null; then
echo -e "${YELLOW}⚠ plannotator hook already in ${SETTINGS_FILE}${NC}"
echo -e "${GRAY} No changes made.${NC}"
else
# Hook JSON (Gemini CLI uses same format as Claude Code)
HOOK_BLOCK='{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "plannotator",
"timeout": 1800
}
]
}
]
}
}'
echo -e "${BLUE}Hook to be added to ${SETTINGS_FILE}:${NC}"
echo "$HOOK_BLOCK"
echo ""
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] No changes written to settings.json${NC}"
elif [ ! -f "$SETTINGS_FILE" ]; then
# Create new settings.json
cat > "$SETTINGS_FILE" <<'EOF'
{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "plannotator",
"timeout": 1800
}
]
}
]
}
}
EOF
echo -e "${GREEN}✓ Created ${SETTINGS_FILE} with plannotator hook${NC}"
else
# Merge into existing settings.json
BACKUP="${SETTINGS_FILE}.bak.$(date +%Y%m%d%H%M%S)"
cp "$SETTINGS_FILE" "$BACKUP"
echo -e "${GRAY} Backup saved: ${BACKUP}${NC}"
if command -v python3 &>/dev/null; then
python3 - "$SETTINGS_FILE" <<'PYEOF'
import json, sys
path = sys.argv[1]
with open(path) as f:
settings = json.load(f)
new_hook = {
"matcher": "ExitPlanMode",
"hooks": [{"type": "command", "command": "plannotator", "timeout": 1800}]
}
hooks = settings.setdefault("hooks", {})
perm = hooks.setdefault("PermissionRequest", [])
for h in perm:
if h.get("matcher") == "ExitPlanMode" and any(
x.get("command") == "plannotator" for x in h.get("hooks", [])
):
print("Hook already present — no changes made.")
sys.exit(0)
perm.append(new_hook)
with open(path, "w") as f:
json.dump(settings, f, indent=2)
f.write("\n")
print("Hook merged successfully.")
PYEOF
echo -e "${GREEN}✓ Hook merged into ${SETTINGS_FILE}${NC}"
else
echo -e "${RED}✗ python3 not found — cannot merge JSON safely${NC}"
echo -e "${YELLOW} Add manually to ${SETTINGS_FILE}:${NC}"
echo "$HOOK_BLOCK"
exit 1
fi
fi
fi
# Also try Gemini CLI's built-in hook migration if available
if command -v gemini &>/dev/null && gemini hooks --help 2>/dev/null | grep -q migrate; then
echo ""
echo -e "${GRAY} Tip: You can also run 'gemini hooks migrate --from-claude' to auto-migrate Claude Code hooks.${NC}"
fi
echo ""
fi
# ════════════════════════════════════════════════════════════
# PART 2: GEMINI.md instructions
# ════════════════════════════════════════════════════════════
if [ "$HOOK_ONLY" = false ]; then
echo -e "${BLUE}━━ Step 2: GEMINI.md plannotator instructions ━━━━${NC}"
echo ""
PLANNOTATOR_MD_BLOCK='
## plannotator — Plan Review
When you have a complete implementation plan, **always submit it for human review** before proceeding:
```bash
# Save markdown plan to file, then send validated JSON payload:
cat > /tmp/plan.md << 'PLAN'
# Your plan markdown...
PLAN
python3 -c "
import json
print(json.dumps({'tool_input': {'plan': open('/tmp/plan.md').read(), 'permission_mode': 'acceptEdits'}}))
" | plannotator > /tmp/plannotator_feedback.txt 2>&1 &
```
**Workflow:**
1. Create your implementation plan in markdown
2. Run the python3 JSON command above (manual mode) OR let ExitPlanMode hook trigger automatically
3. Wait for user approval in the browser UI
4. If approved → proceed with implementation
5. If changes requested → revise and resubmit
**Code review after implementation:**
```bash
plannotator review # Review all uncommitted changes
plannotator review HEAD~1 # Review specific commit
```
**Plan mode:** Run `gemini --approval-mode plan` to work in read-only planning mode.
plannotator hooks automatically trigger when you exit plan mode.
'
if [ -f "$GEMINI_MD" ] && grep -q "plannotator" "$GEMINI_MD" 2>/dev/null; then
echo -e "${YELLOW}⚠ plannotator instructions already in ${GEMINI_MD}${NC}"
echo -e "${GRAY} No changes made.${NC}"
else
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would append to ${GEMINI_MD}:${NC}"
echo "$PLANNOTATOR_MD_BLOCK"
else
# Append plannotator section to GEMINI.md
if [ ! -f "$GEMINI_MD" ]; then
cat > "$GEMINI_MD" <<EOF
# Gemini CLI Agent Configuration
EOF
fi
printf "\n%s\n" "$PLANNOTATOR_MD_BLOCK" >> "$GEMINI_MD"
echo -e "${GREEN}✓ plannotator instructions added to ${GEMINI_MD}${NC}"
fi
fi
echo ""
fi
# ════════════════════════════════════════════════════════════
# Summary
# ════════════════════════════════════════════════════════════
echo -e "${GREEN}Gemini CLI setup complete!${NC}"
echo ""
echo -e "${BLUE}How it works:${NC}"
echo -e " When Gemini exits plan mode (--approval-mode plan),"
echo -e " plannotator opens automatically in your browser."
echo ""
echo -e "${BLUE}Manual trigger:${NC}"
echo -e " ${GREEN}cat > /tmp/plan.md << 'PLAN'${NC}"
echo -e " ${GREEN}# ...your markdown...${NC}"
echo -e " ${GREEN}PLAN${NC}"
echo -e " ${GREEN}python3 -c \"import json; print(json.dumps({'tool_input': {'plan': open('/tmp/plan.md').read(), 'permission_mode': 'acceptEdits'}}))\" | plannotator > /tmp/plannotator_feedback.txt 2>&1 &${NC}"
echo -e " ${GREEN}plannotator review${NC} (review git diff)"
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo -e " ${BLUE}1.${NC} Run ${GREEN}./check-status.sh${NC} to verify configuration"
echo -e " ${BLUE}2.${NC} Use ${GREEN}gemini --approval-mode plan${NC} to enable plan review"
echo ""
#!/bin/bash
# plannotator - Claude Code Hook Setup Script
# Adds the ExitPlanMode hook to ~/.claude/settings.json
# Use this as an alternative to the Claude Code plugin install.
#
# Usage: ./setup-hook.sh [--dry-run]
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
DRY_RUN=false
for arg in "$@"; do
case $arg in
--dry-run) DRY_RUN=true ;;
-h|--help)
echo "Usage: $0 [--dry-run]"
echo ""
echo "Adds the plannotator hook to ~/.claude/settings.json"
echo ""
echo "Options:"
echo " --dry-run Show what would be changed without writing"
echo " -h, --help Show this help"
exit 0
;;
esac
done
SETTINGS_FILE="$HOME/.claude/settings.json"
SETTINGS_DIR="$HOME/.claude"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator Hook Setup ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
# Check plannotator is installed
if ! command -v plannotator &>/dev/null; then
echo -e "${RED}✗ plannotator CLI not found${NC}"
echo -e "${YELLOW} Run ./install.sh first${NC}"
exit 1
fi
echo -e "${GREEN}✓ plannotator CLI is installed${NC}"
echo ""
# Check if already configured
if [ -f "$SETTINGS_FILE" ] && grep -q "plannotator" "$SETTINGS_FILE" 2>/dev/null; then
echo -e "${YELLOW}⚠ plannotator hook already exists in ${SETTINGS_FILE}${NC}"
echo ""
echo -e "Current hook configuration:"
grep -A3 -B1 "plannotator" "$SETTINGS_FILE" 2>/dev/null | head -20
echo ""
echo -e "${GRAY}No changes made. Remove manually if you want to reconfigure.${NC}"
exit 0
fi
# The hook JSON to inject
HOOK_JSON='{
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "plannotator",
"timeout": 1800
}
]
}
]
}'
echo -e "${BLUE}Hook to be added:${NC}"
echo "$HOOK_JSON"
echo ""
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] No changes written.${NC}"
echo -e "Target file: ${SETTINGS_FILE}"
exit 0
fi
# Ensure ~/.claude directory exists
mkdir -p "$SETTINGS_DIR"
if [ ! -f "$SETTINGS_FILE" ]; then
# Create new settings.json with hook
echo -e "${BLUE}Creating new settings file: ${SETTINGS_FILE}${NC}"
cat > "$SETTINGS_FILE" <<EOF
{
"hooks": {
"PermissionRequest": [
{
"matcher": "ExitPlanMode",
"hooks": [
{
"type": "command",
"command": "plannotator",
"timeout": 1800
}
]
}
]
}
}
EOF
echo -e "${GREEN}✓ Created ${SETTINGS_FILE} with plannotator hook${NC}"
else
# Merge into existing settings.json
echo -e "${BLUE}Merging hook into existing: ${SETTINGS_FILE}${NC}"
echo ""
# Back up existing settings
BACKUP="${SETTINGS_FILE}.bak.$(date +%Y%m%d%H%M%S)"
cp "$SETTINGS_FILE" "$BACKUP"
echo -e "${GRAY} Backup saved: ${BACKUP}${NC}"
# Use Python (available on macOS/Linux) to merge JSON safely
if command -v python3 &>/dev/null; then
python3 - "$SETTINGS_FILE" <<'PYEOF'
import json, sys
path = sys.argv[1]
with open(path) as f:
settings = json.load(f)
new_hook = {
"matcher": "ExitPlanMode",
"hooks": [{"type": "command", "command": "plannotator", "timeout": 1800}]
}
hooks = settings.setdefault("hooks", {})
perm = hooks.setdefault("PermissionRequest", [])
# Don't add if already present
for h in perm:
if h.get("matcher") == "ExitPlanMode" and any(
x.get("command") == "plannotator" for x in h.get("hooks", [])
):
print("Hook already present — no changes made.")
sys.exit(0)
perm.append(new_hook)
with open(path, "w") as f:
json.dump(settings, f, indent=2)
f.write("\n")
print("Hook merged successfully.")
PYEOF
echo -e "${GREEN}✓ Hook added to ${SETTINGS_FILE}${NC}"
else
echo -e "${RED}✗ python3 not found — cannot merge JSON safely${NC}"
echo -e "${YELLOW} Add this manually to ${SETTINGS_FILE}:${NC}"
echo ""
echo ' "hooks": {'
echo ' "PermissionRequest": ['
echo ' {'
echo ' "matcher": "ExitPlanMode",'
echo ' "hooks": [{"type": "command", "command": "plannotator", "timeout": 1800}]'
echo ' }'
echo ' ]'
echo ' }'
exit 1
fi
fi
echo ""
echo -e "${GREEN}Hook setup complete!${NC}"
echo ""
echo -e "${BLUE}How it works:${NC}"
echo -e " When Claude Code finishes planning (Shift+Tab×2 in plan mode),"
echo -e " plannotator opens automatically in your browser."
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo -e " ${BLUE}1.${NC} Restart Claude Code for hooks to take effect"
echo -e " ${BLUE}2.${NC} Run ${GREEN}./check-status.sh${NC} to verify configuration"
echo ""
#!/bin/bash
# plannotator - OpenCode Plugin Registration Script
# Registers @plannotator/opencode@latest plugin in opencode.json
# and copies slash commands to ~/.config/opencode/command/
#
# Usage: ./setup-opencode-plugin.sh [--dry-run] [--project-dir DIR]
set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
GRAY='\033[0;37m'
NC='\033[0m'
DRY_RUN=false
PROJECT_DIR="${PWD}"
for arg in "$@"; do
case $arg in
--dry-run) DRY_RUN=true ;;
--project-dir=*) PROJECT_DIR="${arg#*=}" ;;
--project-dir) PROJECT_DIR="" ;;
-h|--help)
echo "Usage: $0 [--dry-run] [--project-dir DIR]"
echo ""
echo "Registers plannotator OpenCode plugin:"
echo " 1. Adds @plannotator/opencode@latest to opencode.json"
echo " 2. Copies slash commands to ~/.config/opencode/command/"
echo ""
echo "Options:"
echo " --project-dir DIR Target project dir (default: current dir)"
echo " --dry-run Show what would change without writing"
echo " -h, --help Show this help"
exit 0
;;
esac
done
OPENCODE_JSON="${PROJECT_DIR}/opencode.json"
OPENCODE_COMMAND_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/opencode/command"
PLUGIN_NAME="@plannotator/opencode@latest"
echo ""
echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ plannotator × OpenCode Plugin Setup ║${NC}"
echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
echo ""
echo -e "${GRAY}Project dir: ${PROJECT_DIR}${NC}"
echo ""
if ! command -v plannotator &>/dev/null; then
echo -e "${RED}✗ plannotator CLI not found${NC}"
echo -e "${YELLOW} Run ./install.sh first${NC}"
exit 1
fi
echo -e "${GREEN}✓ plannotator CLI is installed${NC}"
echo ""
# ════════════════════════════════════════════════════════════
# PART 1: opencode.json plugin registration
# ════════════════════════════════════════════════════════════
echo -e "${BLUE}━━ Step 1: opencode.json plugin registration ━━━━━${NC}"
echo ""
if [ -f "$OPENCODE_JSON" ] && grep -q "plannotator" "$OPENCODE_JSON" 2>/dev/null; then
echo -e "${YELLOW}⚠ plannotator already in ${OPENCODE_JSON}${NC}"
echo -e "${GRAY} No changes needed.${NC}"
elif [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would add '${PLUGIN_NAME}' to ${OPENCODE_JSON}${NC}"
else
if [ ! -f "$OPENCODE_JSON" ]; then
cat > "$OPENCODE_JSON" <<EOF
{
"\$schema": "https://opencode.ai/config.json",
"plugin": ["${PLUGIN_NAME}"]
}
EOF
echo -e "${GREEN}✓ Created ${OPENCODE_JSON} with plannotator plugin${NC}"
else
BACKUP="${OPENCODE_JSON}.bak.$(date +%Y%m%d%H%M%S)"
cp "$OPENCODE_JSON" "$BACKUP"
echo -e "${GRAY} Backup saved: ${BACKUP}${NC}"
if command -v python3 &>/dev/null; then
python3 - "$OPENCODE_JSON" "$PLUGIN_NAME" <<'PYEOF'
import json, sys
path = sys.argv[1]
plugin = sys.argv[2]
with open(path) as f:
config = json.load(f)
plugins = config.setdefault("plugin", [])
if any("plannotator" in p for p in plugins):
print("plannotator plugin already present — no change.")
sys.exit(0)
plugins.append(plugin)
with open(path, "w") as f:
json.dump(config, f, indent=2)
f.write("\n")
print("Plugin registered.")
PYEOF
echo -e "${GREEN}✓ Added plannotator plugin to ${OPENCODE_JSON}${NC}"
else
echo -e "${RED}✗ python3 not found — add manually to ${OPENCODE_JSON}:${NC}"
echo ' "plugin": ["'"${PLUGIN_NAME}"'"]'
exit 1
fi
fi
fi
echo ""
# ════════════════════════════════════════════════════════════
# PART 2: Slash commands for OpenCode
# ════════════════════════════════════════════════════════════
echo -e "${BLUE}━━ Step 2: OpenCode slash commands ━━━━━━━━━━━━━━━${NC}"
echo ""
REVIEW_CMD="${OPENCODE_COMMAND_DIR}/plannotator-review.md"
ANNOTATE_CMD="${OPENCODE_COMMAND_DIR}/plannotator-annotate.md"
REVIEW_CMD_CONTENT='---
description: Open interactive code review for current changes
---
Open the plannotator code review UI for current git diff.
!`plannotator review`
Address the code review feedback above.'
ANNOTATE_CMD_CONTENT='---
description: Open interactive annotation UI for a markdown file
---
!`plannotator annotate "$ARGUMENTS"`
Address the annotation feedback above.'
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}[DRY RUN] Would create:${NC}"
echo -e " ${REVIEW_CMD}"
echo -e " ${ANNOTATE_CMD}"
else
mkdir -p "$OPENCODE_COMMAND_DIR"
if [ ! -f "$REVIEW_CMD" ]; then
printf '%s\n' "$REVIEW_CMD_CONTENT" > "$REVIEW_CMD"
echo -e "${GREEN}✓ Created /plannotator-review command${NC}"
else
echo -e "${GRAY} /plannotator-review already exists — skipped${NC}"
fi
if [ ! -f "$ANNOTATE_CMD" ]; then
printf '%s\n' "$ANNOTATE_CMD_CONTENT" > "$ANNOTATE_CMD"
echo -e "${GREEN}✓ Created /plannotator-annotate command${NC}"
else
echo -e "${GRAY} /plannotator-annotate already exists — skipped${NC}"
fi
fi
echo ""
echo -e "${GREEN}OpenCode plugin setup complete!${NC}"
echo ""
echo -e "${BLUE}Next steps:${NC}"
echo -e " ${BLUE}1.${NC} ${YELLOW}Restart OpenCode${NC} for the plugin to take effect"
echo -e " ${BLUE}2.${NC} Add to ${GREEN}opencode.json${NC} if not auto-detected:"
echo ""
echo -e ' { "'
echo -e ' "$schema": "https://opencode.ai/config.json",'
echo -e " \"plugin\": [\"${PLUGIN_NAME}\"]"
echo -e ' }'
echo ""
echo -e " ${BLUE}3.${NC} Available slash commands after restart:"
echo -e " ${GREEN}/plannotator-review${NC} — code review"
echo -e " ${GREEN}/plannotator-annotate file.md${NC} — annotate markdown"
echo ""
echo -e " ${BLUE}4.${NC} The ${GREEN}submit_plan${NC} tool is automatically available to the agent"
echo ""
N:plannotator
D:[plan] Routing-first visual approval gate for AI agent plans, markdown specs, and diffs. Use when a human needs to review a concrete plan before execution, inspect a targeted diff in a browser, mark up a spec/PRD/architecture note, or set up the review loop on Claude Code, Gemini CLI, Codex CLI, or OpenCode. Route planning/spec creation to task-planning or ralph; broad PR policy to code-review; rendered-UI critique to agentation; fresh-session browser verification to browser-harness.
G:plan planning planno plannotator plan-review diff-review markdown-review spec-review approve-plan request-changes visual-review annotate-plan review-agent-plan codex gemini opencode claude-code 계획검토 설계검토 명세검토 차이검토
U[11]:
scripts/install.sh — Install plannotator CLI and optional integrations
scripts/setup-hook.sh — Configure Claude Code hook flow
scripts/setup-gemini-hook.sh — Configure Gemini integration
scripts/setup-codex-hook.sh — Configure Codex integration
scripts/setup-opencode-plugin.sh — Configure OpenCode plugin
scripts/check-status.sh — Verify CLI/integration status
scripts/configure-remote.sh — Configure remote/devcontainer/WSL mode
scripts/review.sh — Launch diff review UI
references/intake-packets-and-route-outs.md — Choose the primary review packet and route-outs
references/platform-setup.md — Platform-specific setup and capability matrix
references/notes-and-troubleshooting.md — Remote/manual-review caveats and troubleshooting ladder
S[6]{n,action,details}:
1,Classify packet,Choose plan-review / diff-review / markdown-review / platform-setup / troubleshooting
2,Verify artifact,Confirm a concrete plan diff PR or markdown artifact exists before review
3,Check platform reality,Decide native-hook vs manual-review truthfully for the current runtime
4,Run review,Use the smallest review path or setup command sequence
5,Decide outcome,Approve request changes annotate only or archive explicitly
6,Route out,Hand planning PR policy browser verification UI critique and note management to neighboring skills
R[4]:
Keep one packet and one concrete artifact per run whenever possible
Treat plannotator as the human approval gate not the planning engine
Keep manual-review vs native-hook differences explicit
Treat note export as secondary to the review packet
E[4]{desc,in,out}:
"Plan review gate","Existing implementation plan needs human approval before coding","Open the runtime's real review path annotate and end with approve or request changes"
"Diff review","Code already changed and reviewer wants markup on main...HEAD","Run scripts/review.sh with a concrete diff target and leave targeted feedback"
"Markdown/spec review","Architecture note or PRD needs visual markup before work continues","Review the concrete markdown artifact and explain approval limitations honestly"
"Codex setup reality","Need plannotator on Codex without fake parity promises","Run install plus status checks and explain current manual or partial review reality"