@protoboxai/codeloop 0.3.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 +589 -0
- package/dist/commands/adopt.d.ts +2 -0
- package/dist/commands/adopt.js +26 -0
- package/dist/commands/adopt.js.map +1 -0
- package/dist/commands/brief.d.ts +2 -0
- package/dist/commands/brief.js +22 -0
- package/dist/commands/brief.js.map +1 -0
- package/dist/commands/card.d.ts +6 -0
- package/dist/commands/card.js +159 -0
- package/dist/commands/card.js.map +1 -0
- package/dist/commands/check.d.ts +4 -0
- package/dist/commands/check.js +76 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/cloud.d.ts +8 -0
- package/dist/commands/cloud.js +123 -0
- package/dist/commands/cloud.js.map +1 -0
- package/dist/commands/guard.d.ts +2 -0
- package/dist/commands/guard.js +26 -0
- package/dist/commands/guard.js.map +1 -0
- package/dist/commands/import.d.ts +2 -0
- package/dist/commands/import.js +24 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/inbox.d.ts +2 -0
- package/dist/commands/inbox.js +48 -0
- package/dist/commands/inbox.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +142 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install.d.ts +2 -0
- package/dist/commands/install.js +125 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/lane.d.ts +2 -0
- package/dist/commands/lane.js +100 -0
- package/dist/commands/lane.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.js +35 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +77 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/mock.d.ts +3 -0
- package/dist/commands/mock.js +22 -0
- package/dist/commands/mock.js.map +1 -0
- package/dist/commands/pack.d.ts +2 -0
- package/dist/commands/pack.js +19 -0
- package/dist/commands/pack.js.map +1 -0
- package/dist/commands/publish.d.ts +2 -0
- package/dist/commands/publish.js +125 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/remove.d.ts +2 -0
- package/dist/commands/remove.js +31 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/render.d.ts +5 -0
- package/dist/commands/render.js +47 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/commands/run.d.ts +2 -0
- package/dist/commands/run.js +45 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scan.d.ts +2 -0
- package/dist/commands/scan.js +26 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/schedule.d.ts +2 -0
- package/dist/commands/schedule.js +51 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +85 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/serve.d.ts +7 -0
- package/dist/commands/serve.js +126 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/spec.d.ts +3 -0
- package/dist/commands/spec.js +64 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/status.d.ts +3 -0
- package/dist/commands/status.js +251 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.js +83 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/verify.d.ts +3 -0
- package/dist/commands/verify.js +75 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/watch.d.ts +6 -0
- package/dist/commands/watch.js +111 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/commands/wiki.d.ts +3 -0
- package/dist/commands/wiki.js +85 -0
- package/dist/commands/wiki.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +86 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent.d.ts +27 -0
- package/dist/lib/agent.js +178 -0
- package/dist/lib/agent.js.map +1 -0
- package/dist/lib/board.d.ts +38 -0
- package/dist/lib/board.js +86 -0
- package/dist/lib/board.js.map +1 -0
- package/dist/lib/cards.d.ts +82 -0
- package/dist/lib/cards.js +107 -0
- package/dist/lib/cards.js.map +1 -0
- package/dist/lib/clock.d.ts +5 -0
- package/dist/lib/clock.js +14 -0
- package/dist/lib/clock.js.map +1 -0
- package/dist/lib/cloud.d.ts +122 -0
- package/dist/lib/cloud.js +580 -0
- package/dist/lib/cloud.js.map +1 -0
- package/dist/lib/competitors.d.ts +28 -0
- package/dist/lib/competitors.js +90 -0
- package/dist/lib/competitors.js.map +1 -0
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.js +25 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/cron.d.ts +5 -0
- package/dist/lib/cron.js +82 -0
- package/dist/lib/cron.js.map +1 -0
- package/dist/lib/detect.d.ts +13 -0
- package/dist/lib/detect.js +60 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/engine.d.ts +88 -0
- package/dist/lib/engine.js +435 -0
- package/dist/lib/engine.js.map +1 -0
- package/dist/lib/flow.d.ts +44 -0
- package/dist/lib/flow.js +121 -0
- package/dist/lib/flow.js.map +1 -0
- package/dist/lib/glob.d.ts +2 -0
- package/dist/lib/glob.js +10 -0
- package/dist/lib/glob.js.map +1 -0
- package/dist/lib/import.d.ts +13 -0
- package/dist/lib/import.js +127 -0
- package/dist/lib/import.js.map +1 -0
- package/dist/lib/inbox.d.ts +42 -0
- package/dist/lib/inbox.js +65 -0
- package/dist/lib/inbox.js.map +1 -0
- package/dist/lib/lane.d.ts +71 -0
- package/dist/lib/lane.js +105 -0
- package/dist/lib/lane.js.map +1 -0
- package/dist/lib/lock.d.ts +6 -0
- package/dist/lib/lock.js +64 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/mcp.d.ts +2 -0
- package/dist/lib/mcp.js +57 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/mock.d.ts +17 -0
- package/dist/lib/mock.js +137 -0
- package/dist/lib/mock.js.map +1 -0
- package/dist/lib/pack.d.ts +24 -0
- package/dist/lib/pack.js +77 -0
- package/dist/lib/pack.js.map +1 -0
- package/dist/lib/proposals.d.ts +48 -0
- package/dist/lib/proposals.js +240 -0
- package/dist/lib/proposals.js.map +1 -0
- package/dist/lib/render.d.ts +7 -0
- package/dist/lib/render.js +84 -0
- package/dist/lib/render.js.map +1 -0
- package/dist/lib/research.d.ts +8 -0
- package/dist/lib/research.js +39 -0
- package/dist/lib/research.js.map +1 -0
- package/dist/lib/run.d.ts +38 -0
- package/dist/lib/run.js +215 -0
- package/dist/lib/run.js.map +1 -0
- package/dist/lib/scaffold.d.ts +16 -0
- package/dist/lib/scaffold.js +175 -0
- package/dist/lib/scaffold.js.map +1 -0
- package/dist/lib/scan.d.ts +22 -0
- package/dist/lib/scan.js +85 -0
- package/dist/lib/scan.js.map +1 -0
- package/dist/lib/schedule.d.ts +20 -0
- package/dist/lib/schedule.js +66 -0
- package/dist/lib/schedule.js.map +1 -0
- package/dist/lib/server.d.ts +68 -0
- package/dist/lib/server.js +235 -0
- package/dist/lib/server.js.map +1 -0
- package/dist/lib/shell.d.ts +1 -0
- package/dist/lib/shell.js +25 -0
- package/dist/lib/shell.js.map +1 -0
- package/dist/lib/skills.d.ts +20 -0
- package/dist/lib/skills.js +92 -0
- package/dist/lib/skills.js.map +1 -0
- package/dist/lib/spec.d.ts +24 -0
- package/dist/lib/spec.js +102 -0
- package/dist/lib/spec.js.map +1 -0
- package/dist/lib/stats.d.ts +13 -0
- package/dist/lib/stats.js +43 -0
- package/dist/lib/stats.js.map +1 -0
- package/dist/lib/verify.d.ts +25 -0
- package/dist/lib/verify.js +135 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/version.d.ts +10 -0
- package/dist/lib/version.js +27 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/lib/wiki.d.ts +51 -0
- package/dist/lib/wiki.js +164 -0
- package/dist/lib/wiki.js.map +1 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.js +8 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/installer.d.ts +30 -0
- package/dist/registry/installer.js +133 -0
- package/dist/registry/installer.js.map +1 -0
- package/dist/registry/local-index.d.ts +32 -0
- package/dist/registry/local-index.js +58 -0
- package/dist/registry/local-index.js.map +1 -0
- package/dist/registry/lockfile.d.ts +40 -0
- package/dist/registry/lockfile.js +85 -0
- package/dist/registry/lockfile.js.map +1 -0
- package/dist/registry/security.d.ts +25 -0
- package/dist/registry/security.js +100 -0
- package/dist/registry/security.js.map +1 -0
- package/dist/registry/skill-schema.d.ts +30 -0
- package/dist/registry/skill-schema.js +95 -0
- package/dist/registry/skill-schema.js.map +1 -0
- package/dist/ui/404.html +1 -0
- package/dist/ui/_next/static/6wzGE5sCtbYkSyhMWxL32/_buildManifest.js +1 -0
- package/dist/ui/_next/static/6wzGE5sCtbYkSyhMWxL32/_ssgManifest.js +1 -0
- package/dist/ui/_next/static/chunks/255-54d3085ce94738a4.js +1 -0
- package/dist/ui/_next/static/chunks/423-bb541b7ae2733575.js +1 -0
- package/dist/ui/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
- package/dist/ui/_next/static/chunks/app/_not-found/page-d6bc774f7acb716e.js +1 -0
- package/dist/ui/_next/static/chunks/app/layout-e5fc8e78e1c8da95.js +1 -0
- package/dist/ui/_next/static/chunks/app/page-0c34b6e119cef236.js +1 -0
- package/dist/ui/_next/static/chunks/framework-de98b93a850cfc71.js +1 -0
- package/dist/ui/_next/static/chunks/main-49fd204fc9037ea3.js +1 -0
- package/dist/ui/_next/static/chunks/main-app-c46afa2f48f3aaef.js +1 -0
- package/dist/ui/_next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
- package/dist/ui/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
- package/dist/ui/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/ui/_next/static/chunks/webpack-4a462cecab786e93.js +1 -0
- package/dist/ui/_next/static/css/1bf01240dbfd6088.css +1 -0
- package/dist/ui/index.html +1 -0
- package/dist/ui/index.txt +19 -0
- package/dist/watch/index.d.ts +21 -0
- package/dist/watch/index.js +88 -0
- package/dist/watch/index.js.map +1 -0
- package/dist/watch/reporter.d.ts +11 -0
- package/dist/watch/reporter.js +44 -0
- package/dist/watch/reporter.js.map +1 -0
- package/dist/watch/signals.d.ts +38 -0
- package/dist/watch/signals.js +119 -0
- package/dist/watch/signals.js.map +1 -0
- package/dist/watch/triggers.d.ts +10 -0
- package/dist/watch/triggers.js +67 -0
- package/dist/watch/triggers.js.map +1 -0
- package/package.json +64 -0
- package/registry/index.json +106 -0
- package/starters/generic.yaml +95 -0
- package/starters/go.yaml +99 -0
- package/starters/node-typescript.yaml +108 -0
- package/starters/python.yaml +105 -0
- package/templates/ci/codeloop-pr.yml +29 -0
- package/templates/ci/codeloop-prod.yml +27 -0
- package/templates/ci/codeloop-staging.yml +34 -0
- package/templates/codeloop/board.json +5 -0
- package/templates/codeloop/gotchas.md +13 -0
- package/templates/codeloop/patterns.md +15 -0
- package/templates/codeloop/principles.md +49 -0
- package/templates/codeloop/rules.md +23 -0
- package/templates/commands/commit.md +255 -0
- package/templates/commands/debug.md +142 -0
- package/templates/commands/deploy.md +144 -0
- package/templates/commands/design.md +102 -0
- package/templates/commands/manage.md +77 -0
- package/templates/commands/plan.md +84 -0
- package/templates/commands/qa.md +155 -0
- package/templates/commands/reflect.md +93 -0
- package/templates/commands/ship.md +187 -0
- package/templates/commands/test.md +133 -0
- package/templates/hooks/commit-msg +8 -0
- package/templates/lanes/analyze.yaml +25 -0
- package/templates/lanes/build.yaml +45 -0
- package/templates/lanes/deploy.yaml +24 -0
- package/templates/lanes/learn.yaml +20 -0
- package/templates/lanes/market.yaml +25 -0
- package/templates/lanes/plan.yaml +24 -0
- package/templates/lanes/scan.yaml +11 -0
- package/templates/lanes/triage.yaml +24 -0
- package/templates/mock/template.html +82 -0
- package/templates/seeds/go-gotchas.md +28 -0
- package/templates/seeds/go-patterns.md +22 -0
- package/templates/seeds/node-typescript-gotchas.md +30 -0
- package/templates/seeds/node-typescript-patterns.md +27 -0
- package/templates/seeds/python-gotchas.md +30 -0
- package/templates/seeds/python-patterns.md +19 -0
- package/templates/seeds/universal-gotchas.md +11 -0
- package/templates/seeds/universal-patterns.md +11 -0
- package/templates/spec/plan.md +7 -0
- package/templates/spec/research.md +19 -0
- package/templates/spec/spec.md +14 -0
- package/templates/spec/tasks.md +10 -0
- package/templates/tasks/todo.md +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Dean Grover
|
|
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,589 @@
|
|
|
1
|
+
# codeloop
|
|
2
|
+
|
|
3
|
+
**The full dev lifecycle for AI coding agents.**
|
|
4
|
+
|
|
5
|
+
Your AI agent plans the work, tests it, reviews its own commits, deploys to staging, debugs production, and learns from every mistake — across sessions, across tools, without you babysitting it.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## The Problem
|
|
10
|
+
|
|
11
|
+
AI coding tools (Claude Code, Cursor, Codex) are stateless. Every session starts from zero. You've explained that `doc.save()` has race conditions six times. You've caught `console.log` in production code on every PR. The agent never learns, because it can't remember.
|
|
12
|
+
|
|
13
|
+
Worse — the agent can write code, but it can't test, deploy, or debug. You're still the glue between "code complete" and "live in production." That's where most of the time goes.
|
|
14
|
+
|
|
15
|
+
## The Pipeline
|
|
16
|
+
|
|
17
|
+
codeloop gives your project ten slash commands that cover the full development lifecycle:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
/design → /plan → /manage → /test → /commit → /qa → /deploy → /debug → /reflect → /ship
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
| Command | What it does |
|
|
24
|
+
|---------|-------------|
|
|
25
|
+
| `/design` | Analyze the codebase, generate a lightweight architectural spec |
|
|
26
|
+
| `/plan` | Write a task plan with acceptance criteria, enter plan mode |
|
|
27
|
+
| `/manage` | Track steps, check off progress, manage the task board |
|
|
28
|
+
| `/test` | Run your test suite, parse results, track coverage over time |
|
|
29
|
+
| `/commit` | Three-phase commit: review diff against learned rubrics → reflect on session → commit |
|
|
30
|
+
| `/qa` | Quality gate: static analysis + tests + coverage threshold + integrity checks |
|
|
31
|
+
| `/deploy` | Deploy to staging or production with verification gates |
|
|
32
|
+
| `/debug` | Search production logs, check health, cross-reference with recent commits |
|
|
33
|
+
| `/reflect` | Deep session review: scan all work, propose lessons to save |
|
|
34
|
+
| `/ship` | Close the loop: QA → staging → production → verify → done |
|
|
35
|
+
|
|
36
|
+
Each command reads your project's config and knowledge files. No runtime, no server — just markdown and YAML that the LLM reads directly.
|
|
37
|
+
|
|
38
|
+
## How Knowledge Compounds
|
|
39
|
+
|
|
40
|
+
Every gotcha has a frequency counter:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Session 1: You discover that boolean query params need Transform decorators.
|
|
44
|
+
/commit saves it → gotchas.md [freq:1]
|
|
45
|
+
Next review: appears as a WARNING (non-blocking)
|
|
46
|
+
|
|
47
|
+
Session 4: It comes up again. /reflect increments → [freq:2]
|
|
48
|
+
|
|
49
|
+
Session 7: Third time. → [freq:3]
|
|
50
|
+
Now it's CRITICAL. /commit blocks until you confirm it's handled.
|
|
51
|
+
|
|
52
|
+
Session 20: [freq:10+]
|
|
53
|
+
codeloop status says: "promote this to rules.md?"
|
|
54
|
+
It graduates from gotcha to non-negotiable rule.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Frequency = severity.** The more something bites you, the harder the system fights to prevent it. No configuration needed — it emerges from use.
|
|
58
|
+
|
|
59
|
+
The review is scoped too. Changed a backend file? It loads backend gotchas. Frontend only? It skips database warnings. Scopes in your config control what's relevant:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
scopes:
|
|
63
|
+
backend:
|
|
64
|
+
paths: ["src/**", "lib/**"]
|
|
65
|
+
gotcha_sections: ["Backend", "Database"]
|
|
66
|
+
frontend:
|
|
67
|
+
paths: ["app/**", "components/**"]
|
|
68
|
+
gotcha_sections: ["Frontend", "React"]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install -g @protoboxai/codeloop
|
|
75
|
+
cd your-project
|
|
76
|
+
codeloop init
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
It asks which AI tools you use, detects your tech stack, and scaffolds:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
.codeloop/
|
|
83
|
+
config.yaml ← Scopes, quality checks, deploy/test/debug config
|
|
84
|
+
rules.md ← Non-negotiable rules (always CRITICAL in review)
|
|
85
|
+
gotchas.md ← Discovered gotchas with frequency tracking
|
|
86
|
+
patterns.md ← Proven patterns with confidence levels
|
|
87
|
+
principles.md ← How you want the AI to operate
|
|
88
|
+
|
|
89
|
+
.claude/commands/ ← 10 slash commands (Claude Code)
|
|
90
|
+
.cursor/commands/ ← 10 slash commands (Cursor)
|
|
91
|
+
.agents/skills/ ← 10 skills (Codex)
|
|
92
|
+
|
|
93
|
+
tasks/todo.md ← Current task plan
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
The knowledge base (`.codeloop/`) is shared across all tools. Doesn't matter if you use Claude Code on Monday and Cursor on Tuesday — same gotchas, same rules.
|
|
97
|
+
|
|
98
|
+
## The Config
|
|
99
|
+
|
|
100
|
+
`.codeloop/config.yaml` controls everything. The AI reads it directly. `.codeloop/local.yaml` (gitignored) overrides it on one machine and is where keys, tokens and machine paths go.
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
project:
|
|
104
|
+
name: "my-api"
|
|
105
|
+
|
|
106
|
+
# Map file paths to knowledge sections
|
|
107
|
+
scopes:
|
|
108
|
+
backend:
|
|
109
|
+
paths: ["src/**"]
|
|
110
|
+
gotcha_sections: ["Backend", "Database", "API"]
|
|
111
|
+
tests:
|
|
112
|
+
paths: ["**/*.test.*"]
|
|
113
|
+
gotcha_sections: ["Testing"]
|
|
114
|
+
|
|
115
|
+
# Build/lint checks run during /commit and /qa
|
|
116
|
+
quality_checks:
|
|
117
|
+
backend:
|
|
118
|
+
- name: "Typecheck"
|
|
119
|
+
command: "npx tsc --noEmit 2>&1 | tail -20"
|
|
120
|
+
|
|
121
|
+
# Patterns banned in diffs
|
|
122
|
+
diff_scan:
|
|
123
|
+
- pattern: "console\\.log"
|
|
124
|
+
files: "*.ts,*.js"
|
|
125
|
+
exclude: "*.test.*"
|
|
126
|
+
severity: CRITICAL
|
|
127
|
+
message: "console.log in production code"
|
|
128
|
+
|
|
129
|
+
# Test runner config (used by /test and /qa)
|
|
130
|
+
test:
|
|
131
|
+
command: "npm test"
|
|
132
|
+
coverage_threshold: 80
|
|
133
|
+
integrity_checks: true
|
|
134
|
+
|
|
135
|
+
# Deployment gates (used by /deploy and /ship)
|
|
136
|
+
deploy:
|
|
137
|
+
staging:
|
|
138
|
+
command: "make deploy-staging"
|
|
139
|
+
verify: "curl -sf https://staging.example.com/health"
|
|
140
|
+
production:
|
|
141
|
+
command: "make deploy-prod"
|
|
142
|
+
verify: "curl -sf https://example.com/health"
|
|
143
|
+
requires: staging
|
|
144
|
+
|
|
145
|
+
# Production debugging (used by /debug)
|
|
146
|
+
debug:
|
|
147
|
+
logs: "fly logs --app myapp"
|
|
148
|
+
health: "curl -sf https://example.com/health"
|
|
149
|
+
|
|
150
|
+
# Frequency thresholds
|
|
151
|
+
codeloop:
|
|
152
|
+
critical_frequency: 3
|
|
153
|
+
promote_frequency: 10
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## The Commit Flow
|
|
157
|
+
|
|
158
|
+
When you type `/commit`:
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
Phase 1: Review
|
|
162
|
+
├─ Map changed files → scopes
|
|
163
|
+
├─ Load gotchas (freq ≥ 3 = CRITICAL, 1-2 = WARNING)
|
|
164
|
+
├─ Load patterns (HIGH confidence = expected)
|
|
165
|
+
├─ Run quality checks for active scopes
|
|
166
|
+
├─ Scan diff for violations
|
|
167
|
+
└─ Verdict: CLEAN / WARNINGS / BLOCKED
|
|
168
|
+
|
|
169
|
+
Phase 2: Reflect (lightweight)
|
|
170
|
+
├─ Scan session for new gotchas or patterns
|
|
171
|
+
├─ Propose saves (you pick what to keep)
|
|
172
|
+
└─ Write to gotchas.md or patterns.md
|
|
173
|
+
|
|
174
|
+
Phase 3: Commit
|
|
175
|
+
├─ Stage files
|
|
176
|
+
├─ Generate conventional commit message
|
|
177
|
+
└─ Create commit
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
If the review finds CRITICAL issues, it blocks. You can fix them, override, or abort.
|
|
181
|
+
|
|
182
|
+
## The Deployment Pipeline
|
|
183
|
+
|
|
184
|
+
`/qa` → `/deploy staging` → `/deploy prod` forms a gate chain:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
/qa passes → sets env:local-pass → unlocks staging
|
|
188
|
+
/deploy staging → sets env:staging-pass → unlocks production
|
|
189
|
+
/deploy prod → sets env:prod-pass → task is done
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`/ship` runs the full chain in one command. If any gate fails, it stops and creates a regression task on the board.
|
|
193
|
+
|
|
194
|
+
## Lanes
|
|
195
|
+
|
|
196
|
+
A lane is one YAML file in `.codeloop/lanes/`. It lists the stages a card moves through, the skill each stage runs, the command that decides whether the stage is finished, and the gates where a person has to say yes. `codeloop init` installs eight: build, market, analyze, triage, plan, deploy, learn, scan.
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
codeloop start "Add CSV export" # a card in the build lane, plus its spec folder
|
|
200
|
+
codeloop next # run the current stage's check; move the card if it passes
|
|
201
|
+
codeloop inbox # what is waiting for you, what to read, what shipped
|
|
202
|
+
codeloop approve 1 # approve the gate and move the card on
|
|
203
|
+
codeloop reject 1 "no proof for the claim"
|
|
204
|
+
codeloop run # start lanes that are due, advance every card not waiting for you
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Every command that changes a card ends with a `Next:` line saying what to do. A card id can be typed as `1`, `001`, `c-001` or `C-001`. The long forms (`codeloop card new|show|list|advance|approve|reject`) do the same things.
|
|
208
|
+
|
|
209
|
+
| Who you are | How it is decided |
|
|
210
|
+
|---|---|
|
|
211
|
+
| owner | You are typing at a terminal and `CODELOOP_ROLE` is unset. |
|
|
212
|
+
| agent | Input is piped or spawned: an agent, CI, the MCP server. |
|
|
213
|
+
| either, explicitly | `--as owner|reviewer|agent`, or `CODELOOP_ROLE`. |
|
|
214
|
+
|
|
215
|
+
| Behaviour | Rule |
|
|
216
|
+
|---|---|
|
|
217
|
+
| Check fails | The card stays in its stage. After `retries` failures (default 3) it is marked `stuck` with the command output attached. `codeloop run` does not count a failure again while the stage's output file is unchanged. |
|
|
218
|
+
| Approval | An approval covers the stage output and check as they were when it was given. If either changes before the card advances, the card waits for you again. |
|
|
219
|
+
| Gate | The card waits for you after the stage's check passes. `codeloop approve` approves and advances it once. A waiting card cannot advance. |
|
|
220
|
+
| Gate with `outward: true` | The stage changes something public (publish, prod deploy), so the card waits when it enters the stage, before any work or check runs. Approving does not run it; after approval the check still has to pass. |
|
|
221
|
+
| `trigger: { on: lane.done, lane: build }` | A card starts when a card finishes that lane. Same as the other lane's `on_done.start`; declaring both starts one card. |
|
|
222
|
+
| `trigger: { cron: "0 9-17 * * MON-FRI" }` | Five fields in local time: `*`, `*/n`, `a`, `a-b`, `a-b/n`, comma lists, day names. `lane lint` rejects anything else; `codeloop run` reports a lane it cannot parse and carries on. |
|
|
223
|
+
| `trigger: { on: git.commit }` or `git.tag` | `codeloop run --due` starts one card per new HEAD sha or newest tag. |
|
|
224
|
+
| `gates.mode: trusted` in `config.yaml` | Gates auto-approve, except outward gates, which always stop. |
|
|
225
|
+
| `wip` on a lane | New cards are refused once that many are unfinished. Proposals do not count. |
|
|
226
|
+
| `capacity.gates_per_day` | New cards are refused while more cards than this are parked. Proposals do not count. |
|
|
227
|
+
| Proposed card | `codeloop card propose <lane> "<title>"` creates a card at stage `proposed`, waiting at gate `proposal`. It takes no place in the lane and no run starts it. `codeloop approve` (owner) puts it in the lane's first stage without running that stage's check; `codeloop reject` drops it. |
|
|
228
|
+
| A check that writes the board | A stage's command may propose cards (the scan stage does). `codeloop verify` records its evidence on its own card the same way. The advance is then written on the board the check left, unless the card was moved or parked meanwhile, which is exit 3. |
|
|
229
|
+
| Exit codes | 2 = a check, gate or permission refused. 3 = `cards.json` changed since it was read; re-read and retry. |
|
|
230
|
+
|
|
231
|
+
Cards live in `.codeloop/cards.json`, separate from the task board in `board.json`.
|
|
232
|
+
|
|
233
|
+
**Roles are not authentication.** Locally the role is whatever the caller says it is: `--as owner` and `CODELOOP_ROLE=owner` are open to any agent or script on the machine. Gates stop a cooperating agent from moving on by accident; they do not stop one that claims to be the owner. Each event records the claimed role. `codeloop gate check` prints a warning for an approval that is only a local event, so CI should not treat it as proof that a person approved. `lane promote` and `lane rollback` need the owner role under the same caveat.
|
|
234
|
+
|
|
235
|
+
### Running unattended
|
|
236
|
+
|
|
237
|
+
`codeloop run` on its own only checks work that already exists. With an agent configured it also does the work: for each card that is not waiting for you and whose stage check does not pass yet, it starts a headless coding agent on that stage, then runs the check and moves the card, parks it at its gate, or counts a failed try.
|
|
238
|
+
|
|
239
|
+
```yaml
|
|
240
|
+
# .codeloop/config.yaml
|
|
241
|
+
agents:
|
|
242
|
+
default: claude
|
|
243
|
+
claude:
|
|
244
|
+
cmd: "claude -p --permission-mode acceptEdits < {brief}"
|
|
245
|
+
timeout_minutes: 20 # default 20
|
|
246
|
+
max_runs_per_day: 20 # default 20
|
|
247
|
+
codex:
|
|
248
|
+
cmd: "codex exec - < {brief}"
|
|
249
|
+
run:
|
|
250
|
+
agent: true # optional: plain `codeloop run` starts agents too
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
```bash
|
|
254
|
+
codeloop brief 1 # what the agent is given for the card's current stage
|
|
255
|
+
codeloop run --agent # agents.default; `--agent codex` names another
|
|
256
|
+
codeloop run --agent --dry-run # which cards would get an agent; starts and changes nothing
|
|
257
|
+
codeloop schedule install --every 30m # a crontab entry that runs `codeloop run --agent` here
|
|
258
|
+
codeloop schedule status | remove
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
`{brief}` becomes the shell-quoted path of `.codeloop/state/briefs/<card>-<stage>.md`. The brief holds the card, the stage's skill text from the skills index, the output path, the check command, rejection notes and the last failing check output for the stage, the wiki pages whose scope matches the files in play, and the rules: do this stage only, write the output, do not approve or advance, do not edit `cards.json` or lane files. The agent's output is kept in `.codeloop/state/agent-runs/<card>-<stage>-<n>.log` and each run is recorded on the card as `agent-start` and `agent-run` events (agent, exit code, duration, log path).
|
|
262
|
+
|
|
263
|
+
| Limit | Rule |
|
|
264
|
+
|---|---|
|
|
265
|
+
| One stage per card per run | After the agent finishes, the check runs once. The card moves one stage at most. |
|
|
266
|
+
| Waiting on a person | No agent starts for a card at a gate or marked stuck. |
|
|
267
|
+
| After a rejection | The stage is given back to the agent on the next run, with the note in its brief, even though the check that passed before still passes. Once per rejection; the card then waits at the gate again. |
|
|
268
|
+
| Public steps | No agent starts for a stage with `outward: true` until its gate is approved. |
|
|
269
|
+
| `wip` on a lane | Agents work on the first `wip` unfinished cards of the lane; the rest wait their turn. |
|
|
270
|
+
| `capacity.gates_per_day` | No agent starts while that many cards are waiting on you. |
|
|
271
|
+
| `max_runs_per_day` | Agent starts across the project in any 24 hours, counted from card events. The run says so when it is reached. |
|
|
272
|
+
| `timeout_minutes` | The agent and its child processes are killed. |
|
|
273
|
+
| Failed agent | An agent that exits non-zero or times out leaves the check to decide. A failed check after an agent run always counts toward `retries`, so a stage gets at most `retries` agent attempts before the card is stuck and waits for you. The `Next:` line names the log. |
|
|
274
|
+
| Overlapping runs | A card whose agent is still running from an earlier run is skipped. |
|
|
275
|
+
| Role | The agent runs with `CODELOOP_ROLE=agent`. `codeloop approve` and `reject` from inside it are refused, with or without `--as owner`. An agent that clears its own environment can still claim another role; see "Roles are not authentication" above. |
|
|
276
|
+
|
|
277
|
+
`schedule install` takes `--every` (minutes that divide the hour such as `30m`, or hours that divide the day such as `6h`; default `30m`) or `--cron "<five fields>"`, and `--agent <name>`. The entry carries the PATH of the shell that installed it, because cron starts with a bare one, and appends output to `.codeloop/state/run.log`. `--print` prints the line and installs nothing. Only this repo's entry is replaced or removed; other crontab lines are kept. `bash scripts/e2e-agent-real.sh` runs one stage with a real `claude -p` when `CODELOOP_E2E_REAL_AGENT=1` is set, and prints `SKIP` otherwise.
|
|
278
|
+
|
|
279
|
+
### A founder's week, as a script
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
npm run build && bash scripts/demo-founder-week.sh
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The script sets up a fresh temp project with the eight shipped lanes and a scripted stand-in for the coding agent, then drives a week and checks every step it claims (it exits 1 on the first mismatch). Sunday night triage proposes cards from an issues file; Monday the scan proposes a card from a competitor's changelog, the founder promotes it, plan ranks it, and a build card goes research, mock, spec gate, build, verify, review, release and live; finishing it starts a market card whose copy is rejected once, redone from the note and published; Friday the growth review opens a plan card; a third rejection at the copy gate becomes a lane proposal, an eval and market version 2. It ends with the inbox, the stats and a summary of cards, approvals, agent runs and lane versions. When a local Protobox answers on port 4002 the project is connected to it and the run ends with `cloud status`; otherwise it runs on local files and says so. A saved run is in [docs/artifacts/demo-founder-week.txt](docs/artifacts/demo-founder-week.txt).
|
|
286
|
+
|
|
287
|
+
The week is simulated with `CODELOOP_NOW=<time>`, which replaces the clock for any codeloop command, so every event carries that time and the cron lanes come due. `codeloop run --now <time>` does the same for a single run.
|
|
288
|
+
|
|
289
|
+
### Inbox
|
|
290
|
+
|
|
291
|
+
`codeloop inbox` (or `--json`) opens with one line such as `2 shipped this week, 3 waiting on you, oldest 2 days`. For each waiting card it names the file to read and the last check result. It prints three lists: the gates waiting on you, the cards finished since you last ran `codeloop inbox --seen`, and per-lane numbers (active, parked, done, human turns per card, first-pass rate).
|
|
292
|
+
|
|
293
|
+
### Adopt existing skills
|
|
294
|
+
|
|
295
|
+
The shipped lanes name only the ten skills codeloop installs, and `codeloop init` writes `.codeloop/skills.index.yaml` itself, so `lane lint` and `pack build` pass in a fresh repo. `codeloop adopt` rescans `.claude/skills`, `.claude/commands`, `.cursor/commands` and `.agents/skills` in the project and the `.claude` folders in your home directory (or `--from <dir>...`) and replaces the index. Once the index exists, `codeloop lane lint` rejects a stage that names a skill missing from it. `--gaps` lists stages with no mechanical done check. `codeloop pack build` compiles the lanes and the skills they name into a Protobox skills-only manifest.
|
|
296
|
+
|
|
297
|
+
### Changing a lane
|
|
298
|
+
|
|
299
|
+
Lanes change through proposals, and a proposal has to pass an eval before it can be installed.
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
codeloop lane propose # a gate rejected 3 times, or a stage stuck twice, writes .codeloop/proposals/<id>/
|
|
303
|
+
codeloop lane eval market-draft-1 # lint, fixtures, replay; writes eval-result.json
|
|
304
|
+
codeloop lane promote market-draft-1 --as owner
|
|
305
|
+
codeloop lane rollback market --as owner
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
`eval` exits 4 when a changed done check has no `expect: fail` fixture in `eval.yaml`, or passes on one: a check that cannot fail is refused. It exits 1 when the proposal weakens the lane: it removes a gate, changes a gate's approver, removes `outward`, removes a stage that finished cards passed, or lowers `retries` to 0. Each one must be listed under `accept_weakening:` in `eval.yaml` as `{ change, reason }`, and `promote` prints the reasons. It also exits 1 when a changed check, re-run in the project against the last 10 finished cards, fails one of them. List a card under `accept_regressions:` in `eval.yaml` to accept that. Per-card results are in `eval-result.json`. `promote` keeps the previous file in `.codeloop/lanes/.history/`.
|
|
309
|
+
|
|
310
|
+
### Specs and tasks
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
codeloop spec new c-001 # specs/001-<slug>/{research,spec,plan,tasks}.md, recorded on the card
|
|
314
|
+
codeloop spec check 001 # exit 2 until the spec is traceable
|
|
315
|
+
codeloop task list 001 --layer api # one builder's tasks
|
|
316
|
+
codeloop task done 001 T003
|
|
317
|
+
codeloop task check 001 --all-done # exit 1 while any task is open
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
`spec.md` holds acceptance lines `- US1 Given ..., when ..., then ...`. `tasks.md` holds one line per task: `- [ ] T003 [P] [US1] [api] text`, where the layer is `api`, `sdk`, `ui`, `test` or `docs`. `spec check` exits 2 on an untagged task, an acceptance line with no task, a task citing a missing `USn`, and more than five acceptance lines ("split the card"). The build lane's spec stage runs it, and its build stage requires every task ticked.
|
|
321
|
+
|
|
322
|
+
`codeloop import speckit [dir]` creates one build-lane card per `specs/NNN*/` feature and rewrites tasks with a layer tag. The layer is inferred from file paths in the task text, using `scopes` in `config.yaml` that are named after a layer; tasks it cannot place are marked `[?]` and listed. `codeloop import bmad [dir]` reads `sprint-status.yaml` and creates one card per story at the stage its status maps to. Both only read the source files; copies go to `specs/<card-id>-<slug>/`. Imported cards do not count against `wip` when they are created.
|
|
323
|
+
|
|
324
|
+
### Competitor scan
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
codeloop scan competitors # fetch each competitor page's changelog link
|
|
328
|
+
codeloop scan competitors --from-file notes.md # use a file as the page text (tests, pasted changelogs)
|
|
329
|
+
codeloop scan competitors --only acme
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
For each page in `.codeloop/wiki/competitors/` with a `changelog` link, the scan fetches the URL (10 second limit; a failure is reported as skipped and the scan carries on), turns HTML into lines of text, and compares it with the text stored from the last scan in `.codeloop/state/scan/<name>.txt`. When lines appeared that were not there before, it proposes one card in the plan lane for that competitor, titled `<name> shipped: <first new heading, or first new line>`, with the new lines and the source URL in the card's description. The first scan of a competitor only stores the baseline. The card is a proposal: it waits in `codeloop inbox` until the owner promotes it with `codeloop approve`, and nothing starts it. The same new text never produces a second card, even if the stored text is lost.
|
|
333
|
+
|
|
334
|
+
The shipped `scan` lane runs this weekly (`0 7 * * MON`): its one stage's check is `codeloop scan competitors`, so `codeloop run` does the scan with or without an agent.
|
|
335
|
+
|
|
336
|
+
### Research and competitor pages
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
codeloop wiki competitor add acme --docs https://acme.example/docs --changelog https://acme.example/changelog
|
|
340
|
+
codeloop wiki competitor list
|
|
341
|
+
codeloop check research c-001 --min-sources 3 # exit 1 without a verdict line and three source lines
|
|
342
|
+
codeloop check research c-001 --online # also asks each source URL; 2xx or 3xx passes
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Each competitor is one wiki page, `.codeloop/wiki/competitors/<name>.md`, with `title`, `docs` and `changelog` in its front matter and a `## Findings` list below. The brief for a stage named `research` includes every competitor page. The shipped build lane checks the research stage with `codeloop check research {id} --min-sources 3`: `research.md` needs a line starting `verdict:` and at least three lines of the form `- source: <url> — <note>` (a spaced hyphen also works). The check is offline by default so it gives the same answer every time; `--online` adds a HEAD request per URL, falling back to GET, with a 10 second limit.
|
|
346
|
+
|
|
347
|
+
When a research stage passes, each row of `research.md` that starts with a competitor's name (a table row or a `- name: ...` list item) is appended to that competitor's page as `- <card-id> <card title>: <the row>`. A page that already has rows from the card is left alone, and the card gets a `findings` event naming the page.
|
|
348
|
+
|
|
349
|
+
### Mocks
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
codeloop mock new c-001 --topic exports # docs/mocks/<project>/<topic>/c-001.html from the shared template
|
|
353
|
+
codeloop check mock c-001 # exit 1 until the mock passes
|
|
354
|
+
codeloop mocks index # docs/mocks/index.html: project, topic, cards, newest first
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Every mock starts from `templates/mock/template.html`: one page shell and one tokens block (light and dark colours, spacing, radius), the system font stack, flex and grid with `minmax`, and no pixel sizes. `<project>` is `project.name` from `config.yaml`. `check mock` fails when the file is missing, when it lacks the template's marker comment, when its tokens block differs from the template's, when it uses a hex colour or a colour function outside the tokens block, or when a screen named under `screens:` in the card's `spec.md` has no `<section data-screen="name">`. A spec that names no screens fails too; a card with nothing to draw says `screens: none` and passes without a mock, which is what makes the stage optional per card.
|
|
358
|
+
|
|
359
|
+
The shipped build lane runs `mock` between `research` and `spec`, so the spec gate shows a picture and a story together: `codeloop inbox` prints the mock path under the waiting card, and `codeloop serve` serves the gallery at `/mocks/` and links the card's mock from its detail panel. Projects set up before this keep their own `build.yaml`; add the stage by hand through a lane proposal.
|
|
360
|
+
|
|
361
|
+
### Verify
|
|
362
|
+
|
|
363
|
+
A use case lives in `usecases/<nnn>/<name>.yaml`:
|
|
364
|
+
|
|
365
|
+
```yaml
|
|
366
|
+
id: uc-001-02
|
|
367
|
+
accept: US2
|
|
368
|
+
failure_mode: "two writers who read the same version both land"
|
|
369
|
+
layers:
|
|
370
|
+
cli: { run: "bash usecases/001/uc.sh us2", expect: { exit: 0, stdout: "conflict" } }
|
|
371
|
+
api: { request: { method: PATCH, path: /api/tasks/t-1, body: { stage: live } }, expect: { status: 403 } }
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
`codeloop verify <nnn>` runs every layer, writes `evidence/<nnn>/<uc>.json` (sha, layer, pass, output tail) and `evidence/<nnn>/verify.md` with `result: pass|fail`, and adds the evidence to the card (`--no-record` skips that).
|
|
375
|
+
|
|
376
|
+
| Exit | Meaning |
|
|
377
|
+
|---|---|
|
|
378
|
+
| 2 | An acceptance line has no use case. |
|
|
379
|
+
| 1 | A use case failed, or has no runnable layer. |
|
|
380
|
+
| 2 | Also: the spec has no acceptance lines, or there are no use cases. Nothing to check is not a pass. |
|
|
381
|
+
| 4 | `--mutate`: a use case still passes on the commit before the card's first `Feature: <card-id>` commit, so it cannot fail. |
|
|
382
|
+
| 5 | `--mutate` could not run: no commit carries that trailer, or the setup command failed in the old commit ("environment differs"). No verdict is given. |
|
|
383
|
+
|
|
384
|
+
`--mutate` checks the old commit out in a temporary worktree and runs `verify.setup` from `config.yaml` there first (default `npm ci && npm run build` when the worktree has a `package.json`; set it to `""` to skip). When the project itself ships the `codeloop` binary, use cases drive the worktree's build. `--env <name>` points api use cases at `deploy.<name>.base_url` from `config.yaml`. `codeloop init --hooks` installs a commit-msg hook that adds the `Feature:` trailer from a branch name containing a card id.
|
|
385
|
+
|
|
386
|
+
Not built: the `ui` layer. There is no Playwright runner, and a use case with only a `ui` layer counts as a failure rather than a pass.
|
|
387
|
+
|
|
388
|
+
### Stats
|
|
389
|
+
|
|
390
|
+
`codeloop stats [--card <id>] [--lane <id>] [--compare v1 v2] [--json]` computes, from card events only: human turns per card, the longest unattended span, cycle time, rework (rejections ÷ approvals), stuck rate, and first-pass rate per gate. `--compare` splits by the lane version each card was created under.
|
|
391
|
+
|
|
392
|
+
### Wiki
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
codeloop wiki capture --title "Rename is not atomic across devices" --scope "src/lib/**" --body "..."
|
|
396
|
+
codeloop wiki inject --files src/lib/cards.ts # pages whose scope globs match
|
|
397
|
+
codeloop wiki list | lint
|
|
398
|
+
codeloop learn # apply the frequency thresholds
|
|
399
|
+
codeloop check gotchas --files <changed files> # exit 1 on an unacknowledged critical page
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Pages live in `.codeloop/wiki/{gotchas,decisions,concepts}/` with frontmatter `title, scope, freq, severity, cards, updated`. Capturing a title that exists raises its `freq`. At `codeloop.critical_frequency` (default 3) the page becomes critical and `check gotchas` blocks matching files until `--ack "<title>"`; `/commit` runs that check. At `codeloop.promote_frequency` (default 10) `codeloop learn` appends the page to `rules.md` once. `wiki lint` exits 1 on a broken relative link and reports pages older than 90 days and duplicate titles.
|
|
403
|
+
|
|
404
|
+
### Other hosts, MCP and CI
|
|
405
|
+
|
|
406
|
+
- `codeloop render [--host claude|cursor|codex|all]` writes each lane stage as `.claude/agents/codeloop-<lane>-<stage>.md`, each lane as `.cursor/rules/codeloop-<lane>.mdc` and `.agents/skills/codeloop-<lane>/SKILL.md`, and a block in `AGENTS.md` between `<!-- codeloop:start -->` and `<!-- codeloop:end -->`. A second run changes nothing.
|
|
407
|
+
- `codeloop mcp` serves the engine over stdio with the tools `inbox`, `next_up`, `get_card`, `advance`, `approve`, `reject`, `task_done`, `wiki_inject`, `wiki_capture`. `approve` and `reject` take the role from `CODELOOP_ROLE` in the server's environment and are refused for an agent.
|
|
408
|
+
- `codeloop init --ci github` writes three workflows. The PR one runs build, test, `lane lint` and fails a commit with no `Feature:` trailer. The staging one runs `deploy.staging.command` on a push to main and then verifies the shipped cards with `--env staging`; it does nothing while that command is unset. The prod one runs on a `v*` tag under `environment: production`, which waits for a reviewer once the environment has required reviewers.
|
|
409
|
+
- `codeloop gate check <id> --require <gate>` exits 2 unless the card has an approval for that gate.
|
|
410
|
+
|
|
411
|
+
### The board in a browser
|
|
412
|
+
|
|
413
|
+
`codeloop serve` prints a URL such as `http://127.0.0.1:4040/?token=…` and opens on a Cards view: one column per stage of the selected lane, a "waiting for you" badge with the gate name, and a detail panel with events, evidence, the spec path and a link to the card's mock. The mock gallery is at `/mocks/`. It starts without a `board.json`; the old task board is the Tasks tab. Approve and Reject on the page work only when the server was started with `codeloop serve --owner`; otherwise those requests return 403.
|
|
414
|
+
|
|
415
|
+
The server has no login. It listens on 127.0.0.1 only (`--host` changes that and exposes the board to the network), answers only to a localhost host name, sends no CORS headers, and requires the token from the printed URL, a JSON content type and a same-origin request for every change. Anyone who has the URL with its token can make changes, including approvals on an `--owner` board.
|
|
416
|
+
|
|
417
|
+
### Cloud store (optional)
|
|
418
|
+
|
|
419
|
+
Local files are the default and nothing below is needed. A Protobox workspace can hold a second copy of the board, the wiki, `config.yaml` and the lanes so several checkouts share them. Only codeloop is installed; there is no Protobox CLI.
|
|
420
|
+
|
|
421
|
+
| Command | What it does |
|
|
422
|
+
|---|---|
|
|
423
|
+
| `codeloop cloud connect --url <mcp url> --key <api key> [--folder <name>]` | Saves the connection in `.codeloop/cloud.json` (gitignored; the key is never printed). Uploads the board to a page titled "codeloop board", `config.yaml` to "codeloop board: config.yaml", each lane to "codeloop board: lanes/<lane>.yaml" and each wiki page under its own title. Pages go in folder `codeloop` (or `--folder`), lanes in `codeloop/codeloop-lanes`, wiki pages in `codeloop/codeloop-wiki`. A board page that already exists is adopted, not overwritten. |
|
|
424
|
+
| `codeloop cloud status` | Workspace URL, board revision against the local version, and every document as `in-sync`, `local-ahead`, `cloud-ahead` or `both-changed`. |
|
|
425
|
+
| `codeloop cloud pull [--force]` | Takes the cloud board, and every other cloud copy whose local file was not edited here. `--force` takes the cloud copy of everything. |
|
|
426
|
+
| `codeloop cloud push [--force]` | Writes the board, wiki pages and config that changed here. `--force` also replaces pages that changed in the cloud. Lanes are never pushed this way. |
|
|
427
|
+
| `codeloop cloud disconnect` | Pushes pending writes, pulls everything back into the repo, then removes `cloud.json` and the sync record. |
|
|
428
|
+
|
|
429
|
+
`.codeloop/state/sync.json` (gitignored) records, for each document, its page id, the revision this checkout last saw and a hash of the content at that moment. That is how a change here is told apart from a change in the cloud.
|
|
430
|
+
|
|
431
|
+
While connected, every command starts by syncing, and says what it did on stderr. That is one request to the workspace per command and one per card write; the endpoint allows 60 a minute and codeloop waits when it is told to slow down. `CODELOOP_NO_SYNC=1` skips the sync step for a command (a script that only reads, many times in a row); writes still go to the cloud first.
|
|
432
|
+
|
|
433
|
+
| Case | What happens |
|
|
434
|
+
|---|---|
|
|
435
|
+
| A page changed only in the cloud | The local file is updated before the command runs. This covers the board, config, lanes and wiki. |
|
|
436
|
+
| A wiki page or `config.yaml` was edited only here | Pushed before the command runs. |
|
|
437
|
+
| A lane file was edited here | Reported and not pushed. A lane reaches the cloud only through `codeloop lane promote` (or `lane rollback`). |
|
|
438
|
+
| A wiki page changed on both sides | Yours is kept and the cloud version is written beside it as `<name>.cloud.md`. `codeloop inbox` lists it under what is waiting for you. Merge it into your page and delete the copy; the next command pushes the merge. |
|
|
439
|
+
| The board changed on both sides | The command is refused with exit 3 and the local file is unchanged. `codeloop cloud pull`, then run it again. |
|
|
440
|
+
| `config.yaml` or a lane changed on both sides | Yours is kept and the command says so. `cloud pull --force` takes the cloud copy, `cloud push --force` replaces it. |
|
|
441
|
+
| The cloud cannot be reached | The command runs on the local files. A write is kept locally and marked `pending` in `sync.json`; the next command that reaches the cloud pushes pending writes first, with the same revision check. |
|
|
442
|
+
|
|
443
|
+
Every card write goes to the cloud page first with the revision this checkout last saw, so two checkouts cannot both land a write made from the same board. `wiki capture` also writes the page; `wiki inject` stays local.
|
|
444
|
+
|
|
445
|
+
**Keys, tokens and machine paths belong in `.codeloop/local.yaml`.** `config.yaml` is uploaded as it is, so it should hold only switches the whole team shares: approval mode, work limits, deploy commands. `local.yaml` has the same shape, is laid over `config.yaml` on this machine (maps merge key by key), is gitignored by `codeloop init`, and is never uploaded. codeloop does not move anything there for you.
|
|
446
|
+
|
|
447
|
+
```yaml
|
|
448
|
+
# .codeloop/local.yaml
|
|
449
|
+
agents:
|
|
450
|
+
claude: { cmd: "/Users/me/bin/claude -p --permission-mode acceptEdits < {brief}" }
|
|
451
|
+
deploy:
|
|
452
|
+
staging: { base_url: "http://localhost:8080" }
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
The workspace's MCP endpoint has to serve `KNOWLEDGE_WRITE_PAGE`, `KNOWLEDGE_READ_PAGE`, `KNOWLEDGE_LIST_PAGES` and `KNOWLEDGE_SEARCH`. `bash scripts/e2e-cloud.sh` proves all of the above against a local Protobox and prints `SKIP` when none is running.
|
|
456
|
+
|
|
457
|
+
`bash scripts/e2e-founder-loop.sh` runs all of the above except the cloud store against the built CLI in a temp project.
|
|
458
|
+
|
|
459
|
+
## Watch Mode
|
|
460
|
+
|
|
461
|
+
Monitor your project in the background:
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
codeloop watch # Start watching
|
|
465
|
+
codeloop watch --with-serve # Watch + board server (live UI)
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Watch detects file changes, git commits, test results, and build errors. Events are logged to `.codeloop/watch.log` and pushed to the board UI via SSE when the server is running.
|
|
469
|
+
|
|
470
|
+
## Skill Registry
|
|
471
|
+
|
|
472
|
+
Install community skills or share your own:
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
codeloop search "deploy" # Find skills
|
|
476
|
+
codeloop install review-checklist # Install from registry
|
|
477
|
+
codeloop install github:user/repo # Install from GitHub
|
|
478
|
+
codeloop install ./local-skill # Install from local path
|
|
479
|
+
codeloop list # Show installed skills
|
|
480
|
+
codeloop remove review-checklist # Uninstall
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Every installed skill gets security-validated (no `exec()`, no credential access, no pipe-to-shell) and locked with integrity hashes in `.codeloop/skills.lock`.
|
|
484
|
+
|
|
485
|
+
## Works With Everything
|
|
486
|
+
|
|
487
|
+
codeloop auto-detects your stack and tools:
|
|
488
|
+
|
|
489
|
+
| Stack | Detected by | Starter config |
|
|
490
|
+
|-------|-------------|----------------|
|
|
491
|
+
| TypeScript | `tsconfig.json` | Typecheck, console.log scan, `any` warnings |
|
|
492
|
+
| Python | `pyproject.toml`, `setup.py` | mypy, ruff, print() detection, pdb scan |
|
|
493
|
+
| Go | `go.mod` | go vet, go build, fmt.Print detection |
|
|
494
|
+
| Generic | Fallback | Minimal — you configure |
|
|
495
|
+
|
|
496
|
+
| Tool | Commands installed to | Compatibility |
|
|
497
|
+
|------|---------------------|---------------|
|
|
498
|
+
| Claude Code | `.claude/commands/` | Full (primary target) |
|
|
499
|
+
| Cursor | `.cursor/commands/` | Knowledge + config (tool hints are Claude-specific) |
|
|
500
|
+
| Codex | `.agents/skills/` | Knowledge + config (tool hints are Claude-specific) |
|
|
501
|
+
|
|
502
|
+
**Note**: The `allowed-tools` frontmatter in skill files uses Claude Code tool names (Bash, Read, Edit, etc.). Cursor and Codex ignore this field — the skill instructions still work, but tool restrictions aren't enforced. The knowledge files (gotchas, patterns, rules) and config are fully portable across all tools.
|
|
503
|
+
|
|
504
|
+
## CLI Reference
|
|
505
|
+
|
|
506
|
+
```bash
|
|
507
|
+
# Project setup
|
|
508
|
+
codeloop init # Interactive setup
|
|
509
|
+
codeloop init --tools claude,cursor # Skip tool prompt
|
|
510
|
+
codeloop init --starter python # Force specific stack
|
|
511
|
+
codeloop status # Knowledge stats, version check
|
|
512
|
+
codeloop update # Update skills (never touches knowledge)
|
|
513
|
+
|
|
514
|
+
# Lanes
|
|
515
|
+
codeloop lane list | show <id> | lint # Inspect and check lanes
|
|
516
|
+
codeloop card new <lane> <title> # Start a card (also: show, list, advance, approve, reject)
|
|
517
|
+
codeloop inbox # Gates waiting on you, what shipped, numbers
|
|
518
|
+
codeloop run --due # Start due cron lanes, advance unparked cards
|
|
519
|
+
codeloop run --agent [name] # Same, with a headless agent doing each stage first (--dry-run to preview)
|
|
520
|
+
codeloop brief <card> # The stage brief an agent is given
|
|
521
|
+
codeloop schedule install | status | remove # Crontab entry for `codeloop run --agent`
|
|
522
|
+
codeloop adopt # Index existing skills and commands
|
|
523
|
+
codeloop lane propose | eval | promote | rollback
|
|
524
|
+
codeloop check file <path> --has <s> # Done-check helper for lane stages
|
|
525
|
+
codeloop check research <card> # Verdict line and source lines in research.md (--min-sources, --online)
|
|
526
|
+
codeloop check mock <card> # Mock built from the shared template, every spec screen drawn
|
|
527
|
+
codeloop mock new <card> --topic <t> # Mock file from the shared template
|
|
528
|
+
codeloop mocks index # Mock gallery page
|
|
529
|
+
codeloop pack build # Protobox skills-only manifest
|
|
530
|
+
codeloop spec new | check # Spec folder for a card
|
|
531
|
+
codeloop task list | done | check # Layer-tagged tasks
|
|
532
|
+
codeloop import speckit | bmad # Bring existing specs in as cards
|
|
533
|
+
codeloop verify <nnn> [--mutate] # Run use cases, write evidence
|
|
534
|
+
codeloop stats # Autonomy numbers from card events
|
|
535
|
+
codeloop wiki capture | inject | list | lint
|
|
536
|
+
codeloop wiki competitor add | list # One wiki page per competitor
|
|
537
|
+
codeloop scan competitors # Propose a plan card for what each competitor's changelog added
|
|
538
|
+
codeloop card propose <lane> <title> # A card that waits for the owner before it enters its lane
|
|
539
|
+
codeloop learn # Apply gotcha frequency thresholds
|
|
540
|
+
codeloop render # Agents, rules and skills for Claude, Cursor, Codex
|
|
541
|
+
codeloop mcp # MCP server on stdio
|
|
542
|
+
codeloop gate check <id> --require <gate>
|
|
543
|
+
codeloop init --hooks | --ci github # commit-msg hook, CI workflows
|
|
544
|
+
codeloop start | next | approve | reject # Short forms of the card commands
|
|
545
|
+
codeloop cloud connect | status | push | pull | disconnect # Optional: Protobox copy of board, wiki, config and lanes
|
|
546
|
+
|
|
547
|
+
# Live monitoring
|
|
548
|
+
codeloop watch # Background file + git monitor
|
|
549
|
+
codeloop serve # Board UI server (http://127.0.0.1:4040, token in the printed URL)
|
|
550
|
+
|
|
551
|
+
# Skill registry
|
|
552
|
+
codeloop search <query> # Search for skills
|
|
553
|
+
codeloop install <name> # Install a skill
|
|
554
|
+
codeloop list # Show installed skills
|
|
555
|
+
codeloop remove <name> # Uninstall a skill
|
|
556
|
+
codeloop publish # Publish your skill to the registry
|
|
557
|
+
codeloop login # Authenticate with GitHub
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
## The Knowledge Files
|
|
561
|
+
|
|
562
|
+
**`rules.md`** — Non-negotiable. Always loaded as CRITICAL. Start with universal rules, add yours.
|
|
563
|
+
|
|
564
|
+
**`gotchas.md`** — Discovered through work. Each entry has `[freq:N]`. Severity auto-scales with frequency. Organized by sections matching your scopes.
|
|
565
|
+
|
|
566
|
+
**`patterns.md`** — What works well. HIGH-confidence patterns become expectations — deviations trigger warnings during review.
|
|
567
|
+
|
|
568
|
+
**`principles.md`** — How you want the AI to operate. Plan first? Verify before done? Write it here once, it applies everywhere.
|
|
569
|
+
|
|
570
|
+
All plain markdown. No lock-in, no proprietary format. If you stop using codeloop tomorrow, the knowledge stays as useful documentation.
|
|
571
|
+
|
|
572
|
+
## Working on codeloop itself
|
|
573
|
+
|
|
574
|
+
This repo runs on its own lanes (`.codeloop/lanes/`), which name only the bundled skills.
|
|
575
|
+
|
|
576
|
+
```bash
|
|
577
|
+
npm ci && npm --prefix ui ci
|
|
578
|
+
npm run build:all
|
|
579
|
+
node dist/index.js adopt --from templates/commands # index the bundled skills
|
|
580
|
+
node dist/index.js lane lint
|
|
581
|
+
npm test && bash scripts/e2e-founder-loop.sh
|
|
582
|
+
node dist/index.js inbox # the repo's own cards
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
`scripts/e2e-cloud.sh` and the cloud part of `scripts/demo-founder-week.sh` need a Protobox workspace; set `PROTOBOX_CACHE` to a JSON file holding its workspace id and API key. Both skip the cloud steps when it is absent.
|
|
586
|
+
|
|
587
|
+
## License
|
|
588
|
+
|
|
589
|
+
MIT
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { loadLanes, SKILLS_INDEX } from '../lib/lane.js';
|
|
4
|
+
import { defaultSkillDirs, doneGaps, duplicateSkills, scanSkills, writeSkillsIndex } from '../lib/skills.js';
|
|
5
|
+
import { guard } from './guard.js';
|
|
6
|
+
export const adoptCommand = new Command('adopt')
|
|
7
|
+
.description('Index the skills and commands that already exist so lanes can name them')
|
|
8
|
+
.option('--from <dir...>', 'Directories to scan (default: .claude/skills, .claude/commands, .cursor/commands, .agents/skills in the project, and ~/.claude/skills, ~/.claude/commands)')
|
|
9
|
+
.option('--gaps', 'List lane stages with no mechanical done check')
|
|
10
|
+
.action(guard((opts) => {
|
|
11
|
+
const projectDir = process.cwd();
|
|
12
|
+
const entries = scanSkills(projectDir, opts.from ?? defaultSkillDirs(projectDir));
|
|
13
|
+
writeSkillsIndex(projectDir, entries);
|
|
14
|
+
console.log(` indexed ${entries.length} skills and commands into ${SKILLS_INDEX}`);
|
|
15
|
+
for (const dup of duplicateSkills(entries)) {
|
|
16
|
+
console.log(chalk.yellow(` duplicate: ${dup.name}`));
|
|
17
|
+
dup.sources.forEach(s => console.log(chalk.dim(` ${s}`)));
|
|
18
|
+
}
|
|
19
|
+
if (opts.gaps) {
|
|
20
|
+
const gaps = doneGaps(loadLanes(projectDir));
|
|
21
|
+
if (gaps.length === 0)
|
|
22
|
+
console.log(' no gaps: every lane stage has a check command');
|
|
23
|
+
gaps.forEach(g => console.log(chalk.yellow(` gap: ${g.lane}/${g.stage}: ${g.reason}`)));
|
|
24
|
+
}
|
|
25
|
+
}));
|
|
26
|
+
//# sourceMappingURL=adopt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adopt.js","sourceRoot":"","sources":["../../src/commands/adopt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7G,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,yEAAyE,CAAC;KACtF,MAAM,CAAC,iBAAiB,EAAE,4JAA4J,CAAC;KACvL,MAAM,CAAC,QAAQ,EAAE,gDAAgD,CAAC;KAClE,MAAM,CAAC,KAAK,CAAC,CAAC,IAAyC,EAAE,EAAE;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,IAAI,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC;IAClF,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,MAAM,6BAA6B,YAAY,EAAE,CAAC,CAAC;IAEpF,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACtD,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QACtF,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3F,CAAC;AACH,CAAC,CAAC,CAAC,CAAC"}
|