planning-with-files
Manus-style persistent file-based planning for AI coding agents: keeps task_plan.md, findings.md, and progress.md on disk so work survives context loss and /clear. Use when asked to plan out, break down, or organize a multi-step project, research task, or any work requiring 5+ tool calls. Support...
Install this skill
Security score
The planning-with-files skill was audited on Aug 7, 2026 and we found 14 security issues across 2 threat categories, including 4 critical. Review the findings below before installing.
Categories Tested
Security Issues
Piping content to bash shell
| 10 | command: "SH=\"${CLAUDE_SKILL_DIR}/scripts/inject-plan.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/inject-plan.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/inject-plan.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --context=userprompt; exit 0" |
| 11 | PreToolUse: |
| 12 | - matcher: "Write|Edit|Bash|Read|Glob|Grep" |
| 13 | hooks: |
| 14 | - type: command |
Piping content to sh shell
| 8 | - hooks: |
| 9 | - type: command |
| 10 | command: "SH=\"${CLAUDE_SKILL_DIR}/scripts/inject-plan.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/inject-plan.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/inject-plan.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --context=userprompt; exit 0" |
| 11 | PreToolUse: |
| 12 | - matcher: "Write|Edit|Bash|Read|Glob|Grep" |
Piping content to sh shell
| 13 | hooks: |
| 14 | - type: command |
| 15 | command: "SH=\"${CLAUDE_SKILL_DIR}/scripts/inject-plan.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/inject-plan.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/inject-plan.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --context=pretool; exit 0" |
| 16 | PostToolUse: |
| 17 | - matcher: "Write|Edit" |
Piping content to sh shell
| 27 | hooks: |
| 28 | - type: command |
| 29 | command: "SH=\"${CLAUDE_SKILL_DIR}/scripts/inject-plan.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/inject-plan.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/inject-plan.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --context=precompact; exit 0" |
| 30 | metadata: |
| 31 | version: "3.9.0" |
Command substitution pattern
| 8 | - hooks: |
| 9 | - type: command |
| 10 | command: "SH=\"${CLAUDE_SKILL_DIR}/scripts/inject-plan.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/inject-plan.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/inject-plan.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --context=userprompt; exit 0" |
| 11 | PreToolUse: |
| 12 | - matcher: "Write|Edit|Bash|Read|Glob|Grep" |
Command substitution pattern
| 13 | hooks: |
| 14 | - type: command |
| 15 | command: "SH=\"${CLAUDE_SKILL_DIR}/scripts/inject-plan.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/inject-plan.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/inject-plan.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --context=pretool; exit 0" |
| 16 | PostToolUse: |
| 17 | - matcher: "Write|Edit" |
Command substitution pattern
| 22 | - hooks: |
| 23 | - type: command |
| 24 | command: "PS1_T=\"${CLAUDE_SKILL_DIR}/scripts/check-complete.ps1\"; [ -f \"$PS1_T\" ] || PS1_T=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/check-complete.ps1\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/check-complete.ps1\" 2>/dev/null | head -1); SH_T=\"${CLAUDE_SKILL_DIR}/scripts/gate-stop.sh\"; [ -f \"$SH_T\" ] || SH_T=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/gate-stop.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/gate-stop.sh\" 2>/dev/null | head -1); case \"$(uname -s 2>/dev/null)\" in MINGW*|MSYS*|CYGWIN*) if [ -n \"$PS1_T\" ] && [ -f \"$PS1_T\" ]; then powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File \"$PS1_T\" -Gate 2>/dev/null; elif [ -n \"$SH_T\" ] && [ -f \"$SH_T\" ]; then sh \"$SH_T\" 2>/dev/null; fi ;; *) if [ -n \"$SH_T\" ] && [ -f \"$SH_T\" ]; then sh \"$SH_T\" 2>/dev/null; elif [ -n \"$PS1_T\" ] && [ -f \"$PS1_T\" ]; then powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File \"$PS1_T\" -Gate 2>/dev/null; fi ;; esac; exit 0" |
| 25 | PreCompact: |
| 26 | - matcher: "*" |
Command substitution pattern
| 27 | hooks: |
| 28 | - type: command |
| 29 | command: "SH=\"${CLAUDE_SKILL_DIR}/scripts/inject-plan.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/inject-plan.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/inject-plan.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --context=precompact; exit 0" |
| 30 | metadata: |
| 31 | version: "3.9.0" |
Command substitution pattern
| 46 | # Linux/macOS — auto-detects skill directory (plugin env or default install path) |
| 47 | SKILL_DIR="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/skills/planning-with-files}" |
| 48 | $(command -v python3 || command -v python) "${SKILL_DIR}/scripts/session-catchup.py" "$(pwd)" |
| 49 | ``` |
| 50 |
Access to home directory dotfiles
| 264 | |
| 265 | Naming the plan explicitly, with either variable or an attached session, skips that check. Detection looks one directory deep, so a project nested further down is not detected. |
| 266 | - `scripts/session-catchup.py` — Recover context from previous session (v2.2.0). For OpenCode (v2.38.0+), reads the new SQLite store at `${XDG_DATA_HOME:-~/.local/share}/opencode/opencode.db` instead of the legacy JSON tree. |
| 267 | |
| 268 | ## Claude Code Turn-Loop Integration (v2.38.0+) |
Access to home directory dotfiles
| 279 | | `npx skills add OthmanAdi/planning-with-files` (or ClawHub) | SKILL.md, scripts, templates only | No, follow the manual fallback below | |
| 280 | |
| 281 | The PreCompact hook is registered in the SKILL.md frontmatter and works for both routes. The `/plan-goal` and `/plan-loop` slash commands live in `commands/` at the repo root, which only the plugin route copies into `~/.claude/plugins/marketplaces/`. Skill-only installs land at `~/.claude/skills/planning-with-files/` and do not see `commands/`. |
| 282 | |
| 283 | Both slash commands also carry `disable-model-invocation: true`, which means the model will not auto-trigger them. You type them. Per known Claude Code behavior (anthropics/claude-code issues #26251, #41417), some sessions interpret `disable-model-invocation: true` as "I cannot use the Skill tool for this entry at all" and refuse to fire even when you type the slash. If that happens, the manual fallback below produces the same effect. |
Access to home directory dotfiles
| 341 | ### `loop.md` template |
| 342 | |
| 343 | Claude Code's bare `/loop` reads `.claude/loop.md` (project) or `~/.claude/loop.md` (user). v2.38 ships a planning-aware template at `templates/loop.md`. Install once: |
| 344 | |
| 345 | ```bash |
Access to home directory dotfiles
| 345 | ```bash |
| 346 | # user-wide |
| 347 | cp ${CLAUDE_PLUGIN_ROOT}/templates/loop.md ~/.claude/loop.md |
| 348 | |
| 349 | # project-specific |
Access to home directory dotfiles
| 456 | - **Structured ledger injection.** In autonomous and gated mode the raw `progress.md` tail is no longer injected. `progress.md` is not covered by attestation, so any instruction-like text written there (for example a tool output or a fetched page summary appended during an unattended run) used to flow into context every turn. v3 injects a synthesized `ledger-summary.sh` block with no free text from disk instead. |
| 457 | - **Attestation default-on.** Autonomous and gated mode attest the plan at init. Unattended loops amplify any single injection on every tick, so the tamper gate is on from the start, not opt-in. Editing the plan after init requires explicit re-attest. |
| 458 | - **User-private SHA cache.** The hook SHA cache moved from a world-writable `/tmp` path to `$XDG_CACHE_HOME/pwf-sha` (or `~/.cache/pwf-sha`), which removes the shared-tmp poisoning surface. In gated mode the cache is a perf hint only: the gate path always re-hashes so the termination oracle never trusts a stale entry. |
| 459 | |
| 460 | | Rule | Why | |