codebase-ai 0.3.3 → 0.3.4
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 +82 -222
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/logo.svg" alt="codebase" width="800"/>
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
5
|
<p align="center">
|
|
4
6
|
<img src="https://img.shields.io/npm/v/codebase-ai" alt="npm version" />
|
|
@@ -9,176 +11,101 @@
|
|
|
9
11
|
<a href="https://securityscorecards.dev/viewer/?uri=github.com/ZySec-AI/codebase"><img src="https://api.securityscorecards.dev/projects/github.com/ZySec-AI/codebase/badge" alt="OpenSSF Scorecard" /></a>
|
|
10
12
|
</p>
|
|
11
13
|
|
|
12
|
-
<p align="center">
|
|
13
|
-
<b>One command. Your AI understands your project, finds bugs, fixes them, and ships.</b>
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
14
|
---
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Imagine hiring an engineer who reads your entire project in seconds and works through your bug list on demand. That's what `codebase` does — it gives AI the context and the tools to work *on* your project, not just *for* you.
|
|
21
|
-
|
|
22
|
-
**Without codebase:** Every time you open Claude Code, it starts from zero. You re-explain your project, paste in files, describe what's broken. You're the coordinator. Claude is the cursor.
|
|
23
|
-
|
|
24
|
-
**With codebase:** Claude reads a single compact file that captures everything about your project — your stack, your commands, your open issues. It knows where things are. It knows what needs doing. It can act.
|
|
25
|
-
|
|
26
|
-
**Two things happen:**
|
|
27
|
-
|
|
28
|
-
**1 — Claude gets permanent memory of your project**
|
|
29
|
-
One command scans your project and writes a small snapshot file (`.codebase.json`). Claude reads this automatically on every session via `CLAUDE.md`. You never re-explain your project again.
|
|
30
|
-
|
|
31
|
-
**2 — AI gets the ability to act**
|
|
32
|
-
Seven slash commands give AI a complete workflow: simulate real users in a browser, work through your bug backlog, run tests, commit fixes, and ship releases. Not prompts — real, repeatable actions.
|
|
16
|
+
> **~95% fewer tokens.** Claude reads one 500-token snapshot instead of exploring thousands of files. Instant context, every session.
|
|
33
17
|
|
|
34
18
|
---
|
|
35
19
|
|
|
36
|
-
##
|
|
37
|
-
|
|
38
|
-
Once set up, your entire development loop is:
|
|
20
|
+
## Install
|
|
39
21
|
|
|
40
|
-
```
|
|
41
|
-
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g codebase-ai
|
|
42
24
|
```
|
|
43
25
|
|
|
44
|
-
|
|
26
|
+
Then in your project:
|
|
45
27
|
|
|
28
|
+
```bash
|
|
29
|
+
npx codebase-ai
|
|
46
30
|
```
|
|
47
|
-
/vibeloop
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Here's what each step does:
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
### `/simulate` — AI becomes your user
|
|
55
|
-
|
|
56
|
-
Claude opens your app in a real browser (agent-browser) and acts like a real customer. It tries to sign up, log in, complete purchases, hit edge cases. When something breaks or feels wrong, it:
|
|
57
31
|
|
|
58
|
-
|
|
59
|
-
2. Commits the fix with a proper message
|
|
60
|
-
3. Opens a GitHub Issue if the bug is too complex to fix inline
|
|
61
|
-
4. Records UX problems (confusing copy, broken flows, accessibility issues) as issues
|
|
32
|
+
That's it. Every Claude session now starts with instant project context.
|
|
62
33
|
|
|
63
|
-
|
|
34
|
+
> Requires Node.js 20+. For the autonomous loop, also install [Claude Code](https://www.npmjs.com/package/@anthropic-ai/claude-code) and run `gh auth login`.
|
|
64
35
|
|
|
65
36
|
---
|
|
66
37
|
|
|
67
|
-
|
|
38
|
+
## What it does
|
|
68
39
|
|
|
69
|
-
|
|
40
|
+
`codebase` is a vibecoding loop built around three ideas:
|
|
70
41
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
4. Runs your test suite
|
|
75
|
-
5. Commits if tests pass — or opens a new issue if it gets stuck
|
|
76
|
-
6. Closes the original issue with a summary of what was done
|
|
77
|
-
7. Moves to the next issue
|
|
78
|
-
8. Repeats until the backlog is clear or you stop it
|
|
42
|
+
- **Codebase = brain.** One scan writes a compact snapshot (`.codebase.json`) — your stack, commands, open issues, recent decisions. AI reads this instead of exploring files. ~95% fewer tokens, instant context.
|
|
43
|
+
- **GitHub = memory.** Issues, PRs, and labels are the persistent state. The loop can restart anytime and pick up where it left off.
|
|
44
|
+
- **Claude = execution.** Slash commands give AI a complete workflow: simulate real users, fix bugs, run tests, commit, ship.
|
|
79
45
|
|
|
80
|
-
|
|
46
|
+
Multiple developers can jump into the same loop. Commit `.codebase.json` and `.claude/commands/` — everyone gets the same context and commands.
|
|
81
47
|
|
|
82
48
|
---
|
|
83
49
|
|
|
84
|
-
|
|
50
|
+
## The loop
|
|
85
51
|
|
|
86
|
-
|
|
52
|
+
<p align="center">
|
|
53
|
+
<img src="assets/loop.svg" alt="codebase loop animation" width="800"/>
|
|
54
|
+
</p>
|
|
87
55
|
|
|
88
|
-
|
|
89
|
-
|------|---------------|
|
|
90
|
-
| **Bugs** | No open critical or high severity issues |
|
|
91
|
-
| **Tests** | Your full test suite passes |
|
|
92
|
-
| **UX score** | World-class score ≥ 7.0 (from `/simulate` cycles) |
|
|
93
|
-
| **Branch** | No uncommitted changes, branch is clean |
|
|
56
|
+
Or run the entire loop hands-free with one command:
|
|
94
57
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- Merges `develop → main` with a proper merge commit
|
|
99
|
-
- Creates a GitHub Release with auto-generated release notes
|
|
100
|
-
- Rotates the milestone
|
|
58
|
+
```
|
|
59
|
+
/vibeloop
|
|
60
|
+
```
|
|
101
61
|
|
|
102
|
-
|
|
62
|
+
| Command | What it does |
|
|
63
|
+
|---------|-------------|
|
|
64
|
+
| `/simulate` | Opens your app in a real browser. Acts like real users. Fixes bugs inline, tracks complex ones as GitHub Issues. |
|
|
65
|
+
| `/build` | Reads open issues, picks the highest priority, implements the fix, tests it, commits, closes the issue. Repeats. |
|
|
66
|
+
| `/launch` | Checks quality gates (open bugs, test suite, UX score). If all pass: bumps version, tags release, merges to main, publishes GitHub Release. |
|
|
67
|
+
| `/vibeloop` | **Runs everything.** Continuous `/simulate → /build → /launch` loop. Zero intervention. |
|
|
68
|
+
|
|
69
|
+
First time? Run `/setup` in Claude Code to create `docs/PRODUCT.md` and your first milestone.
|
|
103
70
|
|
|
104
71
|
---
|
|
105
72
|
|
|
106
73
|
## Quick start
|
|
107
74
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
Only requires Node.js 20+.
|
|
75
|
+
**Level 1 — Give Claude memory of your project** (Node.js only)
|
|
111
76
|
|
|
112
77
|
```bash
|
|
113
78
|
cd your-project
|
|
114
79
|
npx codebase-ai
|
|
115
80
|
```
|
|
116
81
|
|
|
117
|
-
|
|
118
|
-
- Writes `.codebase.json` — a compact snapshot of your stack, commands, and structure
|
|
119
|
-
- Injects smart instructions into `CLAUDE.md`
|
|
120
|
-
- Configures the MCP server so Claude can query project context natively
|
|
121
|
-
- Installs git hooks so the manifest stays fresh on every commit
|
|
122
|
-
- Updates `.gitignore`
|
|
82
|
+
Scans your project and wires everything: `.codebase.json`, `CLAUDE.md`, MCP server, git hooks, `.gitignore`.
|
|
123
83
|
|
|
124
|
-
|
|
84
|
+
**Level 2 — Autonomous dev loop**
|
|
125
85
|
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
### Level 2 — Autonomous dev loop
|
|
129
|
-
|
|
130
|
-
> **Requires:** Claude Code (`npm install -g @anthropic-ai/claude-code`) and GitHub CLI (`gh auth login`)
|
|
131
|
-
|
|
132
|
-
Open Claude Code in your project and run `/setup` — this creates `docs/PRODUCT.md` and sets up your first GitHub milestone.
|
|
133
|
-
|
|
134
|
-
Then run the loop:
|
|
135
86
|
```bash
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
/launch # ship the release
|
|
87
|
+
npm install -g @anthropic-ai/claude-code
|
|
88
|
+
gh auth login
|
|
139
89
|
```
|
|
140
90
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
## Why does Claude actually understand my project?
|
|
144
|
-
|
|
145
|
-
Without codebase, Claude starts every session knowing nothing:
|
|
91
|
+
Open Claude Code in your project, then:
|
|
146
92
|
|
|
147
93
|
```
|
|
148
|
-
|
|
149
|
-
|
|
94
|
+
/setup ← run once
|
|
95
|
+
/simulate ← find & fix bugs
|
|
96
|
+
/build ← clear the backlog
|
|
97
|
+
/launch ← ship
|
|
150
98
|
```
|
|
151
99
|
|
|
152
|
-
|
|
100
|
+
Or just:
|
|
153
101
|
|
|
154
102
|
```
|
|
155
|
-
|
|
156
|
-
"I can see: Next.js 14, Prisma, Vitest, dev server on port 3000,
|
|
157
|
-
3 open critical bugs, last commit 2 hours ago, milestone v1.2 is 60% done"
|
|
103
|
+
/vibeloop ← does all of the above, continuously
|
|
158
104
|
```
|
|
159
105
|
|
|
160
|
-
**~95% fewer tokens. Instant context. Every session.**
|
|
161
|
-
|
|
162
|
-
The autonomous commands (`/simulate`, `/build`, `/launch`) all read the same manifest. That's why they work without human guidance. They know your stack, your commands, your open issues, your product brief. They're not guessing.
|
|
163
|
-
|
|
164
106
|
---
|
|
165
107
|
|
|
166
|
-
##
|
|
167
|
-
|
|
168
|
-
These live in `.claude/commands/` in your project. Commit this folder to share them with your team.
|
|
169
|
-
|
|
170
|
-
| Command | Plain English |
|
|
171
|
-
|---------|--------------|
|
|
172
|
-
| `/setup` | First-time setup. Creates GitHub labels, your first milestone, and `docs/PRODUCT.md`. Run once per project. |
|
|
173
|
-
| `/simulate` | Opens your app in a real browser. Acts like multiple types of users. Finds bugs, UX problems, and accessibility issues. Fixes what it can, tracks the rest as GitHub Issues. |
|
|
174
|
-
| `/build` | Reads your open GitHub Issues. Picks the most important one. Implements the fix. Tests it. Commits it. Closes the issue. Moves to the next. Repeats. |
|
|
175
|
-
| `/launch` | Checks quality gates (bugs, tests, UX score). If everything passes: bumps version, tags release, merges to main, publishes GitHub Release. |
|
|
176
|
-
| `/review` | Deep code audit. Checks for security vulnerabilities, code quality problems, outdated/vulnerable dependencies, and accessibility issues. Everything goes to GitHub Issues. |
|
|
177
|
-
| `/vibeloop` | **The single command that does everything.** Runs `/simulate → /build → /launch` in a fully autonomous loop until your project is shipped. Zero human intervention required. |
|
|
178
|
-
|
|
179
|
-
### `/vibeloop` — the one command to rule them all
|
|
180
|
-
|
|
181
|
-
If you only remember one command, make it this one:
|
|
108
|
+
## `/vibeloop` — zero intervention mode
|
|
182
109
|
|
|
183
110
|
```
|
|
184
111
|
/vibeloop # full autonomous run: simulate → build → launch
|
|
@@ -189,51 +116,41 @@ If you only remember one command, make it this one:
|
|
|
189
116
|
/vibeloop --version 1.2.0 # pin the release version tag
|
|
190
117
|
```
|
|
191
118
|
|
|
192
|
-
|
|
119
|
+
Invoke once. Come back to a shipped, tested, tagged release.
|
|
193
120
|
|
|
194
121
|
---
|
|
195
122
|
|
|
196
|
-
##
|
|
197
|
-
|
|
198
|
-
codebase enforces a simple convention that makes autonomous commits safe:
|
|
199
|
-
|
|
200
|
-
- **All work happens on `develop`** — the AI commits here
|
|
201
|
-
- **`main` is protected** — direct commits are blocked by a git hook
|
|
202
|
-
- **Releases merge `develop → main`** — only via `codebase release`, with a proper merge commit
|
|
203
|
-
- **One commit per verified fix** — the AI never batches unrelated changes
|
|
123
|
+
## All CLI commands
|
|
204
124
|
|
|
205
|
-
|
|
125
|
+
```bash
|
|
126
|
+
# First run
|
|
127
|
+
npx codebase-ai # scan + wire AI tools + hooks
|
|
206
128
|
|
|
207
|
-
|
|
129
|
+
# Re-wire after adding a new AI tool
|
|
130
|
+
codebase setup
|
|
208
131
|
|
|
209
|
-
|
|
132
|
+
# AI interface
|
|
133
|
+
codebase brief # full project briefing
|
|
134
|
+
codebase next # highest-priority open issue
|
|
135
|
+
codebase status # kanban board + milestones
|
|
136
|
+
codebase query <path> # e.g. stack.languages or commands.test
|
|
210
137
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
| **Structure** | Where `src/` is, entry points, build output |
|
|
216
|
-
| **Dependencies** | What's installed, what's outdated, what's notable |
|
|
217
|
-
| **Config** | Which env vars exist, feature flags, CI setup |
|
|
218
|
-
| **Git** | Recent commits, active branches, uncommitted changes |
|
|
219
|
-
| **Quality** | Test framework, linter, formatter, pre-commit hooks |
|
|
220
|
-
| **GitHub** | Open issues by priority, PRs, milestones, releases |
|
|
221
|
-
| **Patterns** | Architecture style, API patterns, state management |
|
|
138
|
+
# Issues
|
|
139
|
+
codebase issue create "title"
|
|
140
|
+
codebase issue close <n> --reason "why"
|
|
141
|
+
codebase issue comment <n> --message "text"
|
|
222
142
|
|
|
223
|
-
|
|
143
|
+
# Maintenance
|
|
144
|
+
codebase scan # refresh .codebase.json
|
|
145
|
+
codebase doctor # health check
|
|
146
|
+
codebase fix # auto-repair
|
|
147
|
+
codebase mcp # start MCP server
|
|
148
|
+
```
|
|
224
149
|
|
|
225
150
|
---
|
|
226
151
|
|
|
227
152
|
## MCP Server
|
|
228
153
|
|
|
229
|
-
For AI tools that support Model Context Protocol:
|
|
230
|
-
|
|
231
|
-
```bash
|
|
232
|
-
codebase mcp # start stdio MCP server
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
Add to your Claude Code MCP config (`.mcp.json` in project root):
|
|
236
|
-
|
|
237
154
|
```json
|
|
238
155
|
{
|
|
239
156
|
"mcpServers": {
|
|
@@ -245,96 +162,40 @@ Add to your Claude Code MCP config (`.mcp.json` in project root):
|
|
|
245
162
|
}
|
|
246
163
|
```
|
|
247
164
|
|
|
248
|
-
Tools
|
|
165
|
+
Add to `.mcp.json` in your project root. Tools: `project_brief`, `get_codebase`, `query_codebase`, `get_next_task`, `get_blockers`, `create_issue`, `close_issue`, `rescan_project`, `list_commands`.
|
|
249
166
|
|
|
250
167
|
---
|
|
251
168
|
|
|
169
|
+
## Team usage
|
|
252
170
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
```bash
|
|
256
|
-
codebase doctor # shows exactly what's broken and why
|
|
257
|
-
codebase fix # auto-repairs everything doctor flags
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
`doctor` checks: manifest freshness, AI tool injection, MCP config, git hooks, commit-msg hook, `.claude/commands/`, and `.gitignore`.
|
|
261
|
-
|
|
262
|
-
---
|
|
263
|
-
|
|
264
|
-
## All CLI commands
|
|
265
|
-
|
|
266
|
-
```bash
|
|
267
|
-
# Setup
|
|
268
|
-
# Use `npx codebase` / `codebase init` the first time: scans your project AND wires AI tools + hooks.
|
|
269
|
-
# Use `codebase setup` to re-wire AI tools and hooks only — it does NOT re-scan. Run it when you
|
|
270
|
-
# add a new AI tool or need to reinstall hooks on an existing project.
|
|
271
|
-
npx codebase # full setup — scan + wire AI tools + hooks (run once per project)
|
|
272
|
-
codebase setup # re-wire AI tools and hooks only (no scan)
|
|
273
|
-
|
|
274
|
-
# AI interface (what AI tools call)
|
|
275
|
-
codebase brief # full project briefing
|
|
276
|
-
codebase next # highest-priority open issue
|
|
277
|
-
codebase status # kanban board + milestones
|
|
278
|
-
codebase query <path> # any field, e.g. stack.languages or commands.test
|
|
279
|
-
|
|
280
|
-
# Issues
|
|
281
|
-
codebase issue create "title" # create GitHub issue
|
|
282
|
-
codebase issue close <n> --reason "why" # close with reason
|
|
283
|
-
codebase issue comment <n> --message "text" # add comment (audit trail)
|
|
284
|
-
|
|
285
|
-
# Maintenance
|
|
286
|
-
codebase scan # refresh .codebase.json
|
|
287
|
-
codebase release # quality gates → tag → develop→main → GitHub release
|
|
288
|
-
codebase doctor # health check
|
|
289
|
-
codebase fix # auto-repair
|
|
290
|
-
|
|
291
|
-
# Integrations
|
|
292
|
-
codebase mcp # start MCP server
|
|
293
|
-
```
|
|
171
|
+
Commit `.codebase.json` and `.claude/commands/`. Every teammate with Claude Code gets the same context and slash commands. The loop is resumable — restart anytime, GitHub tracks state.
|
|
294
172
|
|
|
295
173
|
---
|
|
296
174
|
|
|
297
175
|
## FAQ
|
|
298
176
|
|
|
299
|
-
**Do I need Claude Code for this to work?**
|
|
300
|
-
Yes. `codebase` is built for Claude Code. The MCP server, slash commands, and autonomous loop all require Claude Code.
|
|
301
|
-
|
|
302
|
-
**What does "autonomous" actually mean — will it break my code?**
|
|
303
|
-
All AI commits go to `develop`. Nothing reaches `main` until you run `/launch` and quality gates pass. You're always in control of what ships. The AI runs tests before committing and opens issues rather than guessing when it's stuck.
|
|
304
|
-
|
|
305
177
|
**Does it send my code to anyone?**
|
|
306
|
-
No. Everything runs locally.
|
|
307
|
-
|
|
308
|
-
**Will the git hooks slow down my commits?**
|
|
309
|
-
No. The scan runs in ~200ms on most projects.
|
|
178
|
+
No. Everything runs locally. External calls go only to GitHub (via `gh` CLI) and Anthropic's API (only when you run Claude commands).
|
|
310
179
|
|
|
311
180
|
**What if I don't use GitHub?**
|
|
312
|
-
|
|
181
|
+
Manifest and AI tool wiring work without GitHub. You lose issues, PRs, releases, and labels — core context injection still works.
|
|
313
182
|
|
|
314
183
|
**My project isn't JavaScript — does it work?**
|
|
315
|
-
Yes.
|
|
316
|
-
|
|
317
|
-
**Can my whole team use this?**
|
|
318
|
-
Yes. Commit `.codebase.json` and `.claude/commands/`. Every team member with Claude Code gets the same context and the same slash commands.
|
|
319
|
-
|
|
320
|
-
---
|
|
184
|
+
Yes. 30+ languages, 100+ frameworks detected automatically.
|
|
321
185
|
|
|
322
|
-
|
|
186
|
+
**Will the git hooks slow down my commits?**
|
|
187
|
+
No. Scan runs in ~200ms.
|
|
323
188
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
npx codebase-ai # try without installing
|
|
327
|
-
pnpm add -g codebase-ai
|
|
328
|
-
```
|
|
189
|
+
**What does "autonomous" mean — will it break my code?**
|
|
190
|
+
All AI commits go to `develop`. Nothing reaches `main` until `/launch` passes quality gates.
|
|
329
191
|
|
|
330
|
-
|
|
192
|
+
→ [Full how-it-works docs](docs/HOW-IT-WORKS.md)
|
|
331
193
|
|
|
332
194
|
---
|
|
333
195
|
|
|
334
196
|
## Contributing
|
|
335
197
|
|
|
336
|
-
We welcome contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for
|
|
337
|
-
guidelines on how to get started, our commit conventions, and the PR process.
|
|
198
|
+
We welcome contributions! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to get started, our commit conventions, and the PR process.
|
|
338
199
|
|
|
339
200
|
Found a security issue? See [SECURITY.md](SECURITY.md) — do not open a public issue.
|
|
340
201
|
|
|
@@ -344,8 +205,7 @@ See [CHANGELOG.md](CHANGELOG.md) for a full version history.
|
|
|
344
205
|
|
|
345
206
|
## Code of Conduct
|
|
346
207
|
|
|
347
|
-
This project follows a [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
348
|
-
By participating, you agree to uphold it.
|
|
208
|
+
This project follows a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you agree to uphold it.
|
|
349
209
|
|
|
350
210
|
## License
|
|
351
211
|
|
package/dist/index.js
CHANGED
|
@@ -314,7 +314,7 @@ ${s}
|
|
|
314
314
|
`,"utf-8");cn(i,493)}var Je,on,ft=D(()=>{"use strict";Je="# codebase-auto-update";on="# codebase-pre-commit"});var ht={};Vt(ht,{installClaudeCommandsForFix:()=>Gr,installClaudeHooksForFix:()=>Br,installClaudeSkillsForFix:()=>Ur,runSetup:()=>Tt});import{resolve as Hr,dirname as ln,join as N}from"path";import{writeFileSync as ce,existsSync as K,mkdirSync as Ke,readFileSync as le,chmodSync as Mt,readdirSync as un,copyFileSync as mt}from"fs";import{execFile as Pe}from"child_process";async function Tt(e){let t=Hr(e.path);await Ge({...e,sync:!0}),S("Claude Code Integration"),K(N(t,"CLAUDE.md"))||ce(N(t,"CLAUDE.md"),`# Project Rules
|
|
315
315
|
`,"utf-8"),ae.inject(t),g("CLAUDE.md - added .codebase.json reference"),S("Git Hooks"),Re(t,!1)?(g("post-commit hook (auto-updates .codebase.json)"),g("pre-commit hook (runs typecheck + lint before every commit)"),Jr(t),g("commit-msg hook (blocks direct commits to main/master)")):h("Not a git repository - skipping hooks"),S("Claude Code Hooks"),fn(t),S("Browser Automation"),await Kr(),S("Claude Commands"),dn(t),S("Claude Skills"),pn(t),Ce(t),Wr(t,[".vibekit/daemon.lock",".vibekit/daemon.log",".vibekit/build.lock",".vibekit/milestone.env",".mcp.json"]),g(".gitignore updated"),S("Vibekit Bootstrap");let n=N(t,".vibekit");K(n)?h(".vibekit/ already exists"):(Ke(n,{recursive:!0}),g(".vibekit/ directory created")),S("GitHub Labels"),await zr()?(await Vr(t),await Qr(t)):(R("gh CLI not authenticated \u2014 skipping label/issue setup"),R("Run: gh auth login then codebase setup")),S("Product Brief");let o=N(t,"docs");K(o)||Ke(o,{recursive:!0});let r=N(o,"PRODUCT.md");K(r)?h("docs/PRODUCT.md already exists \u2014 skipping (delete to regenerate)"):(Yr(t,r),g("docs/PRODUCT.md generated \u2014 review and fill in [INFERRED] sections")),u(`
|
|
316
316
|
Done! Your project is wired for AI + autonomous loop.`),u(`
|
|
317
|
-
0. codebase brief \u2014 load project context (AI agents: call this first)`),u(" 1. Review docs/PRODUCT.md and fill in any [INFERRED] sections"),u(" 2. /simulate \u2014 AI customer journeys find & fix bugs"),u(" 3. /build \u2014 implement architectural issues autonomously"),u(" 4. /launch \u2014 gate check, release, merge to main")}function Gr(e){dn(e)}function dn(e){let t=N(ln(new URL(import.meta.url).pathname),"..","commands");if(!K(t)){R("Claude commands not found in package \u2014 skipping");return}let s=un(t).filter(r=>r.endsWith(".md")),n=[{dir:N(e,".claude","commands"),label:".claude/commands/"},{dir:N(process.env.HOME??"~",".claude","commands"),label:"~/.claude/commands/"}],i=0,o=0;for(let{dir:r,label:a}of n){Ke(r,{recursive:!0});let c=0,l=0,p=0;for(let m of s){let y=N(t,m),b=N(r,m);if(K(b)){let x=le(y,"utf-8"),j=le(b,"utf-8");x!==j?(mt(y,b),l++):p++}else mt(y,b),c++}let d=[];c>0&&d.push(`${c} new`),l>0&&d.push(`${l} updated`),p>0&&d.push(`${p} unchanged`),c>0||l>0?g(`Claude commands \u2192 ${a} (${d.join(", ")})`):h(`Claude commands up to date \u2192 ${a}`),i+=c,o+=l}(i>0||o>0)&&(h("Available: /setup /simulate /build /launch /review /vibeloop"),h("Tip: commit .claude/commands/ to share these with your team"))}function Ur(e){pn(e)}function pn(e){let t=N(ln(new URL(import.meta.url).pathname),"
|
|
317
|
+
0. codebase brief \u2014 load project context (AI agents: call this first)`),u(" 1. Review docs/PRODUCT.md and fill in any [INFERRED] sections"),u(" 2. /simulate \u2014 AI customer journeys find & fix bugs"),u(" 3. /build \u2014 implement architectural issues autonomously"),u(" 4. /launch \u2014 gate check, release, merge to main")}function Gr(e){dn(e)}function dn(e){let t=N(ln(new URL(import.meta.url).pathname),"..","commands");if(!K(t)){R("Claude commands not found in package \u2014 skipping");return}let s=un(t).filter(r=>r.endsWith(".md")),n=[{dir:N(e,".claude","commands"),label:".claude/commands/"},{dir:N(process.env.HOME??"~",".claude","commands"),label:"~/.claude/commands/"}],i=0,o=0;for(let{dir:r,label:a}of n){Ke(r,{recursive:!0});let c=0,l=0,p=0;for(let m of s){let y=N(t,m),b=N(r,m);if(K(b)){let x=le(y,"utf-8"),j=le(b,"utf-8");x!==j?(mt(y,b),l++):p++}else mt(y,b),c++}let d=[];c>0&&d.push(`${c} new`),l>0&&d.push(`${l} updated`),p>0&&d.push(`${p} unchanged`),c>0||l>0?g(`Claude commands \u2192 ${a} (${d.join(", ")})`):h(`Claude commands up to date \u2192 ${a}`),i+=c,o+=l}(i>0||o>0)&&(h("Available: /setup /simulate /build /launch /review /vibeloop"),h("Tip: commit .claude/commands/ to share these with your team"))}function Ur(e){pn(e)}function pn(e){let t=N(ln(new URL(import.meta.url).pathname),"../..","skills");if(!K(t)){R("Skills not found in package \u2014 skipping");return}let s=un(t).filter(a=>a.endsWith(".skill"));if(s.length===0){h("No skill files found in package");return}let n=[{dir:N(e,".claude","skills"),label:".claude/skills/"},{dir:N(process.env.HOME??"~",".claude","skills"),label:"~/.claude/skills/"}],i=0,o=0;for(let{dir:a,label:c}of n){Ke(a,{recursive:!0});let l=0,p=0,d=0;for(let y of s){let b=N(t,y),x=N(a,y);if(K(x)){let j=le(b),E=le(x);j.equals(E)?d++:(mt(b,x),p++)}else mt(b,x),l++}let m=[];l>0&&m.push(`${l} new`),p>0&&m.push(`${p} updated`),d>0&&m.push(`${d} unchanged`),l>0||p>0?g(`Skills \u2192 ${c} (${m.join(", ")})`):h(`Skills up to date \u2192 ${c}`),i+=l,o+=p}let r=s.map(a=>a.replace(/\.skill$/,"")).join(", ");i>0||o>0?(h(`Available: ${r}`),h("Tip: commit .claude/skills/ to share these with your team")):h(`Available: ${r}`)}function Br(e){fn(e)}function fn(e){let t=N(e,".claude","hooks");Ke(t,{recursive:!0});let s=N(t,"git-guard.sh");ce(s,`#!/bin/bash
|
|
318
318
|
# codebase git-guard \u2014 PreToolUse hook
|
|
319
319
|
# Reads Claude tool input JSON from stdin, enforces git safety rules.
|
|
320
320
|
|
|
@@ -552,7 +552,7 @@ ${w("SEE ALSO")}
|
|
|
552
552
|
`:""}${w("MORE HELP")}
|
|
553
553
|
${$("codebase --help")} Show all commands
|
|
554
554
|
${tt("https://github.com/ZySec-AI/codebase/docs","Full documentation")}
|
|
555
|
-
`)}var Nc={E_NO_GIT:{message:"Not a git repository",suggestion:"Initialize git first: "+$("git init")},E_NO_PACKAGE_JSON:{message:"No package.json found",suggestion:"Initialize project: "+$("npm init")+" or "+$("pnpm init")},E_GH_NOT_AUTHENTICATED:{message:"GitHub CLI not authenticated",suggestion:"Run: "+$("gh auth login")},E_MANIFEST_NOT_FOUND:{message:".codebase.json not found",suggestion:"Run: "+$("codebase init")+" to generate it"},E_INVALID_PATH:{message:"Invalid directory path",suggestion:"Use absolute path or path relative to current directory"},E_PERMISSION_DENIED:{message:"Permission denied",suggestion:"Check file permissions or run with appropriate access"}};var oi={command:"init",subcommand:"",positionals:[],path:process.cwd(),format:"text",depth:4,categories:[],incremental:!1,quiet:!1,force:!1,verbose:!1,port:7432,tools:[],dryRun:!1,since:"",sync:!1,message:"",reason:"",examples:!1,helpCommand:!1},Zt=new Set(["scan","setup","query","mcp","issue","status","init","scan-only","brief","next","doctor","fix","release","plan","skills","serve"]);function es(e){let t={...oi},s=[];for(let n=0;n<e.length;n++){let i=e[n];if(!i.startsWith("-")&&Zt.has(i)){if(t.command=i,e[n+1]==="--help"||e[n+1]==="-h")return t.helpCommand=!0,t;break}}for(let n=0;n<e.length;n++){let i=e[n];if((i==="--help"||i==="-h")&&!t.command&&(Yt(),process.exit(0)),(i==="--version"||i==="-v")&&(console.log("codebase 0.3.
|
|
555
|
+
`)}var Nc={E_NO_GIT:{message:"Not a git repository",suggestion:"Initialize git first: "+$("git init")},E_NO_PACKAGE_JSON:{message:"No package.json found",suggestion:"Initialize project: "+$("npm init")+" or "+$("pnpm init")},E_GH_NOT_AUTHENTICATED:{message:"GitHub CLI not authenticated",suggestion:"Run: "+$("gh auth login")},E_MANIFEST_NOT_FOUND:{message:".codebase.json not found",suggestion:"Run: "+$("codebase init")+" to generate it"},E_INVALID_PATH:{message:"Invalid directory path",suggestion:"Use absolute path or path relative to current directory"},E_PERMISSION_DENIED:{message:"Permission denied",suggestion:"Check file permissions or run with appropriate access"}};var oi={command:"init",subcommand:"",positionals:[],path:process.cwd(),format:"text",depth:4,categories:[],incremental:!1,quiet:!1,force:!1,verbose:!1,port:7432,tools:[],dryRun:!1,since:"",sync:!1,message:"",reason:"",examples:!1,helpCommand:!1},Zt=new Set(["scan","setup","query","mcp","issue","status","init","scan-only","brief","next","doctor","fix","release","plan","skills","serve"]);function es(e){let t={...oi},s=[];for(let n=0;n<e.length;n++){let i=e[n];if(!i.startsWith("-")&&Zt.has(i)){if(t.command=i,e[n+1]==="--help"||e[n+1]==="-h")return t.helpCommand=!0,t;break}}for(let n=0;n<e.length;n++){let i=e[n];if((i==="--help"||i==="-h")&&!t.command&&(Yt(),process.exit(0)),(i==="--version"||i==="-v")&&(console.log("codebase 0.3.4"),process.exit(0)),i.startsWith("--")){let o=i.slice(2);if(o==="quiet"||o==="q"){t.quiet=!0;continue}if(o==="force"){t.force=!0;continue}if(o==="raw"){console.error("Warning: --raw is deprecated, use --force instead"),t.force=!0;continue}if(o==="verbose"||o==="V"){t.verbose=!0;continue}if(o==="incremental"){t.incremental=!0;continue}if(o==="dry-run"){t.dryRun=!0;continue}if(o==="sync"){t.sync=!0;continue}if(o==="examples"){t.examples=!0;continue}if(o==="mine"){s.push("mine");continue}let r=e[n+1];if(!r||r.startsWith("--"))continue;n++,o==="path"?t.path=r:o==="format"?t.format=r:o==="depth"?t.depth=parseInt(r,10)||4:o==="categories"?t.categories=r.split(",").map(a=>a.trim()):o==="port"?t.port=parseInt(r,10)||7432:o==="tools"?t.tools=r.split(",").map(a=>a.trim()):o==="since"?t.since=r:o==="message"||o==="m"?t.message=r:o==="reason"&&(t.reason=r);continue}s.push(i)}if(s.length>0&&Zt.has(s[0])&&(t.command=s.shift()),s.length>0){let n=s[0];["install","uninstall","create","close","comment","list","map"].includes(n)&&(t.subcommand=s.shift())}return t.positionals=s,s.length>0&&/^[\/\.~]/.test(s[0])&&(t.path=s[0]),process.env.CODEBASE_OUTPUT&&(t.path=process.env.CODEBASE_OUTPUT),process.env.CODEBASE_PORT&&(t.port=parseInt(process.env.CODEBASE_PORT,10)||7432),process.env.CODEBASE_DEPTH&&(t.depth=parseInt(process.env.CODEBASE_DEPTH,10)||4),process.env.CODEBASE_QUIET==="true"&&(t.quiet=!0),t}function ts(e){Xt(e),process.exit(0)}M();import{get as ri}from"https";import{readFileSync as jt,writeFileSync as ai,mkdirSync as ci}from"fs";import{homedir as li}from"os";import{join as ss}from"path";import{execSync as st,spawnSync as ui}from"child_process";var ns=ss(li(),".codebase"),is=ss(ns,"update-check.json"),di=1440*60*1e3,me="codebase-ai",ke=!!process.env.NO_COLOR,C={yellow:ke?"":"\x1B[33m",cyan:ke?"":"\x1B[36m",green:ke?"":"\x1B[32m",bold:ke?"":"\x1B[1m",dim:ke?"":"\x1B[2m",reset:ke?"":"\x1B[0m"};function pi(){return"0.3.4"}function fi(e,t){let s=l=>l.replace(/^v/,"").split(".").map(Number),[n,i,o]=s(e),[r,a,c]=s(t);return n!==r?n>r:i!==a?i>a:o>c}function mi(){try{return JSON.parse(jt(is,"utf8"))}catch{return null}}function gi(e){try{ci(ns,{recursive:!0}),ai(is,JSON.stringify({version:e,checkedAt:Date.now()}))}catch{}}function hi(){return new Promise((e,t)=>{let s=ri(`https://registry.npmjs.org/${me}/latest`,{headers:{accept:"application/json"}},n=>{let i="";n.on("data",o=>i+=o.toString()),n.on("end",()=>{try{e(JSON.parse(i).version)}catch{t(new Error("parse error"))}})});s.on("error",t),s.setTimeout(3e3,()=>{s.destroy(),t(new Error("timeout"))})})}function bi(){try{let e=st("npm root -g 2>/dev/null",{encoding:"utf8"}).trim();if(e&&jt(`${e}/${me}/package.json`,"utf8"))return`npm install -g ${me}@latest`}catch{}try{st("pnpm --version 2>/dev/null",{encoding:"utf8"});let e=st("pnpm root -g 2>/dev/null",{encoding:"utf8"}).trim();if(e&&jt(`${e}/${me}/package.json`,"utf8"))return`pnpm add -g ${me}@latest`}catch{}try{return st("yarn --version 2>/dev/null",{encoding:"utf8"}),`yarn global add ${me}@latest`}catch{}return`npm install -g ${me}@latest`}function yi(e){let[t,...s]=e.split(" ");return ui(t,s,{stdio:"inherit"}).status===0}function ki(){return new Promise(e=>{let t=process.stdin,s=t.isTTY;s&&t.setRawMode(!0),t.resume(),t.setEncoding("utf8");let n=i=>{s&&t.setRawMode(!1),t.pause(),t.removeListener("data",n),e(i)};t.on("data",n),setTimeout(()=>{s&&t.setRawMode(!1),t.pause(),t.removeListener("data",n),e("n")},1e4)})}async function os(){if(process.env.CI||process.env.NO_UPDATE_CHECK||process.env.CODEBASE_NO_UPDATE_CHECK||!process.stdout.isTTY||!process.stdin.isTTY)return;let e=pi(),t=mi(),s;if(t&&Date.now()-t.checkedAt<di)s=t.version;else try{s=await hi(),gi(s)}catch{return}if(!fi(s,e))return;let n=bi();console.log(`
|
|
556
556
|
${C.yellow}\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510${C.reset}`),console.log(` ${C.yellow}\u2502${C.reset} ${C.bold}Update available${C.reset} ${C.dim}${e}${C.reset} ${C.yellow}\u2192${C.reset} ${C.bold}${C.cyan}${s}${C.reset}`),console.log(` ${C.yellow}\u2502${C.reset} Press ${C.bold}Y${C.reset} to update now, any other key to skip`),console.log(` ${C.yellow}\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518${C.reset}`),process.stdout.write(`
|
|
557
557
|
> `);let o=(await ki()).toLowerCase()==="y";if(console.log(o?"Updating\u2026":`Skipped.
|
|
558
558
|
`),!o)return;console.log(`
|
|
@@ -621,7 +621,7 @@ ${w("BACKLOG")} (${t.backlog.length})`);for(let n of t.backlog.slice(0,10))u(`
|
|
|
621
621
|
${w("IN PROGRESS")} (${t.in_progress.length})`);for(let n of t.in_progress.slice(0,10)){let i=n.assignee?` @${n.assignee}`:"";u(` #${n.number} ${n.title}${i}`)}t.in_progress.length>10&&te(` \u2026 and ${t.in_progress.length-10} more`);let s=t.needs_verify??[];if(s.length>0){u(`
|
|
622
622
|
${w("NEEDS VERIFY")} (${s.length})`);for(let n of s.slice(0,10))u(` #${n.number} ${n.title}`);s.length>10&&te(` \u2026 and ${s.length-10} more`)}u(`
|
|
623
623
|
${w("DONE")} (${t.done.length} recent)`);for(let n of t.done.slice(0,5))u(` #${n.number} ${n.title}`);t.done.length>5&&te(` \u2026 and ${t.done.length-5} more`)}function _a(e){S("Priority Queue");for(let t of e.priorities.slice(0,15)){let s=t.labels.length?` [${t.labels.join(", ")}]`:"",n=t.assignee?` \u2192 @${t.assignee}`:"";u(` #${t.number} ${t.title}${s}${n}`)}}function Ra(e){S("Milestones");for(let t of e.milestones){let s=Da(t.progress.percent),n=t.due_date?` (due: ${t.due_date.split("T")[0]})`:"";u(`
|
|
624
|
-
${w(t.title)} ${s} ${t.progress.percent}%${n}`),u(` ${t.progress.closed}/${t.progress.open+t.progress.closed} issues closed`)}}function Pa(e){S("Decisions");let t=[...e.from_prs.map(s=>({...s,type:"PR"})),...e.from_adrs.map(s=>({...s,type:"ADR"})),...e.manual.map(s=>({...s,type:"Manual"}))].sort((s,n)=>(n.date||"").localeCompare(s.date||""));for(let s of t.slice(0,15))u(` [${s.type}] ${s.title}`),s.summary&&u(` ${s.summary.slice(0,100)}`)}function Da(e){let t=Math.round(e/5),s=20-t;return`[${"\u2588".repeat(t)}${"\u2591".repeat(s)}]`}import{resolve as Ga}from"path";import{createInterface as Aa}from"readline";import{readFile as Qe,writeFile as wt,rename as vt}from"fs/promises";import{existsSync as kt,readdirSync as Pn}from"fs";import{join as Y,resolve as Dn}from"path";import{homedir as An}from"os";import{execFile as In}from"child_process";je();He();var Oa=[{name:"project_brief",description:"CALL THIS FIRST at the start of every session. Returns a complete project briefing: what the project is, tech stack, current priorities, open issues, blockers, what to work on next, and recent decisions. This is your single source of truth \u2014 call it before doing anything else.",inputSchema:{type:"object",properties:{}}},{name:"get_codebase",description:"Get codebase data by category with optional sparse field selection. Use the 'fields' array to request only specific fields (e.g. fields: ['languages', 'frameworks'] from category: 'stack'). For single dot-path lookups use query_codebase instead.",inputSchema:{type:"object",properties:{category:{type:"string",description:"Section to retrieve: repo, structure, stack, commands, dependencies, config, git, quality, patterns, status, roadmap, decisions"},fields:{type:"array",items:{type:"string"},description:"Optional. When category is specified, return only these keys from that section. E.g. ['languages', 'frameworks'] for stack."}}}},{name:"query_codebase",description:"Query a specific field using dot-path notation. Handles both targeted dot-path queries (e.g. 'stack.languages') and full category reads (e.g. 'stack'). Examples: 'stack.languages', 'commands.test', 'status.kanban.in_progress', 'roadmap.milestones'.",inputSchema:{type:"object",properties:{path:{type:"string",description:"Dot-path query, e.g. 'stack.languages', 'commands.test', 'status.priorities'"},fields:{type:"array",items:{type:"string"},description:"Optional: return only these fields from the result object"}},required:["path"]}},{name:"get_next_task",description:"Get the highest-priority task you should work on next. Returns the top open issue ranked by priority labels (P0 > P1 > bugs > features), including mapped files so you know where to start coding.",inputSchema:{type:"object",properties:{}}},{name:"get_blockers",description:"Get all current blockers \u2014 issues labeled as blocked, PRs waiting for review, PRs with failing CI checks, PRs with merge conflicts, and uncommitted changes. Shows what's preventing progress.",inputSchema:{type:"object",properties:{}}},{name:"create_issue",description:"Create a new GitHub issue. Use this when you discover a bug, identify needed work, or the user asks to track something. Returns the issue URL.",inputSchema:{type:"object",properties:{title:{type:"string",description:"Issue title"},body:{type:"string",description:"Issue body/description (markdown)"},labels:{type:"array",items:{type:"string"},description:"Labels to apply: bug, feature, enhancement, P0, P1, P2, etc."}},required:["title"]}},{name:"close_issue",description:"Close a GitHub issue after fixing it. Add a comment explaining what was done.",inputSchema:{type:"object",properties:{number:{type:"number",description:"Issue number to close"},comment:{type:"string",description:"Comment explaining resolution"}},required:["number"]}},{name:"update_issue",description:"Update a GitHub issue \u2014 add/remove labels, set assignee. Use this to advance issues through the pipeline (e.g., add 'status:in-progress', remove 'status:backlog').",inputSchema:{type:"object",properties:{number:{type:"number",description:"Issue number"},add_labels:{type:"array",items:{type:"string"},description:"Labels to add"},remove_labels:{type:"array",items:{type:"string"},description:"Labels to remove"},assignee:{type:"string",description:"GitHub username to assign (or empty string to unassign)"}},required:["number"]}},{name:"list_commands",description:"List installed Claude Code slash commands in this project. Returns names of available commands (e.g. /vibeloop, /setup, /simulate, /build, /launch, /review).",inputSchema:{type:"object",properties:{}}},{name:"list_skills",description:"List installed Claude Code skills with their names and descriptions. Skills extend /review and other commands with stack-specific analysis.",inputSchema:{type:"object",properties:{}}},{name:"get_plan",description:"Read the project's PLAN.md \u2014 Claude's persistent working memory across sessions. Contains current sprint goals, in-flight work, decisions log, and blockers. Call this after project_brief to restore loop context.",inputSchema:{type:"object",properties:{}}},{name:"update_plan",description:"Append a status update to PLAN.md. Use this at the end of each build or simulate cycle to record what was done, decisions made, and what's next. Creates PLAN.md if it doesn't exist.",inputSchema:{type:"object",properties:{message:{type:"string",description:"Status update text to append to PLAN.md Update Log section"}},required:["message"]}},{name:"get_issue",description:"Get full details of a specific GitHub issue by number, including body, comments, and linked PRs. Use this when working on an issue and need its complete specification.",inputSchema:{type:"object",properties:{number:{type:"number",description:"Issue number"}},required:["number"]}},{name:"get_pr",description:"Get full details of a specific pull request by number, including body, review status, checks, and diff stats.",inputSchema:{type:"object",properties:{number:{type:"number",description:"PR number"}},required:["number"]}},{name:"rescan_project",description:"Rescan the project to refresh the manifest after making changes. Call this after major refactors, dependency updates, or when your cached data feels stale.",inputSchema:{type:"object",properties:{sync:{type:"boolean",description:"Also refresh GitHub data (issues, PRs, milestones). Default: true."},incremental:{type:"boolean",description:"Only re-scan changed areas (faster). Default: false."}}}},{name:"refresh_status",description:"Refresh only GitHub data (issues, PRs, milestones) without re-scanning the filesystem. Much faster than rescan_project. Call this after creating/closing issues to get fresh priority data.",inputSchema:{type:"object",properties:{}}}];async function Nn(e){let t=Aa({input:process.stdin,terminal:!1});for await(let s of t){if(!s.trim())continue;let n;try{n=JSON.parse(s)}catch{On({jsonrpc:"2.0",id:0,error:{code:-32700,message:"Parse error"}});continue}let i=await Ia(n,e);i&&On(i)}}async function Ia(e,t){switch(e.method){case"initialize":return O(e.id,{protocolVersion:"2024-11-05",serverInfo:{name:"codebase",version:"0.3.
|
|
624
|
+
${w(t.title)} ${s} ${t.progress.percent}%${n}`),u(` ${t.progress.closed}/${t.progress.open+t.progress.closed} issues closed`)}}function Pa(e){S("Decisions");let t=[...e.from_prs.map(s=>({...s,type:"PR"})),...e.from_adrs.map(s=>({...s,type:"ADR"})),...e.manual.map(s=>({...s,type:"Manual"}))].sort((s,n)=>(n.date||"").localeCompare(s.date||""));for(let s of t.slice(0,15))u(` [${s.type}] ${s.title}`),s.summary&&u(` ${s.summary.slice(0,100)}`)}function Da(e){let t=Math.round(e/5),s=20-t;return`[${"\u2588".repeat(t)}${"\u2591".repeat(s)}]`}import{resolve as Ga}from"path";import{createInterface as Aa}from"readline";import{readFile as Qe,writeFile as wt,rename as vt}from"fs/promises";import{existsSync as kt,readdirSync as Pn}from"fs";import{join as Y,resolve as Dn}from"path";import{homedir as An}from"os";import{execFile as In}from"child_process";je();He();var Oa=[{name:"project_brief",description:"CALL THIS FIRST at the start of every session. Returns a complete project briefing: what the project is, tech stack, current priorities, open issues, blockers, what to work on next, and recent decisions. This is your single source of truth \u2014 call it before doing anything else.",inputSchema:{type:"object",properties:{}}},{name:"get_codebase",description:"Get codebase data by category with optional sparse field selection. Use the 'fields' array to request only specific fields (e.g. fields: ['languages', 'frameworks'] from category: 'stack'). For single dot-path lookups use query_codebase instead.",inputSchema:{type:"object",properties:{category:{type:"string",description:"Section to retrieve: repo, structure, stack, commands, dependencies, config, git, quality, patterns, status, roadmap, decisions"},fields:{type:"array",items:{type:"string"},description:"Optional. When category is specified, return only these keys from that section. E.g. ['languages', 'frameworks'] for stack."}}}},{name:"query_codebase",description:"Query a specific field using dot-path notation. Handles both targeted dot-path queries (e.g. 'stack.languages') and full category reads (e.g. 'stack'). Examples: 'stack.languages', 'commands.test', 'status.kanban.in_progress', 'roadmap.milestones'.",inputSchema:{type:"object",properties:{path:{type:"string",description:"Dot-path query, e.g. 'stack.languages', 'commands.test', 'status.priorities'"},fields:{type:"array",items:{type:"string"},description:"Optional: return only these fields from the result object"}},required:["path"]}},{name:"get_next_task",description:"Get the highest-priority task you should work on next. Returns the top open issue ranked by priority labels (P0 > P1 > bugs > features), including mapped files so you know where to start coding.",inputSchema:{type:"object",properties:{}}},{name:"get_blockers",description:"Get all current blockers \u2014 issues labeled as blocked, PRs waiting for review, PRs with failing CI checks, PRs with merge conflicts, and uncommitted changes. Shows what's preventing progress.",inputSchema:{type:"object",properties:{}}},{name:"create_issue",description:"Create a new GitHub issue. Use this when you discover a bug, identify needed work, or the user asks to track something. Returns the issue URL.",inputSchema:{type:"object",properties:{title:{type:"string",description:"Issue title"},body:{type:"string",description:"Issue body/description (markdown)"},labels:{type:"array",items:{type:"string"},description:"Labels to apply: bug, feature, enhancement, P0, P1, P2, etc."}},required:["title"]}},{name:"close_issue",description:"Close a GitHub issue after fixing it. Add a comment explaining what was done.",inputSchema:{type:"object",properties:{number:{type:"number",description:"Issue number to close"},comment:{type:"string",description:"Comment explaining resolution"}},required:["number"]}},{name:"update_issue",description:"Update a GitHub issue \u2014 add/remove labels, set assignee. Use this to advance issues through the pipeline (e.g., add 'status:in-progress', remove 'status:backlog').",inputSchema:{type:"object",properties:{number:{type:"number",description:"Issue number"},add_labels:{type:"array",items:{type:"string"},description:"Labels to add"},remove_labels:{type:"array",items:{type:"string"},description:"Labels to remove"},assignee:{type:"string",description:"GitHub username to assign (or empty string to unassign)"}},required:["number"]}},{name:"list_commands",description:"List installed Claude Code slash commands in this project. Returns names of available commands (e.g. /vibeloop, /setup, /simulate, /build, /launch, /review).",inputSchema:{type:"object",properties:{}}},{name:"list_skills",description:"List installed Claude Code skills with their names and descriptions. Skills extend /review and other commands with stack-specific analysis.",inputSchema:{type:"object",properties:{}}},{name:"get_plan",description:"Read the project's PLAN.md \u2014 Claude's persistent working memory across sessions. Contains current sprint goals, in-flight work, decisions log, and blockers. Call this after project_brief to restore loop context.",inputSchema:{type:"object",properties:{}}},{name:"update_plan",description:"Append a status update to PLAN.md. Use this at the end of each build or simulate cycle to record what was done, decisions made, and what's next. Creates PLAN.md if it doesn't exist.",inputSchema:{type:"object",properties:{message:{type:"string",description:"Status update text to append to PLAN.md Update Log section"}},required:["message"]}},{name:"get_issue",description:"Get full details of a specific GitHub issue by number, including body, comments, and linked PRs. Use this when working on an issue and need its complete specification.",inputSchema:{type:"object",properties:{number:{type:"number",description:"Issue number"}},required:["number"]}},{name:"get_pr",description:"Get full details of a specific pull request by number, including body, review status, checks, and diff stats.",inputSchema:{type:"object",properties:{number:{type:"number",description:"PR number"}},required:["number"]}},{name:"rescan_project",description:"Rescan the project to refresh the manifest after making changes. Call this after major refactors, dependency updates, or when your cached data feels stale.",inputSchema:{type:"object",properties:{sync:{type:"boolean",description:"Also refresh GitHub data (issues, PRs, milestones). Default: true."},incremental:{type:"boolean",description:"Only re-scan changed areas (faster). Default: false."}}}},{name:"refresh_status",description:"Refresh only GitHub data (issues, PRs, milestones) without re-scanning the filesystem. Much faster than rescan_project. Call this after creating/closing issues to get fresh priority data.",inputSchema:{type:"object",properties:{}}}];async function Nn(e){let t=Aa({input:process.stdin,terminal:!1});for await(let s of t){if(!s.trim())continue;let n;try{n=JSON.parse(s)}catch{On({jsonrpc:"2.0",id:0,error:{code:-32700,message:"Parse error"}});continue}let i=await Ia(n,e);i&&On(i)}}async function Ia(e,t){switch(e.method){case"initialize":return O(e.id,{protocolVersion:"2024-11-05",serverInfo:{name:"codebase",version:"0.3.4"},capabilities:{tools:{}}});case"notifications/initialized":return null;case"tools/list":return O(e.id,{tools:Oa});case"tools/call":return Na(e,t);default:return{jsonrpc:"2.0",id:e.id,error:{code:-32601,message:`Method not found: ${e.method}`}}}}async function Na(e,t){let s=e.params||{},n=s.name,i=s.arguments||{};try{switch(n){case"project_brief":{let o=await Ve(t,!0),r=yt(o);return O(e.id,{content:[{type:"text",text:r}]})}case"get_codebase":{let o=await Ve(t),r=i.category,a=i.fields;if(r){let c=o[r];if(a?.length&&c&&typeof c=="object"&&c!==null){let l={};for(let p of a)l[p]=c[p];return O(e.id,{content:[{type:"text",text:JSON.stringify(l,null,2)}]})}return O(e.id,{content:[{type:"text",text:JSON.stringify(c??null,null,2)}]})}return O(e.id,{content:[{type:"text",text:JSON.stringify(o,null,2)}]})}case"query_codebase":{let o=await Ve(t),r=i.path,a=i.fields,c=Ae(o,r);if(a?.length&&c!==null&&c!==void 0&&typeof c=="object"&&!Array.isArray(c)){let l={};for(let p of a)l[p]=c[p];c=l}return O(e.id,{content:[{type:"text",text:JSON.stringify(c??null,null,2)}]})}case"get_next_task":{let o=await Ve(t,!0),r=Fa(o);return O(e.id,{content:[{type:"text",text:JSON.stringify(r,null,2)}]})}case"get_blockers":{let o=await Ve(t,!0),r=Ma(o);return O(e.id,{content:[{type:"text",text:JSON.stringify(r,null,2)}]})}case"create_issue":{let o=await Ta(t,i);return await Bt(t),O(e.id,{content:[{type:"text",text:o}]})}case"close_issue":{let o=await qa(t,i);return await Bt(t),O(e.id,{content:[{type:"text",text:o}]})}case"update_issue":{let o=await Ha(t,i);return await Bt(t),O(e.id,{content:[{type:"text",text:o}]})}case"list_commands":{let o=Y(t,".claude","commands"),r=Y(An(),".claude","commands"),a=new Set,c=[];for(let p of[o,r])if(kt(p))for(let d of Pn(p))d.endsWith(".md")&&!a.has(d)&&(a.add(d),c.push(d));if(c.length===0)return O(e.id,{content:[{type:"text",text:"No slash commands installed. Run: codebase setup"}]});let l=c.map(p=>"/"+p.replace(/\.md$/,"")).join(", ");return O(e.id,{content:[{type:"text",text:`Installed commands (${c.length}): ${l}
|
|
625
625
|
|
|
626
626
|
Loop: /simulate \u2192 /build \u2192 /launch`}]})}case"list_skills":{let o=Y(An(),".claude","skills"),r=Y(t,".claude","skills"),a=new Set,c=[];for(let p of[r,o])if(kt(p))for(let d of Pn(p))d.endsWith(".skill")&&!a.has(d)&&(a.add(d),c.push({file:d,dir:p}));if(c.length===0)return O(e.id,{content:[{type:"text",text:"No skills installed in ~/.claude/skills/ or <project>/.claude/skills/. Run: codebase setup"}]});let l=[];return await Promise.all(c.map(({file:p,dir:d})=>new Promise(m=>{let y=Y(d,p);In("unzip",["-p",y,"*/SKILL.md"],{timeout:1e4},(b,x)=>{if(b||!x.trim()){m();return}let j=x.match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!j){m();return}let E=j[1],f=E.match(/^name:\s*(.+)$/m),P=E.match(/^description:\s*(.+)$/m),A=f?f[1].trim():p.replace(/\.skill$/,""),G=P?P[1].trim():"";l.push({name:A,description:G,file:p}),m()})}))),O(e.id,{content:[{type:"text",text:JSON.stringify(l,null,2)}]})}case"get_plan":{let o=Y(Dn(t),"PLAN.md");if(!kt(o))return O(e.id,{content:[{type:"text",text:"No PLAN.md found. Use update_plan to create one."}]});let r=await Qe(o,"utf-8");return O(e.id,{content:[{type:"text",text:r}]})}case"update_plan":{let o=Y(Dn(t),"PLAN.md"),r=i.message,c=`
|
|
627
627
|
<!-- updated: ${new Date().toISOString().split("T")[0]} -->
|
|
@@ -704,6 +704,6 @@ ${n}`;await Jn(e,o,"utf-8"),u(`${w("Created")} PLAN.md`);return}let i=await Wn(e
|
|
|
704
704
|
## Update Log
|
|
705
705
|
${n}`,await Jn(e,i,"utf-8"),u(`${w("Updated")} PLAN.md`)}M();import{join as Kt,resolve as vc}from"path";import{existsSync as $c,readdirSync as xc}from"fs";import{execFile as jc}from"child_process";function Sc(e){return new Promise((t,s)=>{jc("unzip",["-p",e,"*/SKILL.md"],(n,i)=>{n&&!i?s(n):t(i??"")})})}function Cc(e){let t=e.match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!t)return{};let s={};for(let n of t[1].split(`
|
|
706
706
|
`)){let i=n.indexOf(":");if(i===-1)continue;let o=n.slice(0,i).trim(),r=n.slice(i+1).trim().replace(/^['"]|['"]$/g,"");o&&(s[o]=r)}return s}async function Vn(e){let t=Kt(process.env.HOME??"~",".claude","skills"),s=Kt(vc(e.path??"."),".claude","skills"),n=new Set,i=[];for(let d of[s,t])if($c(d))for(let m of xc(d))m.endsWith(".skill")&&!n.has(m)&&(n.add(m),i.push({file:m,dir:d}));if(i.length===0){u("No skills installed. Run: codebase setup");return}let o=[];for(let{file:d,dir:m}of i){let y=Kt(m,d),b=d.replace(/\.skill$/,""),x="";try{let j=await Sc(y),E=Cc(j);E.name&&(b=E.name),E.description&&(x=E.description)}catch{}o.push({name:b,description:x,file:d})}if(o.length===0){u("No skills installed. Run: codebase setup");return}let r=Math.max(4,...o.map(d=>d.name.length)),a=Math.max(11,...o.map(d=>d.description.length)),c=Math.max(4,...o.map(d=>d.file.length)),l=(d,m)=>d.padEnd(m),p=` ${"\u2500".repeat(r)} ${"\u2500".repeat(a)} ${"\u2500".repeat(c)}`;h(`
|
|
707
|
-
${l("Name",r)} ${l("Description",a)} File`),u(p);for(let d of o)u(` ${l(d.name,r)} ${l(d.description,a)} ${d.file}`);u("")}import{createServer as Rc}from"http";je();import{readFile as Ec,writeFile as _c}from"fs/promises";import{join as Qn}from"path";async function Yn(e,t,s){let n=new URL(e,"http://localhost"),i=n.pathname;if(i==="/health")return{status:200,body:{status:"ok",version:"0.3.
|
|
707
|
+
${l("Name",r)} ${l("Description",a)} File`),u(p);for(let d of o)u(` ${l(d.name,r)} ${l(d.description,a)} ${d.file}`);u("")}import{createServer as Rc}from"http";je();import{readFile as Ec,writeFile as _c}from"fs/promises";import{join as Qn}from"path";async function Yn(e,t,s){let n=new URL(e,"http://localhost"),i=n.pathname;if(i==="/health")return{status:200,body:{status:"ok",version:"0.3.4"}};if(i==="/codebase/query"&&t==="GET"){let o=n.searchParams.get("path");if(!o)return{status:400,body:{error:"Missing 'path' query parameter"}};let r=await zt(s);return r?{status:200,body:Ae(r,o)??null}:{status:404,body:{error:"No manifest. POST /codebase/scan first."}}}if(i==="/codebase/scan"&&t==="POST"){let o=await W(s,{quiet:!0});return await _c(Qn(s,".codebase.json"),JSON.stringify(o,null,2),"utf-8"),{status:200,body:o}}if(i==="/codebase"&&t==="GET"){let o=await zt(s);return o?{status:200,body:o}:{status:404,body:{error:"No manifest. POST /codebase/scan first."}}}if(i.startsWith("/codebase/")&&t==="GET"){let o=i.split("/")[2],r=await zt(s);if(!r)return{status:404,body:{error:"No manifest."}};let a=r[o];return a===void 0?{status:404,body:{error:`Category '${o}' not found.`}}:{status:200,body:a}}return{status:404,body:{error:"Not found"}}}async function zt(e){try{let t=await Ec(Qn(e,".codebase.json"),"utf-8");return JSON.parse(t)}catch{return null}}function Xn(e,t){let s=Rc(async(n,i)=>{if(i.setHeader("Access-Control-Allow-Origin","*"),i.setHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS"),i.setHeader("Access-Control-Allow-Headers","Content-Type"),i.setHeader("Content-Type","application/json"),n.method==="OPTIONS"){i.writeHead(200),i.end();return}try{let o=await Yn(n.url||"/",n.method||"GET",e);i.writeHead(o.status),i.end(JSON.stringify(o.body,null,2))}catch{i.writeHead(500),i.end(JSON.stringify({error:"Internal server error"}))}});s.listen(t,()=>{console.log(`codebase server running on http://localhost:${t}`),console.log(`
|
|
708
708
|
Endpoints:`),console.log(" GET /health Health check"),console.log(" GET /codebase Full manifest"),console.log(" GET /codebase/:category Single category"),console.log(" GET /codebase/query?path=stack.languages"),console.log(" POST /codebase/scan Trigger re-scan")}),process.on("SIGINT",()=>{s.close(),process.exit(0)}),process.on("SIGTERM",()=>{s.close(),process.exit(0)})}var pe=es(process.argv.slice(2));ee(pe.quiet);Qt(pe.verbose);pe.helpCommand&&pe.command&&ts(pe.command);var Pc={scan:Ge,init:bn,brief:yn,next:wn,setup:Tt,query:vn,issue:En,status:Rn,mcp:Ln,doctor:qn,fix:Un,release:Bn,plan:zn,skills:Vn,serve:e=>(Xn(e.path,e.port??3e3),Promise.resolve()),"scan-only":Ge};os().catch(()=>{});var[Dc]=process.versions.node.split(".").map(Number);Dc<20&&(console.error(`Error: Node.js 20 or higher is required. You are running v${process.versions.node}.`),console.error("Upgrade: https://nodejs.org"),process.exit(1));var Zn=Pc[pe.command];Zn||(v(`Unknown command: ${pe.command}`),h(`Run ${w("codebase --help")} to see all commands.`),process.exit(1));Zn(pe).catch(e=>{v(`Error: ${e.message}`);let t=e.message.toLowerCase();t.includes("not a git repository")?h(`Initialize git first: ${w("git init")}`):t.includes("permission denied")?h("Check file permissions or run with appropriate access"):t.includes("enoent")&&t.includes("gh")?h(`GitHub CLI (gh) is not installed. Install it: ${w("brew install gh && gh auth login")}`):t.includes("no such file")?h("Check that the path is correct"):t.includes("github")&&(h(`Ensure GitHub CLI is installed: ${w("gh --version")}`),h(`Authenticate: ${w("gh auth login")}`)),process.exit(1)});
|
|
709
709
|
//# sourceMappingURL=index.js.map
|