8 Commits

Author SHA1 Message Date
jparkerweb aedfe944b2 Merge pull request #2 from jparkerweb/handoff
Release v1.16.0: install handoff skill, add publish skill, sync upstream
2026-07-20 22:39:25 -07:00
jparkerweb 9b3c06b498 Address PR review feedback: update step label + release-list limit 2026-07-20 22:36:35 -07:00
jparkerweb 8fe1bfa805 Set v1.16.0 releaseDate to 2026-07-20 2026-07-20 22:33:24 -07:00
jparkerweb 68542fd778 Release v1.16.0: install handoff skill, add publish skill, sync upstream
- Make plan2code-handoff an installed workflow prompt: move to src/,
  register in install.js SOURCE_PROMPTS, remove repo-local-only copy
- Add repo-local maintainer /plan2code-publish skill (cuts GitHub Releases;
  excluded from install.js)
- Review workflow next-step suggestion made context-aware (upstream v1.15.4)
- Doc updates: list handoff in README, QUICK-REFERENCE, architecture table;
  add "Adding a New Workflow Prompt / Skill" checklist to dev-commands
- Fix broken AGENTS.md index links: rename .agents-docs loop/metrics files
  to plan2code-* to match references
- Bump version.json to 1.16.0 to align with package.json and CHANGELOG
2026-07-20 22:31:37 -07:00
jparkerweb 4656a6ebb7 Merge pull request #1 from jparkerweb/handoff
Add plan2code-handoff skill for conversation handoff documents
2026-07-20 22:09:45 -07:00
jparkerweb 7e9de755f1 Add plan2code-handoff skill for conversation handoff documents
AI Assisted
2026-07-20 22:07:21 -07:00
jparkerweb 4b20f93bb9 Bump to v1.15.4 for status line reasoning effort and context token count
AI Assisted
2026-07-19 21:22:54 -07:00
jparkerweb 5b3b84f0a9 Add reasoning effort label and context token count to status line
AI Assisted
2026-07-19 21:18:10 -07:00
18 changed files with 418 additions and 22 deletions
+11
View File
@@ -27,6 +27,8 @@ plan2code/
│ └── local-commands/ # For per-project installation (.claude/, etc.)
├── .husky/ # Git hooks (husky)
│ └── pre-commit # Runs character count validation
├── .claude/ # Repo-local Claude Code config (NOT installed by install.js)
│ └── skills/ # Maintainer-only dev skills, e.g. plan2code-publish/
├── docs/ # Documentation and assets
├── specs/ # Feature specs (if any in-progress)
├── install.js # Interactive installer (Node.js)
@@ -59,6 +61,7 @@ plan2code/
| `plan2code-3-implement.md` | 3 | Execute implementation (phase by phase) |
| `plan2code-review.md` | review | Post-implementation comprehensive review |
| `plan2code-4-finalize.md` | 4 | Validate, summarize, feedback, archive (7 steps) |
| `plan2code-handoff.md` | handoff | Compact the conversation into a self-contained handoff document |
## Naming Convention
@@ -84,6 +87,14 @@ Some workflows use companion reference files for depth that exceeds the 11k char
Reference files are NOT subject to the 11,000 character limit. Currently only the review workflow uses this pattern — it serves as the POC for potential adoption by other workflows.
## Repo-Local Skills (`.claude/skills/`)
Maintainer-only Claude Code skills committed to the repo but **deliberately excluded** from `install.js` — they are dev tooling, not shipped product, so they never install to `~/.claude/skills/` and carry no version bump of their own (a product-version bump would wrongly imply a user-facing release); changelog mentions fold into the current version's entry.
- `plan2code-publish/` — cuts a GitHub Release from the top `CHANGELOG.md` entry once `CHANGELOG.md` / `version.json` / `package.json` agree and the version is ahead of the latest published release. Delegates tag creation to `gh release create --target main`.
**Warning:** anything named `plan2code-*` placed under `~/.claude/skills/` is deleted by the installer's uninstall (`uninstallFiles()` in `install.js`) and by every re-install's pre-copy cleanup in `install()` (both match `/^plan2code-/` for the Claude Code skills target). Keep these skills repo-local only.
## Status Line
Optional Claude Code status bar living in `src/statusline-claude/`. Three-line bar (icon + content per line) showing model, project, branch, uncommitted diff stats, session duration + cost, context window usage, and plan/quota usage.
@@ -74,3 +74,29 @@ When modifying workflow prompts in `src/`:
2. Run `node install.js` to regenerate distribution files
3. Test the workflow in your AI tool of choice
4. The `dist/` folder is regenerated automatically — don't edit files there directly
## Adding a New Workflow Prompt / Skill
Adding a new prompt to `src/` is more than dropping in a file — the installer is
driven by an explicit registry and several docs enumerate the command set. When
you add a `src/plan2code-<name>.md`, do **all** of the following so nothing drifts:
1. **Create the source file** `src/plan2code-<name>.md` — body content **only**,
no YAML frontmatter (the installer generates frontmatter per platform). Keep
it **under 11,000 characters** (`npm test` enforces this).
2. **Register it in the installer.** Add an entry to the `SOURCE_PROMPTS` array in
`install.js` (`source`, `stepNumber`, `name`, `displayName`, `description`, and
`isUtility: true` for non-numbered utilities). If `stepNumber` is a non-numeric
label (e.g. `'handoff'`), add a matching case to `generateStepLabel()` so the
generated description reads correctly.
3. **Update every doc that lists the command set** — keep these in sync, they are
the canonical inventories:
- `README.md` — command table ("When to Use")
- `QUICK-REFERENCE.md` — Commands table
- `.agents-docs/AGENTS-architecture.md` — "Workflow Prompts (in `src/`)" table
- `CHANGELOG.md` — add an entry under the current version
- `docs/index.html`**only** if the new prompt belongs to the core pipeline
shown there; utilities (like `init`, `quick-task`, `handoff`) are deliberately
omitted from that curated marketing list.
4. **Regenerate and validate:** run `node install.js` (regenerates `dist/`) and
`npm test` (character-count validator now covers the new file).
+159
View File
@@ -0,0 +1,159 @@
---
name: plan2code-publish
description: "Publish a GitHub Release for jparkerweb/plan2code whenever CHANGELOG.md's top version is ahead of the latest published release on GitHub — after verifying CHANGELOG.md, version.json, and package.json all agree on the version. Use this skill when the user says 'publish a release', 'create a GitHub release', 'cut a release', 'tag a release', 'tag and release', 'is the changelog published', or otherwise mentions publishing/releasing/tagging this repo."
---
# Plan2Code Release Publisher
Publish a GitHub Release for `jparkerweb/plan2code` whenever `CHANGELOG.md`'s top version is ahead of the latest published release on GitHub. This turns the merged CHANGELOG entry on `main` into an actual GitHub Release (which also creates the `vX.Y.Z` git tag).
**Repo-local by design.** This skill lives in the repo's `.claude/skills/` and is intentionally NOT wired into `install.js` — it is a maintainer dev tool, not part of the shipped product, so it is never installed to `~/.claude/skills/`. Do **not** copy it there: the uninstaller (`uninstallFiles()` in `install.js`) and every re-install's pre-copy cleanup in `install()` both delete every entry matching `/^plan2code-/` under `~/.claude/skills/`, so a copy placed there would be silently removed.
## Workflow
### Step 1 — Preflight: clean working tree
Run `git status --porcelain`. If the output is non-empty, stop immediately — do not switch branches or take any other action. Tell the user:
> Working tree has uncommitted changes. Commit or stash them, then re-run this skill.
### Step 2 — Switch to main and pull
If the working tree is clean, switch to `main` and pull latest. Run these as two separate, non-chained commands (never `&&`/`;`-chain `git`/`gh` commands — Windows PowerShell 5.1 rejects `&&`):
```bash
git checkout main
git pull origin main
```
### Step 3 — Read the three version sources
Read all three files at the repo root and extract each version:
- `CHANGELOG.md` — parse the first `## vX.Y.Z` heading. Strip the leading `v``$CHANGELOG_VERSION`. Note: plan2code CHANGELOG headings are `## vX.Y.Z` (v-prefixed, **no** date and **no** brackets) — different from a `## [x.y.z] - YYYY-MM-DD` format.
- `version.json` — the `version` field → `$VERSION_JSON`. Also read its `releaseDate` field → `$RELEASE_DATE` (informational only — shown at the confirm step, never part of the sync gate; use `(none)` if absent).
- `package.json` (root) → the `version` field → `$PACKAGE_JSON`.
Also capture from `CHANGELOG.md` the **section body** for the top version: everything from the `## vX.Y.Z` heading line itself (heading **included**) up to — but not including — the next `## v` heading, or end-of-file if there is none. Call this `$SECTION`. Keep the `## vX.Y.Z` heading in `$SECTION`; plan2code release bodies include it.
### Step 4 — Version-sync preflight (STOP on mismatch)
All three versions must be identical. This enforces the repo's documented invariant (`.agents-docs/AGENTS-code-style.md` → "Version sync"): `CHANGELOG.md`, `version.json`, and `package.json` must always show the same version number.
If `$CHANGELOG_VERSION`, `$VERSION_JSON`, and `$PACKAGE_JSON` are **not** all equal, **stop** — do not read the release, do not publish. Report exactly which files disagree:
> ⚠️ Version files are out of sync — refusing to publish. The repo requires `CHANGELOG.md`, `version.json`, and `package.json` to match.
>
> - **CHANGELOG.md:** $CHANGELOG_VERSION
> - **version.json:** $VERSION_JSON
> - **package.json:** $PACKAGE_JSON
>
> Fix the mismatch first, then re-run this skill. To realign: pick the intended version (normally the highest / newest CHANGELOG entry) and update the other two files to match — see the "Version sync" gotcha in `.agents-docs/AGENTS-code-style.md`.
This skill never modifies these files — it only reads and compares them.
### Step 5 — Determine the highest published release
List every published (non-draft) release and take the numerically-highest semver tag. Do **not** rely on `gh release view` / GitHub's "Latest" flag: that flag returns whatever release is *marked* latest — normally the newest semver, but a maintainer can manually pin it to an older release, which would make the Step 6 ahead-comparison misfire.
```bash
gh release list --repo jparkerweb/plan2code --limit 100 --json tagName,isDraft -q '.[] | select(.isDraft==false) | .tagName'
```
Strip any leading `v` from each returned tag, compare them as numeric `(major, minor, patch)` tuples (the same rule as Step 6), and take the maximum → `$RELEASE_VERSION`. If the command returns no tags or exits non-zero for **any** reason (no releases yet, transient error, etc.), set `$RELEASE_VERSION = "0.0.0"` — no error-text matching is needed.
### Step 6 — Compare versions
Compare `$CHANGELOG_VERSION` vs `$RELEASE_VERSION` as a numeric `(major, minor, patch)` tuple. Never do a plain string/lexicographic compare — e.g. `"1.9.0" > "1.10.0"` is true as strings but wrong numerically.
### Step 7 — Not ahead: no-op
If `$CHANGELOG_VERSION``$RELEASE_VERSION`, print a simple status message showing both versions and stop:
> CHANGELOG top version ($CHANGELOG_VERSION) is not ahead of the latest published release ($RELEASE_VERSION). Nothing to publish.
No error is raised and no release is created.
### Step 8 — Ahead: compute and confirm
If `$CHANGELOG_VERSION` > `$RELEASE_VERSION`, compute:
- `tag = "v$CHANGELOG_VERSION"`
- `title = "v$CHANGELOG_VERSION"` (plan2code keeps the `v` prefix in release titles)
- `notes` = the header line `# What's New 🎉`, then one blank line, then `$SECTION` verbatim (`$SECTION` already starts with the `## vX.Y.Z` heading). Build this as a real multi-line string with **actual newlines** — the `\n\n` shorthand shown elsewhere means "a blank line," never the literal two-character sequence `\` + `n`. Getting this wrong would run the header and the first CHANGELOG heading together with a stray `\n\n` in the published body.
Present all three to the user and wait for an explicit answer before any write. Offer the optional decorative title suffix — a plain `vX.Y.Z` title is the default, but a release may append one (e.g. `v1.14.0 - 🔍 Review workflow`):
> 🚀 [Publish Plan2Code Release]
>
> CHANGELOG is ahead of the latest published release:
> - **Current release:** $RELEASE_VERSION
> - **CHANGELOG top version:** $CHANGELOG_VERSION
> - **version.json releaseDate:** $RELEASE_DATE (informational — read from `version.json`)
>
> Proposed release:
> - **Tag:** $tag
> - **Title:** $title
> - **Notes:**
> ```
> $notes
> ```
>
> Publish this release? Reply **yes** to publish as-is, **no** to cancel, or provide a decorative suffix to append to the title (e.g. `⇢ 🎆 Feature Name` or `- 🔍 Feature Name`).
If the user supplies a suffix, set `title = "v$CHANGELOG_VERSION " + <suffix>` (single space join) and proceed to publish. The tag and notes are unaffected by the suffix.
### Step 9 — Publish (on approval)
On approval, write `$notes` to a temp file — never pass multiline text inline via `--notes`, that regresses into a quoting bug — then create the release targeting `main`. Two requirements for the temp file: `$notes` must already hold **real newlines** (per Step 8) because `printf '%s'` / `WriteAllText` write it byte-for-byte — a literal `\n` in the string lands literally in the release body; and it MUST be **UTF-8** because the notes contain emoji (`🎉`, `🐛`, `✨`, `🔧`).
**bash (preferred in this environment):**
```bash
NOTES_FILE=$(mktemp)
printf '%s' "$notes" > "$NOTES_FILE"
gh release create "$tag" --repo jparkerweb/plan2code --title "$title" --notes-file "$NOTES_FILE" --target main
rm -f "$NOTES_FILE"
```
**PowerShell:** do NOT use `Set-Content` — under Windows PowerShell 5.1 it writes ANSI/UTF-16 by default and mangles the emoji into `??`. Write UTF-8 **without BOM** (a BOM would leak into the release body):
```powershell
$NotesFile = [System.IO.Path]::GetTempFileName()
[System.IO.File]::WriteAllText($NotesFile, $notes, [System.Text.UTF8Encoding]::new($false))
gh release create "$tag" --repo jparkerweb/plan2code --title "$title" --notes-file "$NotesFile" --target main
Remove-Item -Path $NotesFile
```
Always delete the temp file afterward, regardless of whether `gh release create` succeeded or failed.
**Failure handling — already-exists classification:** if `gh release create` exits non-zero, inspect the error text.
- If and only if it contains the substring `already exists` (real output: `HTTP 422: Validation Failed` / `Release.tag_name already exists`), report this to the user as already published, not as a raw CLI error:
> This version ($CHANGELOG_VERSION) was already published as a release — nothing more to do.
- Every other failure (auth, network, permissions, etc.) must be surfaced to the user verbatim. Never silently reclassify a genuine failure as "already published."
### Step 10 — Verify
Confirm the release now exists and report its URL:
```bash
gh release view "$tag" --repo jparkerweb/plan2code
```
Report the release URL to the user.
## Rules
- **Repo-local only** — this skill is not part of the installed product; never add it to `install.js`, and never copy it to `~/.claude/skills/` (the uninstaller deletes `plan2code-*` entries there).
- **Read-only on version files** — never modify `CHANGELOG.md`, `version.json`, or `package.json`; this skill only reads and compares them.
- **Version-sync gate is hard** (Step 4) — if the three version sources disagree, stop and report; do not publish a release from an inconsistent repo.
- **Never run a local `git tag` or `git push`** — tag creation is delegated entirely to `gh release create --target main`.
- **Always use `--notes-file`**, never inline multiline `--notes`, and always write the notes file as UTF-8 (no BOM) so emoji survive.
- **Always clean up the temp notes file**, even on a mid-run error.
- **Always get explicit approval before any write** (Step 8) — no release is created without a yes (or a yes-with-suffix).
- **Derive the current version from the highest published semver tag** (Step 5), never from GitHub's manually-pinnable "Latest" flag. On an empty or failed release list, treat it as "no prior release" (baseline `0.0.0`) — no error-text matching needed.
- **On a `gh release create` failure** (Step 9), only reclassify as already-published when the error contains `already exists` — every other failure must be shown verbatim, never swallowed.
- **Idempotent and safe to re-run** at any time — re-running after a successful publish hits the Step 7 no-op; re-running after a race-lost publish hits the Step 9 already-exists handling.
File diff suppressed because one or more lines are too long
+1
View File
@@ -11,6 +11,7 @@ plan2code-metrics/package-lock.json
.plan2code-metrics
nul
.cognition/
handoffs/
node_modules/
package-lock.json
SYNC.md
+20
View File
@@ -2,6 +2,26 @@
All notable changes to Plan2Code will be documented in this file.
## v1.16.0
### ✨ Added
- **`/plan2code-handoff` skill** — compacts the current conversation into a self-contained handoff document (written to gitignored `./handoffs/<timestamp>-handoff.md`) so a fresh session or another agent can resume the work
- Always captures a confirmed **Next task**: infers a candidate from context and requires the user to confirm or fill it in before the file is written
- References plan specs, logs, and files by path rather than copying them; strips secrets; suggests follow-on skills and verification steps
- Repo-safe: checks `git check-ignore` and warns (without silently editing `.gitignore`) when `handoffs/` isn't ignored in an arbitrary repo
- **Repo-local release publisher skill** — new `/plan2code-publish` maintainer skill in `.claude/skills/` cuts a GitHub Release from the top `CHANGELOG.md` entry once `CHANGELOG.md`, `version.json`, and `package.json` agree and the version is ahead of the latest published release. Dev tooling only — deliberately excluded from `install.js`, never installed to `~/.claude/skills/`.
### 🐛 Fixed
- **Review workflow next-step suggestion made context-aware** — `/plan2code-review` Session End now reconciles three signals: session context (what preceded the review in the conversation), the user's review intent, and on-disk spec state gathered shell-agnostically — a file-search tool's empty result is never treated as proof that no specs exist. Suggestions render only at actual session end, cite their evidence and its source, and conflicting signals ask one targeted question instead of guessing.
## v1.15.4
### ✨ Added
- **Status line: reasoning effort + context token count** — model segment now appends the current reasoning effort level (e.g. `Sonnet 5 | High`, hidden when the model doesn't support an effort parameter); context bar now shows raw input tokens used alongside the percentage (e.g. `42% (84k)`), independently toggleable via new `items.effort` / `items.contextTokens` config flags
## v1.15.3
### ✨ Added
+1
View File
@@ -13,6 +13,7 @@
| 2 | /plan2code-2-document | PLAN-DRAFT.md | overview.md + Phase files |
| 3 | /plan2code-3-implement | overview.md | Implemented code |
| 4 | /plan2code-4-finalize | overview.md | Archived specs |
| handoff | /plan2code-handoff | Conversation | Self-contained handoff doc in handoffs/ |
## File Structure
+1
View File
@@ -26,6 +26,7 @@ A structured 4-step workflow for developing features and projects with AI assist
| `/plan2code-2-document` | After planning, create implementation specs |
| `/plan2code-3-implement` | Execute implementation (one phase per conversation) |
| `/plan2code-4-finalize` | All phases complete, ready to archive |
| `/plan2code-handoff` | Compact the conversation into a handoff doc for a fresh session |
**Key Rules:**
- Start NEW conversation for each step (and each implementation phase)
+10
View File
@@ -180,6 +180,14 @@ const SOURCE_PROMPTS = [
name: 'finalize',
displayName: 'Finalization Mode',
description: 'Validate, summarize, and archive completed work'
},
{
source: 'plan2code-handoff.md',
stepNumber: 'handoff',
name: 'handoff',
displayName: 'Handoff Mode',
description: 'Compact the conversation into a self-contained handoff document for a fresh session',
isUtility: true
}
];
@@ -199,7 +207,9 @@ function generateSkillName(prompt) {
// Helper function to generate step label for descriptions
function generateStepLabel(prompt) {
if (prompt.stepNumber === 'init') return 'Init';
if (prompt.stepNumber === 'update') return 'Update';
if (prompt.stepNumber === 'review') return 'Review';
if (prompt.stepNumber === 'handoff') return 'Handoff';
return `Step ${prompt.stepNumber}`;
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "plan2code",
"version": "1.15.3",
"version": "1.16.0",
"private": true,
"bin": {
"plan2code": "./install.js"
+131
View File
@@ -0,0 +1,131 @@
# plan2code-handoff
Turn everything useful in the current conversation into a single, self-contained
handoff document that lets a *different* agent — a new session, a teammate's
session, or a subagent — resume the work without re-reading this transcript.
The reader of this document starts with **zero context**. They can see the repo
and can open files, but they cannot see this conversation. Write for them.
## The one hard rule: capture the next task, and confirm it with the user
Every handoff MUST end with a **Next task** that the incoming agent should start
on. This is the single most important part of the document — a handoff with a
vague or missing next step forces the reader to re-derive intent, which is
exactly what this skill exists to prevent.
Determine it like this:
1. **Try to infer it** from the conversation — the open TODO, the failing test,
the plan step you were mid-way through, the thing the user just asked for
next. Look at what's actually unfinished, not just the last message.
2. **Present it to the user for confirmation before writing the file.** If you
inferred a candidate, show it and ask them to confirm or correct it. If you
genuinely can't infer one, ask them to tell you what the next agent should do.
Use `AskUserQuestion` (offer your inferred task as the recommended option) or
a plain question — either is fine.
3. **Do not write the document until the user has confirmed or supplied the next
task.** This gate is mandatory even when your inference feels obviously
correct. The user's answer is the source of truth; your inference is only a
draft of it.
If the user passed a focus area as an argument, treat it as a strong signal for
the next task (and shape the whole document around it), but still confirm.
## Where to write it
Save to `./handoffs/` at the repo root with a timestamped filename so it's
discoverable but doesn't collide with earlier handoffs:
```
./handoffs/<YYYY-MM-DD-HHmm>-handoff.md
```
Get the timestamp from the shell rather than guessing — e.g. PowerShell
`Get-Date -Format 'yyyy-MM-dd-HHmm'`. Create the `handoffs/` directory if it
doesn't exist.
### Make sure you aren't leaking the file into version control
The handoff is working state for the next session, not a project artifact, so it
should stay out of commits and PRs. Don't assume it will — this skill may run in
any repo. Before (or right after) writing, check whether the path is ignored:
- Is this even a git repo? `git rev-parse --is-inside-work-tree` — if it errors,
there's nothing to ignore; skip this and just tell the user where the file is.
- Is the file ignored? `git check-ignore handoffs/` (exit 0 = ignored). This is
the reliable check — a repo may ignore `handoffs/` via a global or nested
`.gitignore`, so don't rely on grepping the root `.gitignore` alone.
If it is **not** ignored, do not silently modify the user's `.gitignore`. Tell
them the file would be tracked by git and offer to add a `handoffs/` line to
`.gitignore` — let them decide. Some users may want handoffs committed so
teammates get them; that's a legitimate choice, so present it, don't force it.
## What to include
Keep it tight and high-signal. Prefer pointers over prose: this repo already
records a lot (plan specs, the loop's NDJSON logs, git history, diffs), so
**reference those by path or URL instead of copying them in**. The reader can
open a file; they can't open your memory.
Use this structure:
```markdown
# Handoff — <short title of the work>
<!-- written <timestamp> -->
## Next task
<the confirmed next task — concrete and actionable, e.g.
"Implement Step 3 of specs/<name>.md: wire the aggregator into cli.ts, then
run `npm run build` in plan2code-metrics/ and fix the two failing tests.">
## Goal / why
<13 sentences: what the user is ultimately trying to achieve, so the reader
can make good judgment calls the instructions don't cover.>
## Current state
<Where things stand right now. What's done, what's in progress, what's broken.
Name the branch. Point at the plan/spec file(s) by path rather than restating
them. Note anything half-applied or left uncommitted.>
## Key files & pointers
<Bulleted paths the reader will need, each with a one-line "why". Include plan
specs, the files you were editing, relevant logs (e.g. .plan2code-loop NDJSON),
and any PR/issue URLs.>
## Gotchas & decisions
<Non-obvious things learned this session: a constraint (e.g. the 11k-char limit
on src/plan2code-*.md), a decision made and why, a dead end already ruled out,
a command that must be run a specific way. Save the reader from re-discovering
these the hard way.>
## Suggested skills
<Which skills the next agent should use, and when — e.g. sync-repo for syncing,
a plan2code workflow phase, /code-review before finishing. Skip if none apply.>
## Verification
<How the reader confirms their work: exact test/build commands, what "done"
looks like.>
```
Adapt the sections to the work — drop any that would be empty rather than
padding them. **Next task** is the only section that is never optional.
## Strip sensitive data
Before writing, remove credentials, API tokens, passwords, and personal
identifiers. If a secret is load-bearing for the next step, reference *where* it
lives (env var name, secret manager entry) rather than its value.
## After writing
Tell the user the path you wrote to and give a one-line summary of the confirmed
next task, so they know what the incoming agent will start on. Mention that a
fresh session can be pointed at the file to resume the work.
If your ignore check above found the file is **not** gitignored (or the repo has
no `.gitignore`, or it isn't a git repo at all), say so plainly here — e.g. "note:
`handoffs/` isn't gitignored in this repo, so this file will show up in `git
status` and could be committed" — and offer to add the ignore line. Never leave
the user unaware that the handoff might ride along into a commit.
+16 -8
View File
@@ -141,7 +141,7 @@ Run every finding through the false-positive detection shortcuts before presenti
> **Totals:** X Critical · Y Warning · Z Suggestion
**Fix options:** Reply `H` (high-priority), `A` (all), or `S 1,3,5` (specific findings).
**Fix options:** Reply `H` to fix Critical + Warning findings, `A` to fix all findings, or `S 1,3,5` to fix specific findings.
**Zero findings:** Skip table and fix options. Dimension Coverage justifies each clean dimension.
@@ -155,16 +155,24 @@ Run every finding through the false-positive detection shortcuts before presenti
## Session End
Render this section only when the session is over: fix options resolved (fixes applied and verified, or user declined) or the review had zero findings. Step 5 ends at fix options — stop there and wait.
Work summary — tell user: scope reviewed, findings count by severity (Critical/Warning/Suggestion), fixes applied, unresolved findings.
After approval, select template based on project state:
**Next step** — suggest what genuinely helps next. Principles to reason from, not a lookup table — adapt; when a case doesn't fit cleanly, say what you verified and ask.
**Pre-condition check:** Before suggesting implement or finalize, verify that `overview.md` AND at least one `phase-*.md` file exist in the specs directory. If they do NOT exist, the document step has not been run yet.
- **Specs dir exists but NO overview.md / phase-*.md files:** "Next: generate implementation docs. NEW conversation: `/plan2code-2-document`"
- **Specs + overview.md + phase files + more phases:** "Next: Phase X. NEW conversation: `/plan2code-3-implement`"
- **Specs + overview.md + phase files + all complete:** "All complete! NEW conversation: `/plan2code-4-finalize`"
- **Standalone:** "Review complete -- [summary]."
- **Plan2Code Workflow Pipeline:** `/plan2code-1-plan``PLAN-*` files · `/plan2code-2-document``overview.md` + `phase-*.md` (the "spec docs") in `specs/<feature>/` · `/plan2code-3-implement` → checks off phase tasks, one phase per run · `/plan2code-4-finalize` → archives to `specs--completed/`.
- **Find specs (any OS/shell):** `specs/` is gitignored, and search tools (Glob/Grep/project search) skip gitignored paths on many platforms — an empty search result is not evidence either way. Check with a terminal listing: `ls specs/<feature>/` (bash/zsh) · `Get-ChildItem specs/<feature>` (PowerShell) · `dir specs\<feature>` (cmd). Feature dir unknown? List `specs/` first. Command errors? Try another shell's form, then read the expected files directly — file reads see gitignored paths. Conclude "no specs" only after a terminal listing or a failed direct read.
- **Reconcile three signals:** session context (what this conversation was doing — a fresh session may have none), user intent (what they asked reviewed), the disk check above. Disk wins on state; context wins on intent and on disk silence; no context → intent + disk decide.
- **plan2code artifact reviewed (a plan, the spec docs, phases) — route on the reviewed feature's own `specs/<feature>/` state (another feature's specs prove nothing here), to the earliest unmet stage, suggesting only a step whose input exists:**
- `PLAN-*` without `overview.md` `/plan2code-2-document`
- `overview.md` without `phase-*.md``/plan2code-2-document`
- Unchecked `- [ ]` tasks in `phase-*.md``/plan2code-3-implement` (checkboxes are ground truth; flag overview conflicts)
- All phase tasks checked → `/plan2code-4-finalize`
- Archived spec → pipeline complete; summary only
- **Anything else** (code/PRs, logs, docs, tickets, emails, a codebase): no pipeline step — close with the summary; add a next action only if the review makes one obvious and actionable.
- **Gates:** unresolved Criticals → fixing them (H/A/S) is the next step. Signals the rules above can't reconcile, or multiple candidate specs → ask one targeted question.
- **Output:** "Next (NEW conversation): `/plan2code-<step>` — [why + how you know]"; otherwise "Review complete -- [summary]."
- **Commit** (code changes): `git add [files] && git commit -m "fix: [desc]" -m "<JIRA>" -m "AI Assisted"` -- derive JIRA from branch.
```
+8 -5
View File
@@ -7,20 +7,20 @@ A persistent three-line status bar for Claude Code that displays model info, pro
**Pro / Max / Teams** — rate limits segment:
```
╭─╮ Opus 4.6 │ plan2code │ feature/statusline │ +12 -3
╭─╮ Opus 4.6 | High │ plan2code │ feature/statusline │ +12 -3
│★│ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
╰─╯ 3h 5m ($4.62) │ ▰▰▰▰▰▱▱▱▱▱▱▱ 42% │ 5h: 28% · 7d: 61%
╰─╯ 3h 5m ($4.62) │ ▰▰▰▰▰▱▱▱▱▱▱▱ 42% (84k) │ 5h: 28% · 7d: 61%
```
**Enterprise / Bedrock / Vertex / PAYG** — session token counts (no `rate_limits` in stdin):
```
╭─╮ Sonnet 4.5 │ plan2code │ main │ +12 -3
╭─╮ Sonnet 4.5 | Medium │ plan2code │ main │ +12 -3
│★│ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
╰─╯ 2m ($0.18) │ ▰▰▱▱▱▱▱▱▱▱▱▱ 18% │ 88k in · 3k out
╰─╯ 2m ($0.18) │ ▰▰▱▱▱▱▱▱▱▱▱▱ 18% (36k) │ 88k in · 3k out
```
**Line 1:** Planny icon | Model name | Project name | Git branch | Uncommitted changes
**Line 1:** Planny icon | Model name + reasoning effort | Project name | Git branch | Uncommitted changes
**Line 2:** Planny icon | Gray separator
**Line 3:** Planny icon | Session duration + cost | Context window bar | Usage (rate limits or token counts)
@@ -63,6 +63,7 @@ Edit `~/.claude/statusline-config.json`:
"compact": false,
"items": {
"model": true,
"effort": true,
"project": true,
"branch": true,
"contextBar": true,
@@ -80,9 +81,11 @@ Edit `~/.claude/statusline-config.json`:
| `color` | `true` | Enable ANSI color output. Set `false` for monochrome. The `NO_COLOR` environment variable (per [no-color.org](https://no-color.org)) also disables color. |
| `compact` | `false` | Two-line mode — drops the mascot icons and the separator line. Goes from 3 lines to 2, no horizontal truncation. |
| `items.model` | `true` | Show model name (Opus, Sonnet, Haiku) |
| `items.effort` | `true` | Append the current reasoning effort level (Low/Medium/High/XHigh/Max) to the model segment, e.g. `Sonnet 5 \| High`. Reads `effort.level` from stdin; hidden when the current model doesn't support an effort parameter (field absent from stdin). |
| `items.project` | `true` | Show project directory name |
| `items.branch` | `true` | Show current git branch (falls back to short SHA when detached HEAD) |
| `items.contextBar` | `true` | Show context window usage bar with percentage |
| `items.contextTokens` | `true` | Append raw tokens used in the context window next to the percentage, e.g. `42% (84k)`. Reads `context_window.total_input_tokens` (the same input-token count `used_percentage` is derived from — excludes output tokens). Requires `items.contextBar` to also be enabled. |
| `items.planUsage` | `true` | Show usage info: rate limits (Pro/Max) or token counts (Bedrock/Vertex/PAYG) |
| `items.linesChanged` | `true` | Show uncommitted git diff stats (+added -removed) |
| `items.duration` | `true` | Show session duration |
@@ -4,9 +4,11 @@
"compact": false,
"items": {
"model": true,
"effort": true,
"project": true,
"branch": true,
"contextBar": true,
"contextTokens": true,
"planUsage": true,
"linesChanged": true,
"duration": true,
+28 -5
View File
@@ -26,9 +26,11 @@ const DEFAULTS = {
compact: false,
items: {
model: true,
effort: true,
project: true,
branch: true,
contextBar: true,
contextTokens: true,
planUsage: true,
linesChanged: true,
duration: true,
@@ -176,6 +178,14 @@ function getModelName(stdinData) {
return model;
}
const EFFORT_LABELS = { low: 'Low', medium: 'Medium', high: 'High', xhigh: 'XHigh', max: 'Max' };
function getEffortLevel(stdinData) {
const level = stdinData?.effort?.level;
if (!level || typeof level !== 'string') return '';
return EFFORT_LABELS[level] || (level.charAt(0).toUpperCase() + level.slice(1));
}
function getProjectName(stdinData) {
const projectDir = stdinData?.workspace?.project_dir;
if (!projectDir || typeof projectDir !== 'string') return '';
@@ -194,7 +204,7 @@ function calculateContextPercent(stdinData, config) {
return Math.round(Math.min(100, (rawUsedTokens / usableTokens) * 100));
}
function formatContextBar(percent, config) {
function formatContextBar(percent, tokens, config) {
if (percent == null) return null;
const clamped = Math.max(0, Math.min(100, percent));
@@ -202,12 +212,15 @@ function formatContextBar(percent, config) {
const filledStr = '▰'.repeat(filled);
const emptyStr = '▱'.repeat(CONTEXT_BAR_LEN - filled);
if (!config.color) return `${filledStr}${emptyStr} ${clamped}%`;
const tokenStr = config.items.contextTokens && tokens != null ? ` (${formatTokenCount(tokens)})` : '';
if (!config.color) return `${filledStr}${emptyStr} ${clamped}%${tokenStr}`;
const barColor = clamped >= CONTEXT_THRESHOLDS.yellow ? C.barRed
: clamped >= CONTEXT_THRESHOLDS.green ? C.barYellow
: C.barGreen;
return `${barColor}${filledStr}${C.gray}${emptyStr}${C.reset} ${barColor}${clamped}%${C.reset}`;
const tokenPart = tokenStr ? `${C.label}${tokenStr}${C.reset}` : '';
return `${barColor}${filledStr}${C.gray}${emptyStr}${C.reset} ${barColor}${clamped}%${C.reset}${tokenPart}`;
}
function formatLinesChanged(stdinData, config) {
@@ -314,7 +327,16 @@ function formatLine1(stdinData, config) {
if (config.items.model) {
const model = getModelName(stdinData);
if (model) segments.push(config.color ? `${C.muted}${model}${C.reset}` : model);
if (model) {
const effort = config.items.effort ? getEffortLevel(stdinData) : '';
if (!effort) {
segments.push(config.color ? `${C.muted}${model}${C.reset}` : model);
} else if (!config.color) {
segments.push(`${model} | ${effort}`);
} else {
segments.push(`${C.muted}${model}${C.reset}${C.gray} | ${C.reset}${C.label}${effort}${C.reset}`);
}
}
}
if (config.items.project) {
@@ -345,7 +367,8 @@ function formatLine2(stdinData, config) {
if (config.items.contextBar) {
const percent = calculateContextPercent(stdinData, config);
const bar = formatContextBar(percent, config);
const tokens = stdinData?.context_window?.total_input_tokens;
const bar = formatContextBar(percent, tokens, config);
if (bar) segments.push(bar);
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "Plan2Code",
"version": "1.15.3",
"version": "1.16.0",
"description": "A structured 4-step workflow methodology for AI-assisted software development",
"keywords": [
"ai",
@@ -17,7 +17,7 @@
"url": "https://github.com/jparkerweb/plan2code"
},
"homepage": "https://plan2code.jparkerweb.com",
"releaseDate": "2026-06-28",
"releaseDate": "2026-07-20",
"mode": "utility"
}