mirror of
https://github.com/jparkerweb/plan2code.git
synced 2026-09-17 16:22:23 -07:00
Compare commits
5 Commits
v1.16.0
...
fda0146969
| Author | SHA1 | Date | |
|---|---|---|---|
| fda0146969 | |||
| 75605e5e41 | |||
| 3b18b42e30 | |||
| 8e457fa6e4 | |||
| 6740e26261 |
@@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
All notable changes to Plan2Code will be documented in this file.
|
All notable changes to Plan2Code will be documented in this file.
|
||||||
|
|
||||||
|
## v1.16.1
|
||||||
|
|
||||||
|
### ✨ Added
|
||||||
|
|
||||||
|
- **Status line: git worktree awareness** — a session running in a linked git worktree now renders the project segment as `repo ⑂ worktree` (e.g. `plan2code ⑂ spike`) instead of only the worktree's directory name, which previously made the session look like an unrelated project
|
||||||
|
- Repo identity resolved from `git rev-parse --git-common-dir`, so it is correct regardless of how the worktree directory was named (bare `<name>.git` main repos included)
|
||||||
|
- A leading repo prefix is stripped from the worktree name (`plan2code-user-auth` → `user-auth`), and the name collapses to a bare `⑂` when it merely restates the branch already on screen — matched across `/ _ . -` separators and type prefixes like `feature/`, and only when the branch is actually displayed
|
||||||
|
- Toggleable via the new `items.worktree` config flag (default on); one extra timeout-bounded `git` call, skipped outside git repos
|
||||||
|
|
||||||
## v1.16.0
|
## v1.16.0
|
||||||
|
|
||||||
### ✨ Added
|
### ✨ Added
|
||||||
|
|||||||
@@ -75,14 +75,8 @@ The install script requires **Node.js** (v14 or later). If you don't have Node.j
|
|||||||
|
|
||||||
Run the interactive installer directly using `npx` with your preferred GitHub authentication method:
|
Run the interactive installer directly using `npx` with your preferred GitHub authentication method:
|
||||||
|
|
||||||
**If you use SSH keys:**
|
|
||||||
```bash
|
```bash
|
||||||
npx git+ssh://git@github.com/jparkerweb/plan2code.git
|
npx git+https://code.jparkerweb.com/jparkerweb/plan2code.git
|
||||||
```
|
|
||||||
|
|
||||||
**If you use HTTPS authentication:**
|
|
||||||
```bash
|
|
||||||
npx git+https://github.com/jparkerweb/plan2code.git
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This downloads the installer to a temporary location, runs it, installs the workflow files to your machine, and cleans up automatically. The installed workflows remain on your system and work independently. To update or reinstall, simply run the command again.
|
This downloads the installer to a temporary location, runs it, installs the workflow files to your machine, and cleans up automatically. The installed workflows remain on your system and work independently. To update or reinstall, simply run the command again.
|
||||||
@@ -93,14 +87,8 @@ This downloads the installer to a temporary location, runs it, installs the work
|
|||||||
|
|
||||||
Run the interactive installer directly using `npx` with your preferred GitHub authentication method:
|
Run the interactive installer directly using `npx` with your preferred GitHub authentication method:
|
||||||
|
|
||||||
**If you use SSH keys:**
|
|
||||||
```bash
|
```bash
|
||||||
npx git+ssh://git@github.com/jparkerweb/plan2code.git
|
npx git+https://code.jparkerweb.com/jparkerweb/plan2code.git
|
||||||
```
|
|
||||||
|
|
||||||
**If you use HTTPS authentication:**
|
|
||||||
```bash
|
|
||||||
npx git+https://github.com/jparkerweb/plan2code.git
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This downloads the installer to a temporary location, runs it, installs the workflow files to your machine, and cleans up automatically. The installed workflows remain on your system and work independently. To update or reinstall, simply run the command again.
|
This downloads the installer to a temporary location, runs it, installs the workflow files to your machine, and cleans up automatically. The installed workflows remain on your system and work independently. To update or reinstall, simply run the command again.
|
||||||
@@ -109,7 +97,7 @@ This downloads the installer to a temporary location, runs it, installs the work
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Clone the repository
|
# Clone the repository
|
||||||
git clone https://github.com/jparkerweb/plan2code.git
|
git clone https://code.jparkerweb.com/jparkerweb/plan2code.git
|
||||||
cd plan2code
|
cd plan2code
|
||||||
|
|
||||||
# Run the interactive installer
|
# Run the interactive installer
|
||||||
|
|||||||
+6
-6
@@ -905,7 +905,7 @@
|
|||||||
<h1 class="code">CODE</h1>
|
<h1 class="code">CODE</h1>
|
||||||
</div>
|
</div>
|
||||||
<p class="hero-subtitle">The AI workflow that puts planning first</p>
|
<p class="hero-subtitle">The AI workflow that puts planning first</p>
|
||||||
<a href="https://github.com/jparkerweb/plan2code" class="github-link" target="_blank" rel="noopener noreferrer">
|
<a href="https://code.jparkerweb.com/jparkerweb/plan2code" class="github-link" target="_blank" rel="noopener noreferrer">
|
||||||
<svg class="github-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
<svg class="github-icon" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
|
||||||
Get the Code
|
Get the Code
|
||||||
</a>
|
</a>
|
||||||
@@ -1083,14 +1083,14 @@
|
|||||||
<h3 class="subheadline">Install the workflow</h3>
|
<h3 class="subheadline">Install the workflow</h3>
|
||||||
<p>Run the install script to copy the Plan2Code prompts to your AI assistant workflow directories. Works with Claude Code, Cursor, GitHub Copilot, Windsurf, and more.</p>
|
<p>Run the install script to copy the Plan2Code prompts to your AI assistant workflow directories. Works with Claude Code, Cursor, GitHub Copilot, Windsurf, and more.</p>
|
||||||
<pre class="code-block"><span class="comment"># Clone the repository</span>
|
<pre class="code-block"><span class="comment"># Clone the repository</span>
|
||||||
<span class="command">git clone https://github.com/jparkerweb/plan2code.git</span>
|
<span class="command">git clone https://code.jparkerweb.com/jparkerweb/plan2code.git</span>
|
||||||
|
|
||||||
<span class="comment"># Navigate to the directory</span>
|
<span class="comment"># Navigate to the directory</span>
|
||||||
<span class="command">cd plan2code</span>
|
<span class="command">cd plan2code</span>
|
||||||
|
|
||||||
<span class="comment"># Run the interactive installer</span>
|
<span class="comment"># Run the interactive installer</span>
|
||||||
<span class="command">node install.js</span></pre>
|
<span class="command">node install.js</span></pre>
|
||||||
<p><a href="https://github.com/jparkerweb/plan2code" class="inline-link" target="_blank" rel="noopener noreferrer">Get the Code →</a></p>
|
<p><a href="https://code.jparkerweb.com/jparkerweb/plan2code" class="inline-link" target="_blank" rel="noopener noreferrer">Get the Code →</a></p>
|
||||||
<div class="install-screenshot">
|
<div class="install-screenshot">
|
||||||
<img src="install-script.jpg" alt="Plan2Code global installation terminal interface showing platform selection menu">
|
<img src="install-script.jpg" alt="Plan2Code global installation terminal interface showing platform selection menu">
|
||||||
</div>
|
</div>
|
||||||
@@ -1124,8 +1124,8 @@
|
|||||||
|
|
||||||
<!-- CTA Section -->
|
<!-- CTA Section -->
|
||||||
<section class="cta">
|
<section class="cta">
|
||||||
<h2 class="cta-text headline"><a class="-plain" href="https://github.com/jparkerweb/plan2code">START<br>PLANNING<br>NOW</a></h2>
|
<h2 class="cta-text headline"><a class="-plain" href="https://code.jparkerweb.com/jparkerweb/plan2code">START<br>PLANNING<br>NOW</a></h2>
|
||||||
<a href="https://github.com/jparkerweb/plan2code" class="cta-button" target="_blank" rel="noopener noreferrer">GET THE CODE</a>
|
<a href="https://code.jparkerweb.com/jparkerweb/plan2code" class="cta-button" target="_blank" rel="noopener noreferrer">GET THE CODE</a>
|
||||||
<p class="cta-subtext">Transform your AI development workflow today</p>
|
<p class="cta-subtext">Transform your AI development workflow today</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -1199,7 +1199,7 @@
|
|||||||
document.querySelector('.cta-text').setAttribute('tabindex', '0');
|
document.querySelector('.cta-text').setAttribute('tabindex', '0');
|
||||||
document.querySelector('.cta-text').addEventListener('keypress', (e) => {
|
document.querySelector('.cta-text').addEventListener('keypress', (e) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
window.open('https://github.com/jparkerweb/plan2code', '_blank');
|
window.open('https://code.jparkerweb.com/jparkerweb/plan2code', '_blank');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+2
-2
@@ -646,7 +646,7 @@ function displayHeader() {
|
|||||||
console.log('║ ╰───╯ Welcome to Plan2Code! ║');
|
console.log('║ ╰───╯ Welcome to Plan2Code! ║');
|
||||||
console.log('║ ║');
|
console.log('║ ║');
|
||||||
console.log('║ G L O B A L I N S T A L L A T I O N S Y S T E M ║');
|
console.log('║ G L O B A L I N S T A L L A T I O N S Y S T E M ║');
|
||||||
console.log('║ https://jparkerweb.github.io/plan2code ║');
|
console.log('║ https://code.jparkerweb.com/jparkerweb/plan2code ║');
|
||||||
console.log('║ ║');
|
console.log('║ ║');
|
||||||
console.log('╚═════════════════════════════════════════════════════════╝');
|
console.log('╚═════════════════════════════════════════════════════════╝');
|
||||||
console.log(COLORS.RESET);
|
console.log(COLORS.RESET);
|
||||||
@@ -1299,7 +1299,7 @@ async function install(targets = null) {
|
|||||||
if (totalErrors === 0) {
|
if (totalErrors === 0) {
|
||||||
console.log(`${COLORS.GREEN} ╭───╮${COLORS.RESET} ${COLORS.BRIGHT}All done! Happy coding!${COLORS.RESET}`);
|
console.log(`${COLORS.GREEN} ╭───╮${COLORS.RESET} ${COLORS.BRIGHT}All done! Happy coding!${COLORS.RESET}`);
|
||||||
console.log(`${COLORS.GREEN} │ ${COLORS.CYAN}★${COLORS.GREEN} │${COLORS.RESET} ${COLORS.BRIGHT}If this is your first time using Plan2Code, read the docs here:${COLORS.RESET}`);
|
console.log(`${COLORS.GREEN} │ ${COLORS.CYAN}★${COLORS.GREEN} │${COLORS.RESET} ${COLORS.BRIGHT}If this is your first time using Plan2Code, read the docs here:${COLORS.RESET}`);
|
||||||
console.log(`${COLORS.GREEN} │ ${COLORS.BRIGHT}◡${COLORS.GREEN} │${COLORS.RESET} ${COLORS.BRIGHT}https://github.com/jparkerweb/plan2code${COLORS.RESET}`);
|
console.log(`${COLORS.GREEN} │ ${COLORS.BRIGHT}◡${COLORS.GREEN} │${COLORS.RESET} ${COLORS.BRIGHT}https://code.jparkerweb.com/jparkerweb/plan2code${COLORS.RESET}`);
|
||||||
console.log(`${COLORS.GREEN} ╰───╯${COLORS.RESET}`);
|
console.log(`${COLORS.GREEN} ╰───╯${COLORS.RESET}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "plan2code",
|
"name": "plan2code",
|
||||||
"version": "1.16.0",
|
"version": "1.16.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"plan2code": "./install.js"
|
"plan2code": "./install.js"
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Examples:
|
|||||||
plan2code-bot --resume
|
plan2code-bot --resume
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
https://jparkerweb.github.io/plan2code
|
https://code.jparkerweb.com/jparkerweb/plan2code
|
||||||
`);
|
`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,14 @@ A persistent three-line status bar for Claude Code that displays model info, pro
|
|||||||
╰─╯ 2m ($0.18) │ ▰▰▱▱▱▱▱▱▱▱▱▱ 18% (36k) │ 88k in · 3k out
|
╰─╯ 2m ($0.18) │ ▰▰▱▱▱▱▱▱▱▱▱▱ 18% (36k) │ 88k in · 3k out
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Git worktree** — session running in a linked worktree at `C:\git\plan2code-user-auth`:
|
||||||
|
|
||||||
|
```
|
||||||
|
╭─╮ Opus 4.6 | High │ plan2code ⑂ │ feature/user-auth │ +12 -3
|
||||||
|
│★│ ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
|
||||||
|
╰─╯ 3h 5m ($4.62) │ ▰▰▰▰▰▱▱▱▱▱▱▱ 42% (84k) │ 5h: 28% · 7d: 61%
|
||||||
|
```
|
||||||
|
|
||||||
**Line 1:** Planny icon | Model name + reasoning effort | 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 2:** Planny icon | Gray separator
|
||||||
**Line 3:** Planny icon | Session duration + cost | Context window bar | Usage (rate limits or token counts)
|
**Line 3:** Planny icon | Session duration + cost | Context window bar | Usage (rate limits or token counts)
|
||||||
@@ -65,6 +73,7 @@ Edit `~/.claude/statusline-config.json`:
|
|||||||
"model": true,
|
"model": true,
|
||||||
"effort": true,
|
"effort": true,
|
||||||
"project": true,
|
"project": true,
|
||||||
|
"worktree": true,
|
||||||
"branch": true,
|
"branch": true,
|
||||||
"contextBar": true,
|
"contextBar": true,
|
||||||
"planUsage": true,
|
"planUsage": true,
|
||||||
@@ -83,6 +92,7 @@ Edit `~/.claude/statusline-config.json`:
|
|||||||
| `items.model` | `true` | Show model name (Opus, Sonnet, Haiku) |
|
| `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.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.project` | `true` | Show project directory name |
|
||||||
|
| `items.worktree` | `true` | Detect [git worktrees](https://git-scm.com/docs/git-worktree) and render the project segment as `repo ⑂ worktree` instead of just the worktree's directory name. See [Worktree Display](#worktree-display). Requires `items.project`. |
|
||||||
| `items.branch` | `true` | Show current git branch (falls back to short SHA when detached HEAD) |
|
| `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.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.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. |
|
||||||
@@ -101,6 +111,27 @@ Malformed config falls back to defaults silently. Type errors on individual keys
|
|||||||
| Copilot CLI | Planned | Deferred — CLI lacks status line script support as of v0.0.421 |
|
| Copilot CLI | Planned | Deferred — CLI lacks status line script support as of v0.0.421 |
|
||||||
| Others | Not supported | Codex CLI, Gemini CLI have built-in status, not scriptable |
|
| Others | Not supported | Codex CLI, Gemini CLI have built-in status, not scriptable |
|
||||||
|
|
||||||
|
## Worktree Display
|
||||||
|
|
||||||
|
With `items.worktree` disabled, a session in a linked worktree shows only that worktree's directory name (`plan2code-user-auth`) — the underlying repository identity is lost, and the session looks like an unrelated project.
|
||||||
|
|
||||||
|
When enabled, the project segment becomes `repo ⑂ worktree`:
|
||||||
|
|
||||||
|
| Worktree directory | Branch | Rendered | Why |
|
||||||
|
|--------------------|--------|----------|-----|
|
||||||
|
| `plan2code` (primary checkout) | `main` | `plan2code` | Not a linked worktree — unchanged |
|
||||||
|
| `plan2code-spike` | `spike-thing` | `plan2code ⑂ spike` | Repo prefix stripped from the worktree name |
|
||||||
|
| `plan2code-user-auth` | `feature/user-auth` | `plan2code ⑂` | Name is redundant with the visible branch — collapses to the bare marker |
|
||||||
|
| `plan2code-user-auth` | `feature/user-auth`, `items.branch: false` | `plan2code ⑂ user-auth` | No branch shown, so the name is kept |
|
||||||
|
|
||||||
|
Details:
|
||||||
|
|
||||||
|
- **Detection** — a single `git rev-parse --git-dir --git-common-dir`. The two paths differ only inside a linked worktree. The true repo name comes from `--git-common-dir` (its parent directory, or the `<name>.git` basename for a bare main repo), so it is correct regardless of how the worktree directory was named.
|
||||||
|
- **Prefix stripping** — a leading repo name followed by `-`, `_`, or `.` is removed, so `plan2code-user-auth` reads as `user-auth`.
|
||||||
|
- **Redundancy collapse** — worktree directories usually mirror their branch. The name is dropped (leaving `⑂`) when it matches the branch after normalizing case and `/ _ . -` separators, compared against both the full branch and its trailing segment so type prefixes like `feature/` don't defeat the match. This only applies when the branch is actually displayed.
|
||||||
|
- **Color** — the repo keeps its bold silver; the `⑂` marker and worktree name render in amber so a non-primary checkout is obvious at a glance. Monochrome output is `repo ⑂ worktree`.
|
||||||
|
- **Cost** — one extra `git` invocation, subject to the same 1.5s timeout, and skipped entirely outside git repos.
|
||||||
|
|
||||||
## Usage Display
|
## Usage Display
|
||||||
|
|
||||||
The usage segment reads data directly from Claude Code's stdin JSON — no API calls, no auth needed, no background processes.
|
The usage segment reads data directly from Claude Code's stdin JSON — no API calls, no auth needed, no background processes.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
"model": true,
|
"model": true,
|
||||||
"effort": true,
|
"effort": true,
|
||||||
"project": true,
|
"project": true,
|
||||||
|
"worktree": true,
|
||||||
"branch": true,
|
"branch": true,
|
||||||
"contextBar": true,
|
"contextBar": true,
|
||||||
"contextTokens": true,
|
"contextTokens": true,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const DEFAULTS = {
|
|||||||
model: true,
|
model: true,
|
||||||
effort: true,
|
effort: true,
|
||||||
project: true,
|
project: true,
|
||||||
|
worktree: true,
|
||||||
branch: true,
|
branch: true,
|
||||||
contextBar: true,
|
contextBar: true,
|
||||||
contextTokens: true,
|
contextTokens: true,
|
||||||
@@ -90,6 +91,7 @@ const C = {
|
|||||||
// Plan2Code brand
|
// Plan2Code brand
|
||||||
teal: rgb(190, 192, 200), // Silver — repo
|
teal: rgb(190, 192, 200), // Silver — repo
|
||||||
sky: rgb(120, 195, 255), // Light sky blue — branch
|
sky: rgb(120, 195, 255), // Light sky blue — branch
|
||||||
|
amber: rgb(235, 170, 95), // Amber — linked worktree marker
|
||||||
muted: rgb(40, 120, 200), // Mid blue — model
|
muted: rgb(40, 120, 200), // Mid blue — model
|
||||||
label: rgb(130, 135, 150), // Mid gray — field labels (5h, 7d)
|
label: rgb(130, 135, 150), // Mid gray — field labels (5h, 7d)
|
||||||
// Bar & quota thresholds
|
// Bar & quota thresholds
|
||||||
@@ -150,6 +152,54 @@ function getGitBranch(stdinData) {
|
|||||||
return sha || '';
|
return sha || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Linked worktrees have their own .git dir under the main repo's
|
||||||
|
// .git/worktrees/<name>, while --git-common-dir still points at the main repo's
|
||||||
|
// .git. Equal paths mean we're in the primary checkout.
|
||||||
|
function getWorktreeInfo(cwd) {
|
||||||
|
const raw = gitExec(['rev-parse', '--git-dir', '--git-common-dir'], cwd);
|
||||||
|
if (!raw) return null;
|
||||||
|
|
||||||
|
const [gitDir, commonDir] = raw.split('\n').map((p) => path.resolve(cwd, p.trim()));
|
||||||
|
if (!gitDir || !commonDir) return null;
|
||||||
|
|
||||||
|
const samePath = process.platform === 'win32'
|
||||||
|
? gitDir.toLowerCase() === commonDir.toLowerCase()
|
||||||
|
: gitDir === commonDir;
|
||||||
|
if (samePath) return null;
|
||||||
|
|
||||||
|
// commonDir is normally <repo>/.git; bare repos use <name>.git directly
|
||||||
|
const commonBase = path.basename(commonDir);
|
||||||
|
const repoName = commonBase === '.git'
|
||||||
|
? path.basename(path.dirname(commonDir))
|
||||||
|
: commonBase.replace(/\.git$/i, '');
|
||||||
|
|
||||||
|
const toplevel = gitExec(['rev-parse', '--show-toplevel'], cwd);
|
||||||
|
const worktreeName = path.basename(toplevel || cwd);
|
||||||
|
if (!repoName || !worktreeName) return null;
|
||||||
|
|
||||||
|
return { repoName, worktreeName };
|
||||||
|
}
|
||||||
|
|
||||||
|
// "plan2code-user-auth" in repo "plan2code" reads as just "user-auth"
|
||||||
|
function stripRepoPrefix(worktreeName, repoName) {
|
||||||
|
const lowerWt = worktreeName.toLowerCase();
|
||||||
|
const lowerRepo = repoName.toLowerCase();
|
||||||
|
if (!lowerWt.startsWith(lowerRepo) || lowerWt === lowerRepo) return worktreeName;
|
||||||
|
const rest = worktreeName.slice(repoName.length);
|
||||||
|
return /^[-_.]/.test(rest) ? rest.slice(1) : worktreeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizeName = (s) => s.toLowerCase().replace(/[/_.\s-]+/g, '-').replace(/^-|-$/g, '');
|
||||||
|
|
||||||
|
// Worktree dirs usually mirror their branch (plan2code-user-auth / feature/user-auth).
|
||||||
|
// Compare against both the full branch and its trailing segment so the common
|
||||||
|
// type prefixes (feature/, bugfix/, ...) don't defeat the match.
|
||||||
|
function isRedundantWithBranch(worktreeName, branch) {
|
||||||
|
if (!branch) return false;
|
||||||
|
const candidates = new Set([normalizeName(branch), normalizeName(branch.split('/').pop())]);
|
||||||
|
return candidates.has(normalizeName(worktreeName));
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Formatters
|
// Formatters
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -192,6 +242,34 @@ function getProjectName(stdinData) {
|
|||||||
return path.basename(projectDir);
|
return path.basename(projectDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the project segment: "plan2code" normally, "plan2code ⑂ spike" in a
|
||||||
|
// linked worktree — the name collapsing to a bare ⑂ when the branch says it already.
|
||||||
|
function formatProject(stdinData, config, branch) {
|
||||||
|
const project = getProjectName(stdinData);
|
||||||
|
if (!project) return null;
|
||||||
|
const plain = (text) => (config.color ? `${C.bold}${C.teal}${text}${C.reset}` : text);
|
||||||
|
|
||||||
|
if (!config.items.worktree) return plain(project);
|
||||||
|
|
||||||
|
const cwd = stdinData?.workspace?.project_dir || process.cwd();
|
||||||
|
if (!isGitRepo(cwd)) return plain(project);
|
||||||
|
|
||||||
|
const info = getWorktreeInfo(cwd);
|
||||||
|
if (!info) return plain(project);
|
||||||
|
|
||||||
|
const shortName = stripRepoPrefix(info.worktreeName, info.repoName);
|
||||||
|
// Only dedupe against a branch the user can actually see — otherwise the
|
||||||
|
// worktree identity would vanish entirely.
|
||||||
|
const visibleBranch = config.items.branch ? branch : '';
|
||||||
|
const redundant = isRedundantWithBranch(shortName, visibleBranch)
|
||||||
|
|| isRedundantWithBranch(info.worktreeName, visibleBranch)
|
||||||
|
|| normalizeName(shortName) === normalizeName(info.repoName);
|
||||||
|
const marker = redundant ? '⑂' : `⑂ ${shortName}`;
|
||||||
|
|
||||||
|
if (!config.color) return `${info.repoName} ${marker}`;
|
||||||
|
return `${C.bold}${C.teal}${info.repoName}${C.reset} ${C.amber}${marker}${C.reset}`;
|
||||||
|
}
|
||||||
|
|
||||||
function calculateContextPercent(stdinData, config) {
|
function calculateContextPercent(stdinData, config) {
|
||||||
const cw = stdinData?.context_window;
|
const cw = stdinData?.context_window;
|
||||||
if (!cw) return null;
|
if (!cw) return null;
|
||||||
@@ -339,14 +417,16 @@ function formatLine1(stdinData, config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Branch is resolved first — the project segment dedupes the worktree name against it
|
||||||
|
const branch = config.items.branch || config.items.worktree ? getGitBranch(stdinData) : '';
|
||||||
|
|
||||||
if (config.items.project) {
|
if (config.items.project) {
|
||||||
const project = getProjectName(stdinData);
|
const project = formatProject(stdinData, config, branch);
|
||||||
if (project) segments.push(config.color ? `${C.bold}${C.teal}${project}${C.reset}` : project);
|
if (project) segments.push(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.items.branch) {
|
if (config.items.branch && branch) {
|
||||||
const branch = getGitBranch(stdinData);
|
segments.push(config.color ? `${C.sky}${branch}${C.reset}` : branch);
|
||||||
if (branch) segments.push(config.color ? `${C.sky}${branch}${C.reset}` : branch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.items.linesChanged) {
|
if (config.items.linesChanged) {
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "Plan2Code",
|
"name": "Plan2Code",
|
||||||
"version": "1.16.0",
|
"version": "1.16.1",
|
||||||
"description": "A structured 4-step workflow methodology for AI-assisted software development",
|
"description": "A structured 4-step workflow methodology for AI-assisted software development",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"ai",
|
"ai",
|
||||||
@@ -14,10 +14,10 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/jparkerweb/plan2code"
|
"url": "https://code.jparkerweb.com/jparkerweb/plan2code"
|
||||||
},
|
},
|
||||||
"homepage": "https://plan2code.jparkerweb.com",
|
"homepage": "https://code.jparkerweb.com/jparkerweb/plan2code",
|
||||||
"releaseDate": "2026-07-20",
|
"releaseDate": "2026-07-31",
|
||||||
"mode": "utility"
|
"mode": "utility"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user