
Plannotator
- 35 installs
- 40 repo stars
- Updated August 4, 2026
- akillness/skills-template
Plannotator is an agent skill that reviews and annotates AI agent plans or diffs in a visual browser UI, then approves, requests changes, or archives the result.
About
Plannotator is a skill that reviews and annotates AI agent plans or diffs in a visual browser UI, then approves, requests changes, or archives them. A developer uses it as a human approval gate before implementation or for visual diff review after coding. It supports Claude Code, Codex CLI, Gemini CLI, and OpenCode, and can save reviewed plans to Obsidian or Bear.
- Browser-based visual gate to approve or request changes on agent plans
- Visual git diff review after implementation via scripts/review.sh
- Installs into Claude Code, Codex CLI, Gemini CLI, and OpenCode; saves to Obsidian/Bear
Plannotator by the numbers
- 35 all-time installs (skills.sh)
- Ranked #637 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
plannotator capabilities & compatibility
- Capabilities
- plan review · diff review · code review · approval gate
- Works with
- obsidian
- Use cases
- code review · planning
What plannotator says it does
Review and annotate AI agent plans or diffs in a visual browser UI, then approve, request changes, or archive the result with structured feedback.
`plannotator` is the **human approval gate**, not the planner itself.
source: backnotprop/plannotator
npx skills add https://github.com/akillness/skills-template --skill plannotatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 35 |
|---|---|
| repo stars | ★ 40 |
| Last updated | August 4, 2026 |
| Repository | akillness/skills-template ↗ |
What it does
Open an agent-produced plan or git diff in a browser UI, annotate it, then approve, request changes, or archive to Obsidian or Bear.
Who is it for?
Human plan-review gates before implementation and visual line-level diff review after coding.
Skip if: Creating or refining the plan itself, or broad PR risk and policy review.
When should I use this skill?
A human needs a plan-review gate before implementation or a visual diff review after coding.
What you get
An explicit approve, request-changes, or archive decision with structured annotations.
- Approved/rejected plan with annotations
- Diff review feedback
- Optional saved note in Obsidian/Bear
By the numbers
- 5 review modes (plan-review, diff-review, note-export, platform-setup, troubleshooting)
- 8 bundled setup/review scripts
Files
plannotator
Use this skill when the main job is reviewing an agent-produced plan or diff in a visual UI before work proceeds.
plannotator is the human approval gate, not the planner itself. It sits between:
- plan/spec creation (
task-planning,ralph) - execution orchestration (
jeo,vibe-kanban,bmad) - downstream code/UI feedback (
code-review,agentation)
Read these support docs before making setup or routing decisions:
- references/review-modes-and-boundaries.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
- You want to review a git diff visually after implementation and send targeted feedback
- You need a browser-based annotation loop instead of a long chat reply
- You want to save reviewed plans to Obsidian or Bear after approval or for team reference
- You need a clear install / integration path for Claude Code, Codex CLI, Gemini CLI, or OpenCode
When not to use this skill
- The main job is creating or improving the plan itself → use
task-planning,ralph, or another planning/spec skill first - The main job is broad PR judgment, policy review, or risk-based approval criteria → use
code-review - The main job is UI screenshot annotation that should drive code fixes → use
agentation - The main job is orchestration, kanban movement, or multi-agent execution state → use
jeoorvibe-kanban - The main job is generic note-taking or wiki curation → use
obsidian/llm-wiki
Instructions
Step 1: Classify the review mode
Normalize the request into one primary mode:
plannotator_mode:
primary_mode: plan-review | diff-review | note-export | platform-setup | troubleshooting
artifact_ready: yes | no
platform: claude | codex | gemini | opencode | unknown
feedback_goal: approve | request-changes | archive | unknown
repo_context: git-repo | markdown-only | remote-container | unknownUse one primary mode per run. If the user is vague, default to the smallest obvious interpretation:
- existing plan to review →
plan-review - existing code changes to inspect →
diff-review - save reviewed plan →
note-export - install/integrate plannotator →
platform-setup
Step 2: Verify the artifact exists before opening review
plannotator is only useful once something concrete exists.
Checklist: 1. A plan, diff, or markdown file already exists. 2. The user wants human review, not plan generation. 3. For diff review, a git repo or commit range is available. 4. For note export, plannotator is running in the right mode and saving is configured.
If the artifact is missing, route out instead of forcing the review tool.
Step 3: Choose the smallest review path
A. Plan review
Use when a plan exists and the human wants to approve or request changes before execution.
Typical flow: 1. Ensure plannotator is installed and integrated for the current platform. 2. Trigger the plan-review UI from the platform’s normal plan/hook flow. 3. Annotate with one concrete intent at a time:
deleteinsertreplacecomment
4. End in one explicit outcome:
- Approve → implementation can proceed
- Request changes → agent replans with structured feedback
- Archive / save → store the plan without advancing work
B. Diff review
Use when the code already changed and the human wants visual line-level review.
Typical flow:
# current working tree
bash scripts/review.sh
# specific commit
bash scripts/review.sh HEAD~1
# branch diff
bash scripts/review.sh main...HEADUse diff review when the code exists. If the user is still deciding the approach, route back to plan review first.
C. Note export
Use when the review result should be saved to Obsidian or Bear.
Use this only after confirming the relevant save path is configured. Keep note export secondary to the review decision; it is not the main trigger for the skill.
D. Platform setup
Use when the user needs plannotator installed or connected to Claude / Codex / Gemini / OpenCode.
Start with:
bash scripts/install.sh
bash scripts/check-status.shThen choose the platform-specific setup from references/platform-setup.md.
Step 4: Keep boundaries explicit
Use these route-outs aggressively:
- Need the plan written or refined? →
task-planning,ralph - Need a broader approval / risk / correctness review of code changes? →
code-review - Need UI screenshot markup that should turn into code fixes? →
agentation - Need orchestration state, ledger updates, or multi-agent gating? →
jeo,vibe-kanban - Need note-system management beyond reviewed plan export? →
obsidian,llm-wiki
Step 5: Prefer structured, low-ambiguity annotations
Good annotations are:
- narrow
- tied to one issue
- actionable
- anchored to a specific plan step or diff line range
- explicit about expected acceptance criteria
Bad annotations are:
- vague (“this feels wrong”)
- multi-issue bundles
- generic style commentary with no requested change
- hidden planning work that should have happened before review
Step 6: Use the script bundle instead of ad hoc commands
Available scripts:
scripts/install.sh— install CLI and optional integrationsscripts/setup-hook.sh— Claude Code hook setupscripts/setup-gemini-hook.sh— Gemini setupscripts/setup-codex-hook.sh— Codex setupscripts/setup-opencode-plugin.sh— OpenCode setupscripts/check-status.sh— integration/status verificationscripts/configure-remote.sh— remote/devcontainer/WSL setupscripts/review.sh— diff review launcher
If you need the exact per-platform commands, caveats, or remote-mode notes, read the support references instead of bloating the main flow.
Step 7: Return one of these output shapes
Preferred outputs:
# plannotator Review Brief
## Mode
- Primary mode:
- Why it fits:
## Artifact
- What is being reviewed:
- Review surface:
- Platform:
## Next action
1. command / trigger
2. review action
3. outcome decision
## Route-outs
- Neighboring skills to use before/after this step:
## Risks / caveats
- Setup prerequisites:
- Known limitations:Or:
# plannotator Setup Brief
## Platform
- Claude / Codex / Gemini / OpenCode
## Install
- exact commands
## Verification
- status checks
- how to trigger review
## Caveats
- remote mode / note export / known limitationsExamples
Example 1: Plan approval gate
Input
The agent 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
- mode:
plan-review - verify the plan already exists
- trigger plannotator through the platform’s normal plan-review flow
- annotate one issue per change
- finish with approve vs request-changes
- route plan-creation work back to
task-planningif the plan is missing or too immature
Example 2: Review a recent code diff
Input
The agent already changed three files. Open the visual diff review and let me mark up the changes.
Good output direction
- mode:
diff-review - verify git repo / diff range
- use
bash scripts/review.shwith the right target - keep broader approval-policy questions routed to
code-review
Example 3: Save reviewed plans to notes
Input
I want reviewed plans saved to Obsidian so my team can revisit them later.
Good output direction
- mode:
note-export - verify save integration prerequisites and hook-mode caveat
- explain how review output gets saved
- route broader vault-management work to note-taking skills
Best practices
1. Treat plannotator as the visual approval gate, not the planning engine. 2. Review one concrete artifact at a time. 3. Use one annotation per issue whenever possible. 4. Keep the final outcome explicit: approve, request changes, or archive. 5. Use scripts/check-status.sh before debugging cross-platform integration issues. 6. Move platform/setup specifics into references so the core skill stays short and trigger-friendly. 7. When in doubt, route planning/spec generation and orchestration state to neighboring skills instead of stretching this one.
References
- GitHub: backnotprop/plannotator
- Official site: plannotator.ai
- references/review-modes-and-boundaries.md
- references/platform-setup.md
- references/notes-and-troubleshooting.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, and describes an approve vs request-changes flow with structured annotations.",
"assertions": [
"Response identifies plan-review as the primary mode or equivalent",
"Response requires a concrete existing plan before opening 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 mode 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 reviewed plans saved to Obsidian, but if the real issue is vault organization or wiki structure I do not want this skill to pretend it owns that work.",
"expected_output": "The skill activates in note-export mode, confirms save prerequisites, and routes broader note-system management to Obsidian/wiki skills.",
"assertions": [
"Response identifies note-export as the primary mode or equivalent",
"Response treats save integration as a prerequisite-driven secondary flow",
"Response routes broader note/vault/wiki management to `obsidian` or `llm-wiki`"
]
}
]
}
Notes and troubleshooting
Notes export
Use note export only after confirming the review flow itself works.
Obsidian / Bear export
- Obsidian/Bear saving is optional; review/approval can still happen without it.
- Save reviewed plans when the goal is team reference, future retrieval, or lightweight archiving.
- If the user needs a broader note taxonomy, vault automation, or wiki curation workflow, route to
obsidianorllm-wiki.
Known caveats
- Diff review requires a git repo or commit range.
- Manual review mode may not push feedback directly into the active agent session the same way a hook-driven plan-review flow does.
- Note export depends on the mode/environment being configured correctly; verify before treating note save as a guaranteed output.
- 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
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, or file to annotate)
2. Diff review is failing
- confirm you are inside a git repo
- try a specific commit or diff range instead of an ambiguous state
3. Remote session is flaky
- run
bash scripts/configure-remote.sh - verify the expected port/environment settings
4. 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 orchestration, environment setup, 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 user needs plannotator installed or integrated with a specific agent platform.
Universal first step
bash scripts/install.sh
bash scripts/check-status.shIf the CLI is not installed or status is unclear, start there.
Claude Code
Best fit
- strongest plan-gating flow when plan mode / ExitPlanMode is available
- good default when the user wants approval before execution
Setup paths
# hook-based setup
bash scripts/setup-hook.sh
# optional install helper
bash scripts/install.sh --with-pluginUse the plugin/hook path recommended by the current upstream installation flow. After setup, restart Claude Code.
Gemini CLI
bash scripts/setup-gemini-hook.shTypical flow:
- work in plan/approval mode
- let the configured hook hand off into plannotator review
Codex CLI
bash scripts/setup-codex-hook.shTypical flow:
- install the helper prompt/config integration
- use the documented prompt/manual review path for plan submission
OpenCode
bash scripts/setup-opencode-plugin.shTypical flow:
- register the plugin
- restart OpenCode
- use the available slash commands for review/annotation
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/ports need extra handling.
Verification checklist
plannotatorCLI is installed- the platform-specific hook/plugin/prompt integration is in place
bash scripts/check-status.shreports the expected integration- a real plan or diff can trigger the review UI
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 - note-system management beyond save integration →
obsidian,llm-wiki
Review modes and boundaries
Core rule
plannotator is for reviewing a concrete plan or diff in a visual browser UI. It should not quietly absorb planning, orchestration, or broad code-review policy work.
Mode selection
1) Plan review
Use when:
- a plan already exists
- a human wants to approve or request changes before implementation begins
- the value comes from inline annotations and a clear gate
Do not use when:
- the real problem is writing the plan from scratch
- the plan is still at vague brainstorming level
Route out to:
task-planningralphsurveywhen the work needs research before planning
2) Diff review
Use when:
- code already changed
- the reviewer wants visual, line-targeted markup
- feedback should be attached to a concrete diff or commit range
Do not use when:
- the user wants repo-wide approval policy, test/risk discussion, or architectural judgment without a concrete diff
Route out to:
code-reviewdebuggingif the problem is root-cause isolation rather than review
3) Note export
Use when:
- the review result should be archived to Obsidian or Bear
- the review already happened or will happen as part of the same flow
Do not use when:
- the real task is note taxonomy, wiki organization, or ongoing knowledge-base maintenance
Route out to:
obsidianllm-wiki
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 | Visual UI bug markup separate from plan/diff review |
obsidian / llm-wiki | Durable note/wiki management | General note-system administration |
Review quality heuristics
Good feedback:
- names the exact step or line 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, and release policy 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] Review AI agent plans or diffs in a visual browser UI, then approve, request changes, or archive the result with structured feedback. Use when a human needs a plan-review gate before implementation, wants visual diff review after coding, or needs to save reviewed plans to Obsidian/Bear. Route planning/spec creation to task-planning or ralph; route broad PR judgment to code-review; route UI screenshot annotation to agentation.
G:plan planning planno plannotator plan-review diff-review code-review approve-plan request-changes visual-review annotate-plan review-agent-plan obsidian bear-notes design-review 계획검토 설계검토 차이검토
U[10]:
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/review-modes-and-boundaries.md — Choose review mode and route-outs
references/platform-setup.md — Platform-specific setup guide
S[5]{n,action,details}:
1,Classify mode,Choose plan-review / diff-review / note-export / platform-setup / troubleshooting
2,Verify artifact,Confirm plan or diff exists before opening review
3,Run review,Use platform hook flow or scripts/review.sh for diff review
4,Decide outcome,Approve or request changes with concrete annotations
5,Route out,Hand planning/spec/orchestration/note-management to neighboring skills when appropriate
R[4]:
Keep one annotation per issue whenever possible
Treat plannotator as the human approval gate, not the planning engine
Use scripts/check-status.sh before deep troubleshooting
Use note export only after review flow and save prerequisites are confirmed
E[3]{desc,in,out}:
"Plan review gate","Existing implementation plan needs human approval before coding","Open visual review, annotate, then approve or request changes"
"Diff review","Code already changed and reviewer wants markup on main...HEAD","Run scripts/review.sh with target diff and leave targeted feedback"
"Note export","Reviewed plan should be saved to Obsidian or Bear","Confirm save prerequisites and archive the reviewed artifact"
Related skills
FAQ
Which platforms does it support?
Claude Code, Codex CLI, Gemini CLI, and OpenCode.
Is it the planner?
No, it is the human approval gate, not the planner itself; route plan creation to task-planning or ralph.