cc-plan-viewer 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # cc-plan-viewer
1
+ # Claude Code Plan Viewer
2
2
 
3
3
  A browser-based review UI for Claude Code plans. When Claude Code enters plan mode, a browser tab opens automatically showing the plan with proper markdown rendering, syntax highlighting, and inline commenting.
4
4
 
@@ -27498,7 +27498,8 @@ var init_lifecycle = __esm({
27498
27498
  import { createServer } from "node:http";
27499
27499
  import fs3 from "node:fs";
27500
27500
  import path3 from "node:path";
27501
- function createApp(plansDirs2) {
27501
+ function createApp(initialPlansDirs) {
27502
+ const plansDirs2 = [...initialPlansDirs];
27502
27503
  const plansDir = plansDirs2[0] || "";
27503
27504
  const app = (0, import_express.default)();
27504
27505
  const server2 = createServer(app);
@@ -27569,6 +27570,10 @@ function createApp(plansDirs2) {
27569
27570
  app.post("/api/plan-updated", (req, res) => {
27570
27571
  const { filePath, planOptions } = req.body;
27571
27572
  const filename = path3.basename(filePath || "");
27573
+ const dir = path3.dirname(filePath || "");
27574
+ if (dir && !plansDirs2.includes(dir) && fs3.existsSync(dir)) {
27575
+ plansDirs2.push(dir);
27576
+ }
27572
27577
  const message = JSON.stringify({
27573
27578
  type: "plan-updated",
27574
27579
  filename,
@@ -6,7 +6,8 @@ import path from 'node:path';
6
6
  import { parsePlan } from './planParser.js';
7
7
  import { saveReview, getReview } from './reviewStore.js';
8
8
  import { resetIdleTimer } from './lifecycle.js';
9
- export function createApp(plansDirs) {
9
+ export function createApp(initialPlansDirs) {
10
+ const plansDirs = [...initialPlansDirs];
10
11
  const plansDir = plansDirs[0] || '';
11
12
  const app = express();
12
13
  const server = createServer(app);
@@ -86,6 +87,11 @@ export function createApp(plansDirs) {
86
87
  app.post('/api/plan-updated', (req, res) => {
87
88
  const { filePath, planOptions } = req.body;
88
89
  const filename = path.basename(filePath || '');
90
+ // Dynamically register new plan directories (e.g., project-level .claude/plans/)
91
+ const dir = path.dirname(filePath || '');
92
+ if (dir && !plansDirs.includes(dir) && fs.existsSync(dir)) {
93
+ plansDirs.push(dir);
94
+ }
89
95
  // Broadcast to all WebSocket clients
90
96
  const message = JSON.stringify({
91
97
  type: 'plan-updated',
@@ -27481,7 +27481,8 @@ function resetIdleTimer() {
27481
27481
  }
27482
27482
 
27483
27483
  // dist/server/server/app.js
27484
- function createApp(plansDirs2) {
27484
+ function createApp(initialPlansDirs) {
27485
+ const plansDirs2 = [...initialPlansDirs];
27485
27486
  const plansDir = plansDirs2[0] || "";
27486
27487
  const app = (0, import_express.default)();
27487
27488
  const server2 = createServer(app);
@@ -27552,6 +27553,10 @@ function createApp(plansDirs2) {
27552
27553
  app.post("/api/plan-updated", (req, res) => {
27553
27554
  const { filePath, planOptions } = req.body;
27554
27555
  const filename = path3.basename(filePath || "");
27556
+ const dir = path3.dirname(filePath || "");
27557
+ if (dir && !plansDirs2.includes(dir) && fs3.existsSync(dir)) {
27558
+ plansDirs2.push(dir);
27559
+ }
27555
27560
  const message = JSON.stringify({
27556
27561
  type: "plan-updated",
27557
27562
  filename,
@@ -14,17 +14,21 @@ const PORT_FILE = path.join(os.tmpdir(), 'cc-plan-viewer-port');
14
14
  const DEBOUNCE_FILE = path.join(os.tmpdir(), 'cc-plan-viewer-opened.json');
15
15
  const DEBOUNCE_MS = 5000; // 5 seconds (prevents rapid re-opens during multi-chunk writes)
16
16
 
17
- // Dynamically find all ~/.claude*/plans/ directories
17
+ // Dynamically find all plans directories (home-level + project-level)
18
18
  function getAllPlansDirs() {
19
+ const dirs = [];
19
20
  const home = os.homedir();
20
21
  try {
21
- return fs.readdirSync(home)
22
+ fs.readdirSync(home)
22
23
  .filter(name => name.startsWith('.claude'))
23
24
  .map(name => path.join(home, name, 'plans'))
24
- .filter(dir => fs.existsSync(dir));
25
- } catch {
26
- return [];
27
- }
25
+ .filter(dir => fs.existsSync(dir))
26
+ .forEach(dir => dirs.push(dir));
27
+ } catch {}
28
+ // Project-level: {cwd}/.claude/plans/
29
+ const projectDir = path.join(process.cwd(), '.claude', 'plans');
30
+ if (fs.existsSync(projectDir)) dirs.push(projectDir);
31
+ return dirs;
28
32
  }
29
33
 
30
34
  function getServerPort() {
@@ -37,10 +41,12 @@ function getServerPort() {
37
41
 
38
42
  function isPlanFile(filePath) {
39
43
  if (!filePath || !filePath.endsWith('.md')) return false;
40
- // Match any ~/.claude*/plans/*.md
44
+ // Home-level: ~/.claude*/plans/*.md
41
45
  const home = os.homedir();
42
46
  const rel = path.relative(home, filePath);
43
- return /^\.claude[^/]*\/plans\/[^/]+\.md$/.test(rel);
47
+ if (/^\.claude[^/]*\/plans\/[^/]+\.md$/.test(rel)) return true;
48
+ // Project-level: */.claude/plans/*.md
49
+ return /\/\.claude\/plans\/[^/]+\.md$/.test(filePath);
44
50
  }
45
51
 
46
52
  function shouldOpenBrowser(filename) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-plan-viewer",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Browser-based PR-style review UI for Claude Code plans",
5
5
  "type": "module",
6
6
  "bin": {