@prepcli/prepcli 0.1.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/LICENSE +21 -0
- package/README.md +378 -0
- package/bin/prepcli.js +104 -0
- package/package.json +41 -0
- package/src/commands/auth.js +125 -0
- package/src/commands/context.js +151 -0
- package/src/commands/doctor.js +10 -0
- package/src/commands/hook.js +131 -0
- package/src/commands/init.js +175 -0
- package/src/commands/install.js +130 -0
- package/src/commands/log.js +65 -0
- package/src/commands/record.js +141 -0
- package/src/commands/session.js +44 -0
- package/src/commands/stats.js +10 -0
- package/src/commands/team.js +21 -0
- package/src/commands/uninstall.js +105 -0
- package/src/lib/api.js +38 -0
- package/src/lib/config.js +145 -0
- package/src/lib/decision.js +61 -0
- package/src/lib/detect.js +194 -0
- package/src/lib/git.js +200 -0
- package/src/lib/session-file.js +48 -0
- package/src/lib/targets/antigravity.js +14 -0
- package/src/lib/targets/claude.js +22 -0
- package/src/lib/targets/cursor.js +14 -0
- package/src/lib/targets/windsurf.js +14 -0
- package/workflows/debug.md +156 -0
- package/workflows/plan.md +156 -0
- package/workflows/prep.md +150 -0
- package/workflows/prepcli.md +154 -0
- package/workflows/refactor.md +154 -0
- package/workflows/review.md +156 -0
- package/workflows/write.md +154 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bhavik Devganiya
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
# prepcli
|
|
2
|
+
|
|
3
|
+
Persistent AI collaboration layer — structured prompts, project context, and decision records for Claude, Cursor, Windsurf, and more.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
Most AI coding sessions start cold. The AI asks what your stack is. It suggests something you ruled out last week. It doesn't know about the deployment freeze. You spend the first 10 messages re-explaining context that hasn't changed.
|
|
10
|
+
|
|
11
|
+
prepcli fixes this in three layers:
|
|
12
|
+
|
|
13
|
+
**Layer 1 — Structured prompts.**
|
|
14
|
+
Six workflow slash commands (`/debug`, `/plan`, `/prep`, etc.) that ask targeted questions before the AI starts working. Better questions → better output on the first attempt → less back-and-forth.
|
|
15
|
+
|
|
16
|
+
**Layer 2 — Project context.**
|
|
17
|
+
`prepcli init` scans your codebase, stores your stack and constraints in the cloud, and silently injects them at the start of every AI session. The AI already knows your stack, your hard limits, and what was decided last week — without you saying a word.
|
|
18
|
+
|
|
19
|
+
**Layer 3 — Decision records.**
|
|
20
|
+
Every AI session gets recorded as a structured Markdown document: what was done, why, what was ruled out, linked to the git commit. Records live in a hidden git branch that travels with every clone. No account needed to read history. Works offline.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick start
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g prepcli
|
|
28
|
+
prepcli install # copy workflow files to your AI tool
|
|
29
|
+
prepcli auth login # create free account (optional — enables cloud features)
|
|
30
|
+
prepcli init # scan project, push context, set up shadow branch
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Open your AI tool and type `/debug`, `/plan`, or any workflow command.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Workflow commands
|
|
38
|
+
|
|
39
|
+
| Command | What it does |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `/prep` | Universal session starter — ask targeted questions, build a structured prompt, execute on approval |
|
|
42
|
+
| `/debug` | Turn a vague bug report into a precise debugging prompt |
|
|
43
|
+
| `/plan` | Gather product and technical constraints, build a planning prompt |
|
|
44
|
+
| `/refactor` | Gather constraints for a safe refactor |
|
|
45
|
+
| `/review` | Gather review intent and constraints, build a focused code review |
|
|
46
|
+
| `/write` | Gather audience and constraints, build a precise writing prompt |
|
|
47
|
+
|
|
48
|
+
Each workflow follows the same structure:
|
|
49
|
+
- **STEP 0** — silently reads project context before asking anything
|
|
50
|
+
- **STEP 1–4** — asks one question at a time to fill critical gaps
|
|
51
|
+
- **STEP 5** — builds and shows a structured prompt, executes on your approval
|
|
52
|
+
- **FINAL STEP** — silently records what was done to the local session file
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Project context
|
|
57
|
+
|
|
58
|
+
Run once per project:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
cd your-project
|
|
62
|
+
prepcli init
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
prepcli scans your codebase (reads `package.json`, lock files, config files, git remote) and asks three questions:
|
|
66
|
+
|
|
67
|
+
1. **Hard limits** — things AI must never do (`never add console.log to production`)
|
|
68
|
+
2. **Active constraints** — things that are true right now (`auth module is frozen until Dec 15`)
|
|
69
|
+
3. **Conventions** — patterns AI would get wrong (`use AppError class, never throw raw strings`)
|
|
70
|
+
|
|
71
|
+
This context is pushed to the cloud and injected silently at the start of every AI session via STEP 0. The AI knows your stack, your limits, and your conventions without you repeating them.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
prepcli context # show current context
|
|
75
|
+
prepcli context --preview # show exactly what STEP 0 injects
|
|
76
|
+
prepcli context --edit # open in $EDITOR and push changes
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Stack detection covers: language, runtime, framework, database, auth, testing, API layer, styling, monorepo, i18n, CI, hosting, package manager.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Decision records
|
|
84
|
+
|
|
85
|
+
After every AI session, `prepcli` records what was done, why, and what was ruled out — linked to the git commit it produced.
|
|
86
|
+
|
|
87
|
+
### How recording works
|
|
88
|
+
|
|
89
|
+
During a session, the AI silently runs after each task:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
prepcli session add \
|
|
93
|
+
--workflow=debug \
|
|
94
|
+
--what="replaced date-fns with custom UTC offset handler" \
|
|
95
|
+
--why="date-fns fails silently on UTC+5:30 half-hour offsets"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This writes to a local `.prepcli-session` file — no network, no auth, works offline.
|
|
99
|
+
|
|
100
|
+
When you run `git push`, a pre-push hook fires:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
[prepcli] 2 AI turns this session:
|
|
104
|
+
[debug] identified date-fns as root cause
|
|
105
|
+
[debug] replaced with custom UTC offset handler
|
|
106
|
+
|
|
107
|
+
Final summary? (Enter to skip): _
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Type a one-line summary and press Enter. The push is never blocked — Enter skips recording entirely.
|
|
111
|
+
|
|
112
|
+
### Where records live
|
|
113
|
+
|
|
114
|
+
Records are stored in two places:
|
|
115
|
+
|
|
116
|
+
| | Shadow Branch | Database |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| **Content** | Full Markdown — all turns, alternatives, constraints | Lean JSON — summary, key files, turn count |
|
|
119
|
+
| **Needs account** | No | Yes |
|
|
120
|
+
| **Works offline** | Yes | No |
|
|
121
|
+
| **Travels with clone** | Yes | No |
|
|
122
|
+
| **AI reads at STEP 0** | No | Yes — feeds `recent_decisions` |
|
|
123
|
+
|
|
124
|
+
The shadow branch (`prepcli/shadow/v1`) is an orphan git branch — completely separate from your code history. It travels with every `git clone` and every `git fetch`.
|
|
125
|
+
|
|
126
|
+
### Reading records
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
prepcli log # last 10 decisions
|
|
130
|
+
prepcli log --workflow debug # debug sessions only
|
|
131
|
+
prepcli log --file src/auth.js # decisions touching this file
|
|
132
|
+
prepcli log --commit abc123 # specific commit
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Or directly with git — no prepcli needed:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
git show prepcli/shadow/v1:20260524-dec-a3f9c2b1.md
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### How decisions get recorded
|
|
142
|
+
|
|
143
|
+
There are two ways a decision lands in `prepcli log` — by the AI automatically, or by you manually.
|
|
144
|
+
|
|
145
|
+
**Recorded by AI (automatic)**
|
|
146
|
+
|
|
147
|
+
After every AI task, the workflow silently runs:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
prepcli session add \
|
|
151
|
+
--workflow=debug \
|
|
152
|
+
--what="replaced date-fns with custom UTC offset handler" \
|
|
153
|
+
--why="date-fns fails silently on UTC+5:30 half-hour offsets"
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Turns accumulate locally in `.prepcli-session`. When you run `git push`, the pre-push hook fires:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
[prepcli] 2 AI turns this session:
|
|
160
|
+
[debug] identified date-fns as root cause
|
|
161
|
+
[debug] replaced with custom UTC offset handler
|
|
162
|
+
|
|
163
|
+
Final summary? (Enter to skip): rebuilt calendar with custom timezone handling
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Type a one-line summary and press Enter. One decision record is written to the shadow branch covering the full session.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
**Recorded manually**
|
|
171
|
+
|
|
172
|
+
You don't have to wait for an AI session or a push. If you discover something — a production bug, an architectural decision made in a meeting, a constraint found in docs — record it immediately.
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
prepcli record
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
[prepcli] Recording decision
|
|
180
|
+
|
|
181
|
+
What did you decide or discover?
|
|
182
|
+
> switched Upstash to paid tier after finding silent rate limiting in prod
|
|
183
|
+
|
|
184
|
+
Why?
|
|
185
|
+
> free tier drops requests above 100/min silently, no error returned
|
|
186
|
+
|
|
187
|
+
What was ruled out? (Enter to skip)
|
|
188
|
+
> self-hosted Redis — too much infra overhead at current scale
|
|
189
|
+
|
|
190
|
+
Workflow? [manual/debug/plan/discovery] (Enter for manual)
|
|
191
|
+
> discovery
|
|
192
|
+
|
|
193
|
+
Writing to shadow branch... done.
|
|
194
|
+
✓ Decision recorded (dec-3f9a1b2c)
|
|
195
|
+
View: prepcli log
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Inline mode** — no prompts:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
prepcli record \
|
|
202
|
+
--what="switched Upstash to paid tier" \
|
|
203
|
+
--why="free tier silently drops requests above 100/min" \
|
|
204
|
+
--ruled-out="self-hosted Redis, Upstash Pro alternative plan" \
|
|
205
|
+
--workflow=discovery
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Manual records are marked `ai_turn_count: 0` so you can distinguish them from AI session records in `prepcli log`. Records are written directly to the shadow branch — no push needed.
|
|
209
|
+
|
|
210
|
+
### Accessing records on a fresh clone
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
git clone https://github.com/your/repo
|
|
214
|
+
git fetch origin prepcli/shadow/v1:prepcli/shadow/v1
|
|
215
|
+
prepcli log # full decision history available immediately
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
No account required. The history is pure git objects.
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Installation options
|
|
223
|
+
|
|
224
|
+
**Temporary (no global install):**
|
|
225
|
+
```bash
|
|
226
|
+
npx prepcli install
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Permanent global install:**
|
|
230
|
+
```bash
|
|
231
|
+
npm install -g prepcli
|
|
232
|
+
prepcli install
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
When prompted, choose where to install:
|
|
236
|
+
- **Claude Code** — personal (`~/.claude/commands`) or project (`.claude/commands`)
|
|
237
|
+
- **Cursor** — `.cursor/prompts`
|
|
238
|
+
- **Windsurf** — `.windsurf`
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## Auth
|
|
243
|
+
|
|
244
|
+
Login is via email OTP — no password required:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
prepcli auth login # sends a one-time code to your email
|
|
248
|
+
prepcli auth status # show current session and expiry
|
|
249
|
+
prepcli auth logout # invalidate session
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Auth is optional. Without it:
|
|
253
|
+
- Workflow commands work fully
|
|
254
|
+
- `prepcli init` saves context locally in `.prepclirc`
|
|
255
|
+
- Session recording writes to the shadow branch locally
|
|
256
|
+
- Cloud sync and `recent_decisions` injection are disabled
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Commands reference
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
prepcli install # copy workflow files to AI tool directories
|
|
264
|
+
prepcli uninstall # remove workflow files
|
|
265
|
+
|
|
266
|
+
prepcli auth login # sign in with email OTP
|
|
267
|
+
prepcli auth logout # sign out
|
|
268
|
+
prepcli auth status # show current session
|
|
269
|
+
|
|
270
|
+
prepcli init # scan project, push context, set up shadow branch
|
|
271
|
+
prepcli context # show current project context
|
|
272
|
+
prepcli context --preview # show what STEP 0 injects
|
|
273
|
+
prepcli context --edit # edit and push context
|
|
274
|
+
|
|
275
|
+
prepcli session add # add a turn to the local session file (used by AI)
|
|
276
|
+
prepcli session show # inspect the current session
|
|
277
|
+
prepcli session clear # clear the session file
|
|
278
|
+
|
|
279
|
+
prepcli log # browse decision records
|
|
280
|
+
prepcli log --workflow <type> # filter by workflow
|
|
281
|
+
prepcli log --file <path> # filter by file
|
|
282
|
+
prepcli log --commit <hash> # show decision for a specific commit
|
|
283
|
+
|
|
284
|
+
prepcli record # manually save a decision (interactive)
|
|
285
|
+
prepcli record --what "..." --why "..." --ruled-out "..." --workflow manual
|
|
286
|
+
prepcli stats # show prompt quality scores and delta trends
|
|
287
|
+
prepcli doctor # diagnose setup issues
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Files created in your project
|
|
293
|
+
|
|
294
|
+
| File | What it is | Safe to commit |
|
|
295
|
+
|---|---|---|
|
|
296
|
+
| `.prepclirc` | Project ID + git remote | Yes |
|
|
297
|
+
| `.git/hooks/pre-push` | Hook installed by `prepcli init` | N/A (in .git) |
|
|
298
|
+
| `.prepcli-session` | Local session accumulator | No (in .gitignore) |
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Requirements
|
|
303
|
+
|
|
304
|
+
- Node.js >= 18
|
|
305
|
+
- Git
|
|
306
|
+
- Claude Code, Cursor, or Windsurf
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Self-hosting
|
|
311
|
+
|
|
312
|
+
Run your own backend instead of using `api.prepcli.in`:
|
|
313
|
+
|
|
314
|
+
1. Create a [Supabase](https://supabase.com) project
|
|
315
|
+
2. Run `schema.sql` in the Supabase SQL editor
|
|
316
|
+
3. Deploy `worker/` to [Cloudflare Workers](https://workers.cloudflare.com)
|
|
317
|
+
4. Set Cloudflare secrets:
|
|
318
|
+
```bash
|
|
319
|
+
wrangler secret put SUPABASE_URL
|
|
320
|
+
wrangler secret put SUPABASE_ANON_KEY
|
|
321
|
+
```
|
|
322
|
+
5. Point the CLI at your worker:
|
|
323
|
+
```bash
|
|
324
|
+
PREPCLI_API_URL=https://your-worker.workers.dev prepcli init
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Codebase structure
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
bin/
|
|
333
|
+
prepcli.js CLI entry point
|
|
334
|
+
|
|
335
|
+
src/
|
|
336
|
+
commands/
|
|
337
|
+
auth.js login / logout / status
|
|
338
|
+
init.js project setup
|
|
339
|
+
context.js read and edit project context
|
|
340
|
+
session.js local session accumulator
|
|
341
|
+
hook.js pre-push hook handler
|
|
342
|
+
log.js browse decision records
|
|
343
|
+
record.js manual decision entry
|
|
344
|
+
install.js workflow file installer
|
|
345
|
+
stats.js quality scores (Phase 4)
|
|
346
|
+
team.js team management (Phase 6)
|
|
347
|
+
doctor.js setup diagnostics (Phase 6)
|
|
348
|
+
|
|
349
|
+
lib/
|
|
350
|
+
api.js HTTP client → api.prepcli.in
|
|
351
|
+
config.js auth token + .prepclirc helpers
|
|
352
|
+
detect.js stack auto-detection
|
|
353
|
+
git.js shadow branch plumbing
|
|
354
|
+
session-file.js .prepcli-session read/write
|
|
355
|
+
decision.js Markdown record builder
|
|
356
|
+
targets/ AI tool detection (Claude, Cursor, Windsurf)
|
|
357
|
+
|
|
358
|
+
workflows/
|
|
359
|
+
prep.md /prep workflow
|
|
360
|
+
debug.md /debug workflow
|
|
361
|
+
plan.md /plan workflow
|
|
362
|
+
refactor.md /refactor workflow
|
|
363
|
+
review.md /review workflow
|
|
364
|
+
write.md /write workflow
|
|
365
|
+
|
|
366
|
+
worker/
|
|
367
|
+
src/index.js Cloudflare Worker (API layer)
|
|
368
|
+
|
|
369
|
+
schema.sql Supabase schema + RLS policies
|
|
370
|
+
docs/
|
|
371
|
+
design.md Visual design reference
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## License
|
|
377
|
+
|
|
378
|
+
MIT
|
package/bin/prepcli.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const { program } = require("commander");
|
|
5
|
+
|
|
6
|
+
program
|
|
7
|
+
.name("prepcli")
|
|
8
|
+
.description("Persistent AI collaboration layer — context, decisions, and self-improving prompts")
|
|
9
|
+
.version("0.1.0");
|
|
10
|
+
|
|
11
|
+
// ── Auth ──────────────────────────────────────────────────────────────────────
|
|
12
|
+
program
|
|
13
|
+
.command("auth <action>")
|
|
14
|
+
.description("login | logout | status")
|
|
15
|
+
.action((action) => require("../src/commands/auth").run(action));
|
|
16
|
+
|
|
17
|
+
// ── Init ──────────────────────────────────────────────────────────────────────
|
|
18
|
+
program
|
|
19
|
+
.command("init")
|
|
20
|
+
.description("Scan codebase, create .prepclirc, push initial context to cloud")
|
|
21
|
+
.action(() => require("../src/commands/init").run());
|
|
22
|
+
|
|
23
|
+
// ── Install ───────────────────────────────────────────────────────────────────
|
|
24
|
+
program
|
|
25
|
+
.command("install")
|
|
26
|
+
.description("Copy workflow files to AI tool directories")
|
|
27
|
+
.option("--all", "Install to all detected tools")
|
|
28
|
+
.option("--tool <ids>", "Comma-separated tool ids (claude-project, cursor, windsurf…)")
|
|
29
|
+
.option("--yes, -y", "Skip confirmation prompt")
|
|
30
|
+
.action((opts) => require("../src/commands/install").run(opts));
|
|
31
|
+
|
|
32
|
+
// ── Uninstall ─────────────────────────────────────────────────────────────────
|
|
33
|
+
program
|
|
34
|
+
.command("uninstall")
|
|
35
|
+
.description("Remove workflow files from AI tool directories")
|
|
36
|
+
.option("--all", "Remove from all locations without prompting")
|
|
37
|
+
.option("--yes, -y", "Skip confirmation prompt")
|
|
38
|
+
.action((opts) => require("../src/commands/uninstall").run(opts));
|
|
39
|
+
|
|
40
|
+
// ── Context ───────────────────────────────────────────────────────────────────
|
|
41
|
+
program
|
|
42
|
+
.command("context")
|
|
43
|
+
.description("Show current project context from cloud")
|
|
44
|
+
.option("--preview", "Show exactly what STEP 0 would inject")
|
|
45
|
+
.option("--edit", "Open context in editor")
|
|
46
|
+
.action((opts) => require("../src/commands/context").run(opts));
|
|
47
|
+
|
|
48
|
+
// ── Session (AI calls this silently) ─────────────────────────────────────────
|
|
49
|
+
program
|
|
50
|
+
.command("session <action>")
|
|
51
|
+
.description("add | show | clear — manage the local AI session accumulator")
|
|
52
|
+
.option("--workflow <type>", "Workflow type (debug, plan, review, prep, refactor, write)")
|
|
53
|
+
.option("--what <text>", "One sentence: what was done")
|
|
54
|
+
.option("--why <text>", "One sentence: why this approach")
|
|
55
|
+
.action((action, opts) => require("../src/commands/session").run(action, opts));
|
|
56
|
+
|
|
57
|
+
// ── Internal git hook handler ─────────────────────────────────────────────────
|
|
58
|
+
program
|
|
59
|
+
.command("_hook <name>", { hidden: true })
|
|
60
|
+
.description("Internal: called by git hooks installed by prepcli init")
|
|
61
|
+
.action((name) => require("../src/commands/hook").run(name));
|
|
62
|
+
|
|
63
|
+
// ── Decision log ──────────────────────────────────────────────────────────────
|
|
64
|
+
program
|
|
65
|
+
.command("log")
|
|
66
|
+
.description("Browse AI decision records linked to commits")
|
|
67
|
+
.option("--workflow <type>", "Filter by workflow type (debug, plan, review…)")
|
|
68
|
+
.option("--file <path>", "Filter by file path")
|
|
69
|
+
.option("--commit <hash>", "Show decision for a specific commit")
|
|
70
|
+
.option("--last <period>", "Filter by time period (e.g. 30d)")
|
|
71
|
+
.action((opts) => require("../src/commands/log").run(opts));
|
|
72
|
+
|
|
73
|
+
// ── Record ────────────────────────────────────────────────────────────────────
|
|
74
|
+
program
|
|
75
|
+
.command("record")
|
|
76
|
+
.description("Manually save a decision to the shadow branch")
|
|
77
|
+
.option("--what <text>", "What was decided or discovered")
|
|
78
|
+
.option("--why <text>", "Why this approach over alternatives")
|
|
79
|
+
.option("--ruled-out <text>", "What was considered and rejected (comma-separated)")
|
|
80
|
+
.option("--workflow <type>", "Workflow type (manual, debug, plan, discovery)")
|
|
81
|
+
.action((opts) => require("../src/commands/record").run(opts));
|
|
82
|
+
|
|
83
|
+
// ── Stats ─────────────────────────────────────────────────────────────────────
|
|
84
|
+
program
|
|
85
|
+
.command("stats")
|
|
86
|
+
.description("Show prompt quality scores and delta trends")
|
|
87
|
+
.option("--workflow <type>", "Filter by workflow type")
|
|
88
|
+
.option("--last <period>", "Filter by time period (e.g. 30d)")
|
|
89
|
+
.option("--compare <period>", "Compare to an earlier period")
|
|
90
|
+
.action((opts) => require("../src/commands/stats").run(opts));
|
|
91
|
+
|
|
92
|
+
// ── Team ──────────────────────────────────────────────────────────────────────
|
|
93
|
+
program
|
|
94
|
+
.command("team <action> [email]")
|
|
95
|
+
.description("invite | list | remove")
|
|
96
|
+
.action((action, email) => require("../src/commands/team").run(action, email));
|
|
97
|
+
|
|
98
|
+
// ── Doctor ────────────────────────────────────────────────────────────────────
|
|
99
|
+
program
|
|
100
|
+
.command("doctor")
|
|
101
|
+
.description("Diagnose setup issues (auth, .prepclirc, git hooks, push refspec)")
|
|
102
|
+
.action(() => require("../src/commands/doctor").run());
|
|
103
|
+
|
|
104
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@prepcli/prepcli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Persistent AI collaboration layer — context, decisions, and self-improving prompts",
|
|
5
|
+
"bin": {
|
|
6
|
+
"prepcli": "./bin/prepcli.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"src",
|
|
11
|
+
"workflows",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "node --test src/tests/**/*.test.js"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"commander": "^12.0.0",
|
|
19
|
+
"dotenv": "^17.4.2"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"ai",
|
|
23
|
+
"cli",
|
|
24
|
+
"claude",
|
|
25
|
+
"cursor",
|
|
26
|
+
"prompt",
|
|
27
|
+
"context",
|
|
28
|
+
"developer-tools",
|
|
29
|
+
"llm",
|
|
30
|
+
"workflow"
|
|
31
|
+
],
|
|
32
|
+
"author": "Bhavik Devganiya",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/bhavviik/prepcli.git"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const readline = require("node:readline/promises");
|
|
4
|
+
const api = require("../lib/api");
|
|
5
|
+
const { writeConfig, deleteConfig, readConfig } = require("../lib/config");
|
|
6
|
+
|
|
7
|
+
// ── Login ─────────────────────────────────────────────────────────────────────
|
|
8
|
+
async function login() {
|
|
9
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const email = (await rl.question("Email: ")).trim();
|
|
13
|
+
|
|
14
|
+
if (!email || !email.includes("@")) {
|
|
15
|
+
console.error("Enter a valid email address.");
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
await api.post("/auth/otp", { email });
|
|
21
|
+
} catch (err) {
|
|
22
|
+
console.error("Failed to send code:", err.message);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log("\nCode sent to " + email);
|
|
27
|
+
console.log("Check your email and enter the code below.\n");
|
|
28
|
+
|
|
29
|
+
const code = (await rl.question("Enter code: ")).trim();
|
|
30
|
+
|
|
31
|
+
if (!code || !/^\d+$/.test(code)) {
|
|
32
|
+
console.error("Invalid code.");
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let data;
|
|
37
|
+
try {
|
|
38
|
+
data = await api.post("/auth/verify", { email, token: code });
|
|
39
|
+
} catch {
|
|
40
|
+
console.error("Invalid or expired code. Run: prepcli auth login");
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
writeConfig({
|
|
45
|
+
access_token: data.access_token,
|
|
46
|
+
refresh_token: data.refresh_token,
|
|
47
|
+
user_id: data.user_id,
|
|
48
|
+
email: data.email,
|
|
49
|
+
expires_at: data.expires_at,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
console.log("\nLogged in as " + data.email);
|
|
53
|
+
console.log("Run `prepcli init` inside your project to set it up.");
|
|
54
|
+
|
|
55
|
+
} finally {
|
|
56
|
+
rl.close();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ── Logout ────────────────────────────────────────────────────────────────────
|
|
61
|
+
async function logout() {
|
|
62
|
+
const cfg = readConfig();
|
|
63
|
+
|
|
64
|
+
if (!cfg) {
|
|
65
|
+
console.log("Already logged out.");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
await api.post("/auth/logout", {}, cfg.access_token);
|
|
71
|
+
} catch {
|
|
72
|
+
// Local cleanup is what matters
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
deleteConfig();
|
|
76
|
+
console.log("Logged out.");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ── Status ────────────────────────────────────────────────────────────────────
|
|
80
|
+
async function status() {
|
|
81
|
+
const { refreshIfNeeded } = require("../lib/config");
|
|
82
|
+
let cfg = readConfig();
|
|
83
|
+
|
|
84
|
+
if (!cfg || !cfg.access_token) {
|
|
85
|
+
console.log("Not logged in.");
|
|
86
|
+
console.log("Run: prepcli auth login");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const now = Math.floor(Date.now() / 1000);
|
|
91
|
+
const ttl = (cfg.expires_at || 0) - now;
|
|
92
|
+
|
|
93
|
+
if (ttl <= 300) {
|
|
94
|
+
const refreshed = await refreshIfNeeded();
|
|
95
|
+
if (refreshed) cfg = refreshed;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const expired = cfg.expires_at && now >= cfg.expires_at;
|
|
99
|
+
const expiresStr = cfg.expires_at
|
|
100
|
+
? new Date(cfg.expires_at * 1000).toLocaleString()
|
|
101
|
+
: "unknown";
|
|
102
|
+
|
|
103
|
+
const tokenStatus = expired
|
|
104
|
+
? "EXPIRED — run: prepcli auth login"
|
|
105
|
+
: "valid until " + expiresStr;
|
|
106
|
+
|
|
107
|
+
console.log("Logged in as: " + cfg.email);
|
|
108
|
+
console.log("User ID: " + cfg.user_id);
|
|
109
|
+
console.log("Token: " + tokenStatus);
|
|
110
|
+
console.log("Auto-refresh: enabled");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── Router ────────────────────────────────────────────────────────────────────
|
|
114
|
+
async function run(action) {
|
|
115
|
+
switch (action) {
|
|
116
|
+
case "login": await login(); break;
|
|
117
|
+
case "logout": await logout(); break;
|
|
118
|
+
case "status": await status(); break;
|
|
119
|
+
default:
|
|
120
|
+
console.error("Unknown auth action: \"" + action + "\". Use: login | logout | status");
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
module.exports = { run };
|