prjct-cli 0.10.13 → 0.11.0
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/CHANGELOG.md +58 -0
- package/CLAUDE.md +47 -2
- package/bin/dev.js +217 -0
- package/bin/prjct +10 -0
- package/bin/serve.js +78 -0
- package/core/agentic/command-executor.js +38 -112
- package/core/agentic/prompt-builder.js +72 -0
- package/core/bus/index.js +322 -0
- package/core/command-registry.js +65 -0
- package/core/domain/snapshot-manager.js +375 -0
- package/core/plugin/hooks.js +313 -0
- package/core/plugin/index.js +52 -0
- package/core/plugin/loader.js +331 -0
- package/core/plugin/registry.js +325 -0
- package/core/plugins/webhook.js +143 -0
- package/core/session/index.js +449 -0
- package/core/session/metrics.js +293 -0
- package/package.json +18 -4
- package/templates/agentic/agent-routing.md +42 -9
- package/templates/agentic/checklist-routing.md +98 -0
- package/templates/checklists/accessibility.md +33 -0
- package/templates/checklists/architecture.md +28 -0
- package/templates/checklists/code-quality.md +28 -0
- package/templates/checklists/data.md +33 -0
- package/templates/checklists/documentation.md +33 -0
- package/templates/checklists/infrastructure.md +33 -0
- package/templates/checklists/performance.md +33 -0
- package/templates/checklists/security.md +33 -0
- package/templates/checklists/testing.md +33 -0
- package/templates/checklists/ux-ui.md +37 -0
- package/templates/commands/bug.md +27 -1
- package/templates/commands/done.md +176 -54
- package/templates/commands/feature.md +38 -1
- package/templates/commands/history.md +176 -0
- package/templates/commands/init.md +28 -1
- package/templates/commands/now.md +191 -9
- package/templates/commands/pause.md +176 -12
- package/templates/commands/redo.md +142 -0
- package/templates/commands/resume.md +166 -62
- package/templates/commands/serve.md +121 -0
- package/templates/commands/ship.md +45 -1
- package/templates/commands/sync.md +34 -1
- package/templates/commands/task.md +27 -1
- package/templates/commands/undo.md +152 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: [Read, Write, Bash]
|
|
3
|
+
description: 'Redo previously undone changes'
|
|
4
|
+
timestamp-rule: 'GetTimestamp() for ALL timestamps'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# /p:redo - Redo Previously Undone Snapshot
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
Restores a previously undone snapshot. Only works if you have recently used /p:undo.
|
|
11
|
+
|
|
12
|
+
## Context Variables
|
|
13
|
+
- `{projectId}`: From `.prjct/prjct.config.json`
|
|
14
|
+
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
15
|
+
- `{snapshotDir}`: `{globalPath}/snapshots`
|
|
16
|
+
- `{memoryPath}`: `{globalPath}/memory/context.jsonl`
|
|
17
|
+
- `{redoStackPath}`: `{snapshotDir}/redo-stack.json`
|
|
18
|
+
|
|
19
|
+
## Step 1: Read Config
|
|
20
|
+
|
|
21
|
+
READ: `.prjct/prjct.config.json`
|
|
22
|
+
EXTRACT: `projectId`
|
|
23
|
+
|
|
24
|
+
IF file not found:
|
|
25
|
+
OUTPUT: "No prjct project. Run /p:init first."
|
|
26
|
+
STOP
|
|
27
|
+
|
|
28
|
+
## Step 2: Check Redo Stack
|
|
29
|
+
|
|
30
|
+
READ: `{redoStackPath}`
|
|
31
|
+
|
|
32
|
+
IF file not found OR empty OR equals "[]":
|
|
33
|
+
OUTPUT: "⚠️ Nothing to redo. Use /p:undo first."
|
|
34
|
+
STOP
|
|
35
|
+
|
|
36
|
+
PARSE as JSON array
|
|
37
|
+
GET last item as {redoSnapshot}
|
|
38
|
+
|
|
39
|
+
IF array is empty:
|
|
40
|
+
OUTPUT: "⚠️ Nothing to redo. Use /p:undo first."
|
|
41
|
+
STOP
|
|
42
|
+
|
|
43
|
+
EXTRACT from {redoSnapshot}:
|
|
44
|
+
- `{redoHash}`: hash
|
|
45
|
+
- `{redoMessage}`: message
|
|
46
|
+
- `{redoTimestamp}`: timestamp
|
|
47
|
+
|
|
48
|
+
## Step 3: Get Current State
|
|
49
|
+
|
|
50
|
+
BASH: `cd {snapshotDir} && git rev-parse HEAD`
|
|
51
|
+
CAPTURE as {currentHash}
|
|
52
|
+
|
|
53
|
+
BASH: `cd {snapshotDir} && git log -1 --pretty=format:'%s' {currentHash}`
|
|
54
|
+
CAPTURE as {currentMessage}
|
|
55
|
+
|
|
56
|
+
## Step 4: Get Files That Will Change
|
|
57
|
+
|
|
58
|
+
BASH: `cd {snapshotDir} && git diff --name-only {currentHash} {redoHash}`
|
|
59
|
+
CAPTURE as {affectedFiles}
|
|
60
|
+
|
|
61
|
+
COUNT files as {fileCount}
|
|
62
|
+
|
|
63
|
+
## Step 5: Restore Redo Snapshot
|
|
64
|
+
|
|
65
|
+
### Checkout files from redo snapshot
|
|
66
|
+
BASH: `cd {snapshotDir} && git checkout {redoHash} -- .`
|
|
67
|
+
|
|
68
|
+
### Copy files back to project
|
|
69
|
+
For each file in {affectedFiles}:
|
|
70
|
+
- Source: `{snapshotDir}/{file}`
|
|
71
|
+
- Destination: `{projectPath}/{file}`
|
|
72
|
+
- Copy content
|
|
73
|
+
|
|
74
|
+
## Step 6: Remove from Redo Stack
|
|
75
|
+
|
|
76
|
+
READ: `{redoStackPath}`
|
|
77
|
+
PARSE as JSON array
|
|
78
|
+
REMOVE last item
|
|
79
|
+
WRITE: `{redoStackPath}`
|
|
80
|
+
|
|
81
|
+
## Step 7: Log to Memory
|
|
82
|
+
|
|
83
|
+
APPEND to: `{memoryPath}`
|
|
84
|
+
|
|
85
|
+
Single line (JSONL):
|
|
86
|
+
```json
|
|
87
|
+
{"timestamp":"{GetTimestamp()}","action":"snapshot_redo","from":"{currentHash}","to":"{redoHash}","files":{fileCount}}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Step 8: Log to Manifest
|
|
91
|
+
|
|
92
|
+
APPEND to: `{snapshotDir}/manifest.jsonl`
|
|
93
|
+
|
|
94
|
+
Single line (JSONL):
|
|
95
|
+
```json
|
|
96
|
+
{"type":"redo","from":"{currentHash}","to":"{redoHash}","timestamp":"{GetTimestamp()}","files":{fileCount}}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Output
|
|
100
|
+
|
|
101
|
+
SUCCESS:
|
|
102
|
+
```
|
|
103
|
+
⏩ Redone: {redoMessage}
|
|
104
|
+
|
|
105
|
+
Restored from: {currentMessage}
|
|
106
|
+
Files affected: {fileCount}
|
|
107
|
+
|
|
108
|
+
/p:undo to undo again | /p:history to see all snapshots
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Error Handling
|
|
112
|
+
|
|
113
|
+
| Error | Response | Action |
|
|
114
|
+
|-------|----------|--------|
|
|
115
|
+
| No redo stack | "Nothing to redo" | STOP |
|
|
116
|
+
| Empty redo stack | "Nothing to redo" | STOP |
|
|
117
|
+
| Git error | Show error message | STOP |
|
|
118
|
+
| File copy fails | "Failed to restore {file}" | CONTINUE |
|
|
119
|
+
|
|
120
|
+
## Examples
|
|
121
|
+
|
|
122
|
+
### Example 1: Successful Redo
|
|
123
|
+
```
|
|
124
|
+
⏩ Redone: Ship authentication feature
|
|
125
|
+
|
|
126
|
+
Restored from: Add login form
|
|
127
|
+
Files affected: 5
|
|
128
|
+
|
|
129
|
+
/p:undo to undo again | /p:history to see all snapshots
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Example 2: Nothing to Redo
|
|
133
|
+
```
|
|
134
|
+
⚠️ Nothing to redo. Use /p:undo first.
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Notes
|
|
138
|
+
|
|
139
|
+
- Redo only works after /p:undo
|
|
140
|
+
- Creating a new snapshot clears the redo stack
|
|
141
|
+
- Multiple redos are possible if you undid multiple times
|
|
142
|
+
- Redo stack is project-specific
|
|
@@ -1,97 +1,201 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Read, Write,
|
|
3
|
-
description: 'Resume paused
|
|
4
|
-
timestamp-rule: 'GetTimestamp() for
|
|
2
|
+
allowed-tools: [Read, Write, Bash]
|
|
3
|
+
description: 'Resume paused session'
|
|
4
|
+
timestamp-rule: 'GetTimestamp() for all timestamps'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# /p:resume
|
|
7
|
+
# /p:resume - Resume Paused Session
|
|
8
|
+
|
|
9
|
+
## Context Variables
|
|
10
|
+
- `{projectId}`: From `.prjct/prjct.config.json`
|
|
11
|
+
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
12
|
+
- `{sessionPath}`: `{globalPath}/sessions/current.json`
|
|
13
|
+
- `{nowPath}`: `{globalPath}/core/now.md`
|
|
14
|
+
- `{memoryPath}`: `{globalPath}/memory/context.jsonl`
|
|
15
|
+
|
|
16
|
+
## Step 1: Read Config
|
|
17
|
+
|
|
18
|
+
READ: `.prjct/prjct.config.json`
|
|
19
|
+
EXTRACT: `projectId`
|
|
20
|
+
|
|
21
|
+
IF file not found:
|
|
22
|
+
OUTPUT: "No prjct project. Run /p:init first."
|
|
23
|
+
STOP
|
|
24
|
+
|
|
25
|
+
## Step 2: Check Session State
|
|
26
|
+
|
|
27
|
+
READ: `{sessionPath}`
|
|
28
|
+
|
|
29
|
+
IF file not found OR empty:
|
|
30
|
+
OUTPUT:
|
|
31
|
+
```
|
|
32
|
+
⚠️ No paused session to resume.
|
|
33
|
+
|
|
34
|
+
Start a new task:
|
|
35
|
+
• /p:now <task>
|
|
36
|
+
```
|
|
37
|
+
STOP
|
|
38
|
+
|
|
39
|
+
PARSE as JSON → {session}
|
|
40
|
+
|
|
41
|
+
IF {session.status} == "active":
|
|
42
|
+
CALCULATE: {elapsed} = time since last start/resume
|
|
43
|
+
OUTPUT:
|
|
44
|
+
```
|
|
45
|
+
▶️ Already active: {session.task}
|
|
46
|
+
|
|
47
|
+
Session: {session.id}
|
|
48
|
+
Working for: {elapsed}
|
|
49
|
+
|
|
50
|
+
/p:done to complete | /p:pause to pause
|
|
51
|
+
```
|
|
52
|
+
STOP
|
|
53
|
+
|
|
54
|
+
IF {session.status} == "completed":
|
|
55
|
+
OUTPUT:
|
|
56
|
+
```
|
|
57
|
+
⚠️ Session already completed.
|
|
58
|
+
|
|
59
|
+
Start a new task:
|
|
60
|
+
• /p:now <task>
|
|
61
|
+
```
|
|
62
|
+
STOP
|
|
63
|
+
|
|
64
|
+
IF {session.status} != "paused":
|
|
65
|
+
OUTPUT: "⚠️ No paused session to resume."
|
|
66
|
+
STOP
|
|
67
|
+
|
|
68
|
+
## Step 3: Calculate Pause Duration
|
|
69
|
+
|
|
70
|
+
SET: {now} = GetTimestamp()
|
|
71
|
+
SET: {pauseDuration} = time since {session.pausedAt}
|
|
72
|
+
SET: {pauseFormatted} = format as "Xh Ym" or "Xm"
|
|
73
|
+
|
|
74
|
+
## Step 4: Update Session
|
|
75
|
+
|
|
76
|
+
UPDATE {session}:
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"id": "{session.id}",
|
|
80
|
+
"projectId": "{session.projectId}",
|
|
81
|
+
"task": "{session.task}",
|
|
82
|
+
"status": "active",
|
|
83
|
+
"startedAt": "{session.startedAt}",
|
|
84
|
+
"pausedAt": null,
|
|
85
|
+
"completedAt": null,
|
|
86
|
+
"duration": {session.duration},
|
|
87
|
+
"metrics": {session.metrics},
|
|
88
|
+
"timeline": [
|
|
89
|
+
...{session.timeline},
|
|
90
|
+
{"type": "resume", "at": "{now}"}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
8
94
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- Blocks if active exists
|
|
95
|
+
WRITE: `{sessionPath}`
|
|
96
|
+
Content: Updated session JSON
|
|
12
97
|
|
|
13
|
-
##
|
|
14
|
-
1. Select: last/ID/# → Set status='active', resumed={GetTimestamp()}
|
|
15
|
-
2. Update stack.jsonl + now.md → Log resume
|
|
98
|
+
## Step 5: Update Legacy now.md
|
|
16
99
|
|
|
17
|
-
|
|
18
|
-
|
|
100
|
+
WRITE: `{nowPath}`
|
|
101
|
+
Content:
|
|
102
|
+
```markdown
|
|
103
|
+
# NOW
|
|
19
104
|
|
|
20
|
-
|
|
105
|
+
**{session.task}**
|
|
21
106
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
→ Resumes most recently paused task
|
|
26
|
-
→ Picks up exactly where you left off
|
|
107
|
+
Started: {session.startedAt}
|
|
108
|
+
Resumed: {now}
|
|
109
|
+
Session: {session.id}
|
|
27
110
|
```
|
|
28
111
|
|
|
29
|
-
|
|
30
|
-
```
|
|
31
|
-
/p:resume task-1234567890
|
|
32
|
-
→ Resumes task by ID
|
|
33
|
-
```
|
|
112
|
+
## Step 6: Log to Memory
|
|
34
113
|
|
|
35
|
-
|
|
114
|
+
APPEND to: `{memoryPath}`
|
|
115
|
+
|
|
116
|
+
Single line (JSONL):
|
|
117
|
+
```json
|
|
118
|
+
{"timestamp":"{now}","action":"session_resumed","sessionId":"{session.id}","task":"{session.task}","pauseDuration":{pauseDurationSeconds}}
|
|
36
119
|
```
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
120
|
+
|
|
121
|
+
## Output
|
|
122
|
+
|
|
123
|
+
SUCCESS:
|
|
40
124
|
```
|
|
125
|
+
▶️ Resumed: {session.task}
|
|
41
126
|
|
|
42
|
-
|
|
127
|
+
Session: {session.id}
|
|
128
|
+
Was paused: {pauseFormatted}
|
|
129
|
+
Total active: {session.duration} (before this stretch)
|
|
43
130
|
|
|
44
|
-
|
|
131
|
+
/p:done when finished | /p:pause for another break
|
|
45
132
|
```
|
|
46
|
-
⏸️ Paused tasks (3):
|
|
47
133
|
|
|
48
|
-
|
|
49
|
-
Paused 10m ago | Active time: 45m
|
|
134
|
+
## Error Handling
|
|
50
135
|
|
|
51
|
-
|
|
52
|
-
|
|
136
|
+
| Error | Response | Action |
|
|
137
|
+
|-------|----------|--------|
|
|
138
|
+
| No project | "No prjct project" | STOP |
|
|
139
|
+
| No session | "No paused session" | STOP |
|
|
140
|
+
| Already active | Show active state | STOP |
|
|
141
|
+
| Already completed | Suggest /p:now | STOP |
|
|
142
|
+
| Write fails | Log warning | CONTINUE |
|
|
53
143
|
|
|
54
|
-
|
|
55
|
-
Paused yesterday | Active time: 30m
|
|
144
|
+
## Examples
|
|
56
145
|
|
|
57
|
-
|
|
146
|
+
### Example 1: Resume Paused Session
|
|
147
|
+
**Session:**
|
|
148
|
+
```json
|
|
149
|
+
{
|
|
150
|
+
"id": "sess_abc12345",
|
|
151
|
+
"task": "implement auth",
|
|
152
|
+
"status": "paused",
|
|
153
|
+
"pausedAt": "2025-12-07T12:30:00.000Z",
|
|
154
|
+
"duration": 9000,
|
|
155
|
+
"timeline": [
|
|
156
|
+
{"type": "start", "at": "2025-12-07T10:00:00.000Z"},
|
|
157
|
+
{"type": "pause", "at": "2025-12-07T12:30:00.000Z"}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
58
160
|
```
|
|
59
161
|
|
|
60
|
-
|
|
162
|
+
**Current time:** 2:00 PM (paused 1.5h ago)
|
|
61
163
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- "p. back to {task}" → Resume matching task
|
|
66
|
-
- "p. resume 2" → Resume task #2
|
|
164
|
+
**Output:**
|
|
165
|
+
```
|
|
166
|
+
▶️ Resumed: implement auth
|
|
67
167
|
|
|
68
|
-
|
|
168
|
+
Session: sess_abc12345
|
|
169
|
+
Was paused: 1h 30m
|
|
170
|
+
Total active: 2h 30m (before this stretch)
|
|
69
171
|
|
|
70
|
-
|
|
172
|
+
/p:done when finished | /p:pause for another break
|
|
71
173
|
```
|
|
72
|
-
❌ No paused tasks to resume
|
|
73
|
-
|
|
74
|
-
See what's in queue:
|
|
75
|
-
→ /p:next
|
|
76
174
|
|
|
77
|
-
|
|
78
|
-
|
|
175
|
+
### Example 2: Already Active
|
|
176
|
+
**Output:**
|
|
79
177
|
```
|
|
178
|
+
▶️ Already active: implement auth
|
|
80
179
|
|
|
81
|
-
|
|
180
|
+
Session: sess_abc12345
|
|
181
|
+
Working for: 45m
|
|
182
|
+
|
|
183
|
+
/p:done to complete | /p:pause to pause
|
|
82
184
|
```
|
|
83
|
-
❌ Already working on: {current_task}
|
|
84
185
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
→ /p:pause (pause current)
|
|
88
|
-
→ /p:switch {task_id} (atomic switch)
|
|
186
|
+
### Example 3: No Paused Session
|
|
187
|
+
**Output:**
|
|
89
188
|
```
|
|
189
|
+
⚠️ No paused session to resume.
|
|
90
190
|
|
|
91
|
-
|
|
191
|
+
Start a new task:
|
|
192
|
+
• /p:now <task>
|
|
92
193
|
```
|
|
93
|
-
❌ Task {id} not found or not paused
|
|
94
194
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
195
|
+
## Natural Language Support
|
|
196
|
+
|
|
197
|
+
Detect intent for resume:
|
|
198
|
+
- "p. resume" → Resume paused session
|
|
199
|
+
- "p. continue" → Resume paused session
|
|
200
|
+
- "p. back to work" → Resume paused session
|
|
201
|
+
- "p. unpause" → Resume paused session
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
allowed-tools: [Bash]
|
|
3
|
+
description: 'Start prjct web server'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /p:serve - Start Web Server
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
Starts the prjct web interface with Claude Code CLI integration.
|
|
10
|
+
|
|
11
|
+
**CRITICAL**: Uses your Claude subscription via PTY - NO API costs!
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Start with defaults (port 3333)
|
|
17
|
+
prjct-serve
|
|
18
|
+
|
|
19
|
+
# Custom port
|
|
20
|
+
prjct-serve --port=8080
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## What It Does
|
|
24
|
+
|
|
25
|
+
1. **Starts API Server** (Hono)
|
|
26
|
+
- REST endpoints for projects, sessions, tasks
|
|
27
|
+
- WebSocket for Claude Code CLI interaction
|
|
28
|
+
- SSE for real-time updates
|
|
29
|
+
|
|
30
|
+
2. **Starts Web App** (React + Vite)
|
|
31
|
+
- Dashboard with metrics
|
|
32
|
+
- Terminal with xterm.js
|
|
33
|
+
- Session history
|
|
34
|
+
|
|
35
|
+
3. **PTY Manager**
|
|
36
|
+
- Spawns Claude Code CLI in pseudo-terminal
|
|
37
|
+
- Streams I/O via WebSocket
|
|
38
|
+
- Uses YOUR subscription - $0 API costs
|
|
39
|
+
|
|
40
|
+
## Architecture
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
┌─────────────────────────────────────────────────────────┐
|
|
44
|
+
│ Browser (localhost:3000) │
|
|
45
|
+
│ ┌─────────────────────────────────────────────────┐ │
|
|
46
|
+
│ │ React App │ │
|
|
47
|
+
│ │ ├── Dashboard (metrics, projects) │ │
|
|
48
|
+
│ │ ├── Terminal (xterm.js) │ │
|
|
49
|
+
│ │ └── Sessions (history) │ │
|
|
50
|
+
│ └─────────────────────────────────────────────────┘ │
|
|
51
|
+
│ │ │
|
|
52
|
+
│ WebSocket │
|
|
53
|
+
│ │ │
|
|
54
|
+
│ ┌─────────────────────────────────────────────────┐ │
|
|
55
|
+
│ │ Hono Server (localhost:3333) │ │
|
|
56
|
+
│ │ ├── /api/projects │ │
|
|
57
|
+
│ │ ├── /api/sessions │ │
|
|
58
|
+
│ │ ├── /api/claude/sessions │ │
|
|
59
|
+
│ │ └── /ws/claude/:sessionId │ │
|
|
60
|
+
│ └─────────────────────────────────────────────────┘ │
|
|
61
|
+
│ │ │
|
|
62
|
+
│ PTY (node-pty) │
|
|
63
|
+
│ │ │
|
|
64
|
+
│ ┌─────────────────────────────────────────────────┐ │
|
|
65
|
+
│ │ Claude Code CLI │ │
|
|
66
|
+
│ │ (your subscription, no API costs) │ │
|
|
67
|
+
│ └─────────────────────────────────────────────────┘ │
|
|
68
|
+
└─────────────────────────────────────────────────────────┘
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Endpoints
|
|
72
|
+
|
|
73
|
+
### REST API
|
|
74
|
+
|
|
75
|
+
| Endpoint | Method | Description |
|
|
76
|
+
|----------|--------|-------------|
|
|
77
|
+
| `/api/projects` | GET | List all projects |
|
|
78
|
+
| `/api/projects/:id` | GET | Get project details |
|
|
79
|
+
| `/api/projects/:id/status` | GET | Get project status |
|
|
80
|
+
| `/api/sessions` | GET | List sessions |
|
|
81
|
+
| `/api/sessions/current` | GET | Get current session |
|
|
82
|
+
| `/api/sessions` | POST | Create session |
|
|
83
|
+
| `/api/sessions/:id/pause` | POST | Pause session |
|
|
84
|
+
| `/api/sessions/:id/resume` | POST | Resume session |
|
|
85
|
+
| `/api/sessions/:id/complete` | POST | Complete session |
|
|
86
|
+
| `/api/claude/status` | GET | Check Claude CLI availability |
|
|
87
|
+
| `/api/claude/sessions` | GET | List PTY sessions |
|
|
88
|
+
| `/api/claude/sessions` | POST | Create PTY session |
|
|
89
|
+
|
|
90
|
+
### WebSocket
|
|
91
|
+
|
|
92
|
+
| Endpoint | Description |
|
|
93
|
+
|----------|-------------|
|
|
94
|
+
| `/ws/claude/:sessionId` | Real-time Claude CLI interaction |
|
|
95
|
+
|
|
96
|
+
**Messages:**
|
|
97
|
+
- `{ type: 'input', data: string }` - Send input to CLI
|
|
98
|
+
- `{ type: 'resize', cols: number, rows: number }` - Resize terminal
|
|
99
|
+
- `{ type: 'output', data: string }` - Receive CLI output
|
|
100
|
+
|
|
101
|
+
## Requirements
|
|
102
|
+
|
|
103
|
+
- Node.js 18+
|
|
104
|
+
- Claude Code CLI installed (`claude` command available)
|
|
105
|
+
- Active Claude subscription (Max or similar)
|
|
106
|
+
|
|
107
|
+
## Output
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
╔═══════════════════════════════════════════════════════════╗
|
|
111
|
+
║ ║
|
|
112
|
+
║ ⚡ prjct - Developer Momentum ║
|
|
113
|
+
║ ║
|
|
114
|
+
║ API: http://localhost:3333 ║
|
|
115
|
+
║ Web: http://localhost:3000 ║
|
|
116
|
+
║ Claude: ws://localhost:3333/ws/claude ║
|
|
117
|
+
║ ║
|
|
118
|
+
║ Using your Claude subscription - $0 API costs ║
|
|
119
|
+
║ ║
|
|
120
|
+
╚═══════════════════════════════════════════════════════════╝
|
|
121
|
+
```
|
|
@@ -11,6 +11,7 @@ timestamp-rule: 'GetTimestamp() and GetDate() for ALL timestamps'
|
|
|
11
11
|
- `{globalPath}`: `~/.prjct-cli/projects/{projectId}`
|
|
12
12
|
- `{shippedPath}`: `{globalPath}/progress/shipped.md`
|
|
13
13
|
- `{memoryPath}`: `{globalPath}/memory/context.jsonl`
|
|
14
|
+
- `{snapshotDir}`: `{globalPath}/snapshots`
|
|
14
15
|
- `{feature}`: User-provided feature name
|
|
15
16
|
|
|
16
17
|
## Step 1: Read Config
|
|
@@ -187,6 +188,48 @@ Single line (JSONL):
|
|
|
187
188
|
{"timestamp":"{GetTimestamp()}","action":"feature_shipped","feature":"{feature}","version":"{newVersion}"}
|
|
188
189
|
```
|
|
189
190
|
|
|
191
|
+
## Step 11: Create Snapshot (Undo/Redo Support)
|
|
192
|
+
|
|
193
|
+
This creates a snapshot for the undo/redo system.
|
|
194
|
+
|
|
195
|
+
### Initialize Snapshot Directory
|
|
196
|
+
BASH: `mkdir -p {snapshotDir}`
|
|
197
|
+
|
|
198
|
+
### Check if Git Repo Exists
|
|
199
|
+
BASH: `ls {snapshotDir}/.git 2>/dev/null || echo "INIT_NEEDED"`
|
|
200
|
+
|
|
201
|
+
IF output contains "INIT_NEEDED":
|
|
202
|
+
BASH: `cd {snapshotDir} && git init && git config user.email "prjct@local" && git config user.name "prjct-snapshots" && git commit --allow-empty -m "init: snapshot system"`
|
|
203
|
+
|
|
204
|
+
### Copy Changed Files to Snapshot
|
|
205
|
+
BASH: `git diff --name-only HEAD~1 2>/dev/null || git diff --name-only`
|
|
206
|
+
CAPTURE as {changedFiles}
|
|
207
|
+
|
|
208
|
+
For each file in {changedFiles}:
|
|
209
|
+
- Source: `{projectPath}/{file}`
|
|
210
|
+
- Destination: `{snapshotDir}/{file}`
|
|
211
|
+
- Create parent directories if needed
|
|
212
|
+
- Copy file content
|
|
213
|
+
|
|
214
|
+
### Commit Snapshot
|
|
215
|
+
BASH: `cd {snapshotDir} && git add -A && git commit -m "Ship: {feature} (v{newVersion})" 2>/dev/null || echo "NO_CHANGES"`
|
|
216
|
+
|
|
217
|
+
### Get Snapshot Hash
|
|
218
|
+
BASH: `cd {snapshotDir} && git rev-parse --short HEAD`
|
|
219
|
+
CAPTURE as {snapshotHash}
|
|
220
|
+
|
|
221
|
+
### Clear Redo Stack (new snapshot invalidates redo)
|
|
222
|
+
WRITE: `{snapshotDir}/redo-stack.json`
|
|
223
|
+
Content: `[]`
|
|
224
|
+
|
|
225
|
+
### Log Snapshot
|
|
226
|
+
APPEND to: `{snapshotDir}/manifest.jsonl`
|
|
227
|
+
|
|
228
|
+
Single line (JSONL):
|
|
229
|
+
```json
|
|
230
|
+
{"type":"snapshot","hash":"{snapshotHash}","message":"Ship: {feature}","version":"{newVersion}","timestamp":"{GetTimestamp()}"}
|
|
231
|
+
```
|
|
232
|
+
|
|
190
233
|
## Output
|
|
191
234
|
|
|
192
235
|
SUCCESS:
|
|
@@ -197,11 +240,12 @@ Version: {currentVersion} → {newVersion}
|
|
|
197
240
|
Lint: {lintStatus}
|
|
198
241
|
Tests: {testStatus}
|
|
199
242
|
Commit: {commitHash}
|
|
243
|
+
Snapshot: {snapshotHash}
|
|
200
244
|
|
|
201
245
|
Next:
|
|
246
|
+
• /p:undo - Revert this ship if needed
|
|
202
247
|
• /p:feature - Plan next feature
|
|
203
248
|
• /p:recap - See progress
|
|
204
|
-
• compact - Clean up conversation
|
|
205
249
|
```
|
|
206
250
|
|
|
207
251
|
## Error Handling
|
|
@@ -181,7 +181,40 @@ IF exists:
|
|
|
181
181
|
|
|
182
182
|
WRITE: `{globalPath}/CLAUDE.md`
|
|
183
183
|
|
|
184
|
-
## Step 6:
|
|
184
|
+
## Step 6: Update project.json
|
|
185
|
+
|
|
186
|
+
This file is the source of truth for the web dashboard. It maps projectId → repoPath.
|
|
187
|
+
|
|
188
|
+
### Determine Project Name
|
|
189
|
+
- Try package.json → `name` field
|
|
190
|
+
- Try Cargo.toml → `[package] name`
|
|
191
|
+
- Try pyproject.toml → `[project] name`
|
|
192
|
+
- Fallback to directory name (last segment of current path)
|
|
193
|
+
|
|
194
|
+
WRITE: `{globalPath}/project.json`
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"projectId": "{projectId}",
|
|
199
|
+
"repoPath": "{cwd}",
|
|
200
|
+
"name": "{projectName}",
|
|
201
|
+
"techStack": ["{primaryLanguage}", "{primaryFramework}", ...],
|
|
202
|
+
"createdAt": "{existingCreatedAt || GetTimestamp()}",
|
|
203
|
+
"lastSync": "{GetTimestamp()}"
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### techStack Array Rules
|
|
208
|
+
- Max 4 items for display in dashboard cards
|
|
209
|
+
- Order by relevance: primary language → framework → tools
|
|
210
|
+
- Examples:
|
|
211
|
+
- Node.js + React: `["TypeScript", "React", "Node.js", "Vitest"]`
|
|
212
|
+
- Python Django: `["Python", "Django", "PostgreSQL"]`
|
|
213
|
+
- CLI tool: `["Node.js", "CLI", "CommonJS"]`
|
|
214
|
+
|
|
215
|
+
NOTE: If project.json already exists, preserve `createdAt` field. Always update `lastSync` and `techStack`.
|
|
216
|
+
|
|
217
|
+
## Step 7: Log to Memory
|
|
185
218
|
|
|
186
219
|
APPEND to: `{memoryPath}`
|
|
187
220
|
|
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
---
|
|
2
|
-
allowed-tools: [Read, Write, TodoWrite]
|
|
2
|
+
allowed-tools: [Read, Write, TodoWrite, Task, Glob]
|
|
3
3
|
description: 'Break down complex tasks'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /p:task
|
|
7
7
|
|
|
8
|
+
## Agent Delegation (REQUIRED)
|
|
9
|
+
|
|
10
|
+
Before executing task, delegate to specialist agent:
|
|
11
|
+
|
|
12
|
+
1. **List agents**: `Glob("~/.prjct-cli/projects/{projectId}/agents/*.md")`
|
|
13
|
+
2. **Analyze task domain**: Match to agent expertise
|
|
14
|
+
3. **Delegate via Task tool**:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
Task(
|
|
18
|
+
subagent_type: 'general-purpose',
|
|
19
|
+
prompt: '
|
|
20
|
+
## Agent
|
|
21
|
+
Read: ~/.prjct-cli/projects/{projectId}/agents/{agent}.md
|
|
22
|
+
|
|
23
|
+
## Task
|
|
24
|
+
{task description}
|
|
25
|
+
|
|
26
|
+
## Flow
|
|
27
|
+
1. Read agent file
|
|
28
|
+
2. Apply expertise
|
|
29
|
+
3. Execute task
|
|
30
|
+
'
|
|
31
|
+
)
|
|
32
|
+
```
|
|
33
|
+
|
|
8
34
|
## Usage
|
|
9
35
|
|
|
10
36
|
```
|