@sixfactors-ai/codeloop 0.1.0 → 0.2.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/README.md +134 -72
- 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/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/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/search.d.ts +2 -0
- package/dist/commands/search.js +85 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/status.d.ts +1 -0
- package/dist/commands/status.js +85 -11
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/update.js +10 -22
- package/dist/commands/update.js.map +1 -1
- 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/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/scaffold.test.js +24 -0
- package/dist/lib/__tests__/scaffold.test.js.map +1 -1
- package/dist/lib/__tests__/smoke.test.js +41 -3
- package/dist/lib/__tests__/smoke.test.js.map +1 -1
- package/dist/lib/__tests__/validate-config.test.d.ts +1 -0
- package/dist/lib/__tests__/validate-config.test.js +109 -0
- package/dist/lib/__tests__/validate-config.test.js.map +1 -0
- package/dist/lib/scaffold.js +32 -3
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/registry/__tests__/installer.test.d.ts +1 -0
- package/dist/registry/__tests__/installer.test.js +122 -0
- package/dist/registry/__tests__/installer.test.js.map +1 -0
- package/dist/registry/__tests__/local-index.test.d.ts +1 -0
- package/dist/registry/__tests__/local-index.test.js +73 -0
- package/dist/registry/__tests__/local-index.test.js.map +1 -0
- package/dist/registry/__tests__/lockfile.test.d.ts +1 -0
- package/dist/registry/__tests__/lockfile.test.js +93 -0
- package/dist/registry/__tests__/lockfile.test.js.map +1 -0
- package/dist/registry/__tests__/security.test.d.ts +1 -0
- package/dist/registry/__tests__/security.test.js +100 -0
- package/dist/registry/__tests__/security.test.js.map +1 -0
- package/dist/registry/__tests__/skill-schema.test.d.ts +1 -0
- package/dist/registry/__tests__/skill-schema.test.js +102 -0
- package/dist/registry/__tests__/skill-schema.test.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 -1
- package/dist/ui/index.html +1 -1
- package/dist/ui/index.txt +1 -1
- package/dist/watch/__tests__/config.test.d.ts +1 -0
- package/dist/watch/__tests__/config.test.js +53 -0
- package/dist/watch/__tests__/config.test.js.map +1 -0
- package/dist/watch/__tests__/signals.test.d.ts +1 -0
- package/dist/watch/__tests__/signals.test.js +41 -0
- package/dist/watch/__tests__/signals.test.js.map +1 -0
- package/dist/watch/__tests__/triggers.test.d.ts +1 -0
- package/dist/watch/__tests__/triggers.test.js +92 -0
- package/dist/watch/__tests__/triggers.test.js.map +1 -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 +3 -2
- package/registry/index.json +106 -0
- package/starters/generic.yaml +37 -0
- package/starters/go.yaml +39 -0
- package/starters/node-typescript.yaml +39 -0
- package/starters/python.yaml +42 -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 +1 -1
- package/templates/commands/plan.md +4 -3
- package/templates/commands/qa.md +155 -0
- package/templates/commands/ship.md +187 -0
- package/templates/commands/test.md +133 -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/dist/ui/_next/static/{XkK-IaWE1h2_WYJHhUKNa → Z7X6LpFN441Kvx1ZYF2iY}/_buildManifest.js +0 -0
- /package/dist/ui/_next/static/{XkK-IaWE1h2_WYJHhUKNa → Z7X6LpFN441Kvx1ZYF2iY}/_ssgManifest.js +0 -0
package/README.md
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
# codeloop
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**The full dev lifecycle for AI coding agents.**
|
|
4
4
|
|
|
5
|
-
Your AI agent plans the work,
|
|
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
6
|
|
|
7
|
-

|
|
10
8
|
|
|
11
9
|
## The Problem
|
|
12
10
|
|
|
13
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.
|
|
14
12
|
|
|
15
|
-
|
|
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.
|
|
16
14
|
|
|
17
|
-
## The
|
|
15
|
+
## The Pipeline
|
|
18
16
|
|
|
19
|
-
codeloop
|
|
17
|
+
codeloop gives your project ten slash commands that cover the full development lifecycle:
|
|
20
18
|
|
|
21
19
|
```
|
|
22
|
-
|
|
23
|
-
↑ |
|
|
24
|
-
└─────────────────────────┘
|
|
25
|
-
lessons feed back in
|
|
20
|
+
/design → /plan → /manage → /test → /commit → /qa → /deploy → /debug → /reflect → /ship
|
|
26
21
|
```
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
37
|
|
|
38
38
|
## How Knowledge Compounds
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
Every gotcha has a frequency counter:
|
|
41
41
|
|
|
42
42
|
```
|
|
43
43
|
Session 1: You discover that boolean query params need Transform decorators.
|
|
@@ -56,7 +56,7 @@ Session 20: [freq:10+]
|
|
|
56
56
|
|
|
57
57
|
**Frequency = severity.** The more something bites you, the harder the system fights to prevent it. No configuration needed — it emerges from use.
|
|
58
58
|
|
|
59
|
-
The review
|
|
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
60
|
|
|
61
61
|
```yaml
|
|
62
62
|
scopes:
|
|
@@ -68,10 +68,10 @@ scopes:
|
|
|
68
68
|
gotcha_sections: ["Frontend", "React"]
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
##
|
|
71
|
+
## Quick Start
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
npm install -g codeloop
|
|
74
|
+
npm install -g @sixfactors-ai/codeloop
|
|
75
75
|
cd your-project
|
|
76
76
|
codeloop init
|
|
77
77
|
```
|
|
@@ -80,43 +80,45 @@ It asks which AI tools you use, detects your tech stack, and scaffolds:
|
|
|
80
80
|
|
|
81
81
|
```
|
|
82
82
|
.codeloop/
|
|
83
|
-
config.yaml ← Scopes, quality checks,
|
|
84
|
-
rules.md ← Non-negotiable rules (always CRITICAL)
|
|
83
|
+
config.yaml ← Scopes, quality checks, deploy/test/debug config
|
|
84
|
+
rules.md ← Non-negotiable rules (always CRITICAL in review)
|
|
85
85
|
gotchas.md ← Discovered gotchas with frequency tracking
|
|
86
86
|
patterns.md ← Proven patterns with confidence levels
|
|
87
|
-
principles.md ←
|
|
87
|
+
principles.md ← How you want the AI to operate
|
|
88
88
|
|
|
89
|
-
.claude/commands/ ←
|
|
90
|
-
.cursor/commands/ ←
|
|
91
|
-
.agents/skills/ ←
|
|
89
|
+
.claude/commands/ ← 10 slash commands (Claude Code)
|
|
90
|
+
.cursor/commands/ ← 10 slash commands (Cursor)
|
|
91
|
+
.agents/skills/ ← 10 skills (Codex)
|
|
92
92
|
|
|
93
93
|
tasks/todo.md ← Current task plan
|
|
94
94
|
```
|
|
95
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
|
|
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
97
|
|
|
98
98
|
## The Config
|
|
99
99
|
|
|
100
|
-
`.codeloop/config.yaml`
|
|
100
|
+
`.codeloop/config.yaml` controls everything. The AI reads it directly.
|
|
101
101
|
|
|
102
102
|
```yaml
|
|
103
103
|
project:
|
|
104
104
|
name: "my-api"
|
|
105
105
|
|
|
106
|
+
# Map file paths to knowledge sections
|
|
106
107
|
scopes:
|
|
107
108
|
backend:
|
|
108
109
|
paths: ["src/**"]
|
|
109
110
|
gotcha_sections: ["Backend", "Database", "API"]
|
|
110
|
-
pattern_sections: ["Backend", "Error Handling"]
|
|
111
111
|
tests:
|
|
112
|
-
paths: ["**/*.test.*"
|
|
112
|
+
paths: ["**/*.test.*"]
|
|
113
113
|
gotcha_sections: ["Testing"]
|
|
114
114
|
|
|
115
|
+
# Build/lint checks run during /commit and /qa
|
|
115
116
|
quality_checks:
|
|
116
117
|
backend:
|
|
117
118
|
- name: "Typecheck"
|
|
118
119
|
command: "npx tsc --noEmit 2>&1 | tail -20"
|
|
119
120
|
|
|
121
|
+
# Patterns banned in diffs
|
|
120
122
|
diff_scan:
|
|
121
123
|
- pattern: "console\\.log"
|
|
122
124
|
files: "*.ts,*.js"
|
|
@@ -124,27 +126,42 @@ diff_scan:
|
|
|
124
126
|
severity: CRITICAL
|
|
125
127
|
message: "console.log in production code"
|
|
126
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
|
|
127
151
|
codeloop:
|
|
128
152
|
critical_frequency: 3
|
|
129
153
|
promote_frequency: 10
|
|
130
154
|
```
|
|
131
155
|
|
|
132
|
-
**Scopes** connect file paths to knowledge sections — so `/commit` only loads relevant rubrics.
|
|
133
|
-
|
|
134
|
-
**Quality checks** run build/lint/type commands and report failures as CRITICAL.
|
|
135
|
-
|
|
136
|
-
**Diff scan** searches the actual diff for patterns you've banned (debug statements, .env files, explicit `any` types).
|
|
137
|
-
|
|
138
156
|
## The Commit Flow
|
|
139
157
|
|
|
140
|
-
When you type `/commit
|
|
158
|
+
When you type `/commit`:
|
|
141
159
|
|
|
142
160
|
```
|
|
143
161
|
Phase 1: Review
|
|
144
|
-
├─ Map changed files → scopes
|
|
145
|
-
├─ Load gotchas
|
|
146
|
-
├─ Load patterns (HIGH confidence = expected
|
|
147
|
-
├─ Load rules (always CRITICAL)
|
|
162
|
+
├─ Map changed files → scopes
|
|
163
|
+
├─ Load gotchas (freq ≥ 3 = CRITICAL, 1-2 = WARNING)
|
|
164
|
+
├─ Load patterns (HIGH confidence = expected)
|
|
148
165
|
├─ Run quality checks for active scopes
|
|
149
166
|
├─ Scan diff for violations
|
|
150
167
|
└─ Verdict: CLEAN / WARNINGS / BLOCKED
|
|
@@ -152,7 +169,7 @@ Phase 1: Review
|
|
|
152
169
|
Phase 2: Reflect (lightweight)
|
|
153
170
|
├─ Scan session for new gotchas or patterns
|
|
154
171
|
├─ Propose saves (you pick what to keep)
|
|
155
|
-
└─ Write to
|
|
172
|
+
└─ Write to gotchas.md or patterns.md
|
|
156
173
|
|
|
157
174
|
Phase 3: Commit
|
|
158
175
|
├─ Stage files
|
|
@@ -160,11 +177,49 @@ Phase 3: Commit
|
|
|
160
177
|
└─ Create commit
|
|
161
178
|
```
|
|
162
179
|
|
|
163
|
-
If the review finds CRITICAL issues, it blocks. You can fix them, override, or abort.
|
|
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
|
+
## Watch Mode
|
|
195
|
+
|
|
196
|
+
Monitor your project in the background:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
codeloop watch # Start watching
|
|
200
|
+
codeloop watch --with-serve # Watch + board server (live UI)
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
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.
|
|
204
|
+
|
|
205
|
+
## Skill Registry
|
|
206
|
+
|
|
207
|
+
Install community skills or share your own:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
codeloop search "deploy" # Find skills
|
|
211
|
+
codeloop install review-checklist # Install from registry
|
|
212
|
+
codeloop install github:user/repo # Install from GitHub
|
|
213
|
+
codeloop install ./local-skill # Install from local path
|
|
214
|
+
codeloop list # Show installed skills
|
|
215
|
+
codeloop remove review-checklist # Uninstall
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Every installed skill gets security-validated (no `exec()`, no credential access, no pipe-to-shell) and locked with integrity hashes in `.codeloop/skills.lock`.
|
|
164
219
|
|
|
165
220
|
## Works With Everything
|
|
166
221
|
|
|
167
|
-
codeloop auto-detects your stack and
|
|
222
|
+
codeloop auto-detects your stack and tools:
|
|
168
223
|
|
|
169
224
|
| Stack | Detected by | Starter config |
|
|
170
225
|
|-------|-------------|----------------|
|
|
@@ -173,41 +228,48 @@ codeloop auto-detects your stack and your tools:
|
|
|
173
228
|
| Go | `go.mod` | go vet, go build, fmt.Print detection |
|
|
174
229
|
| Generic | Fallback | Minimal — you configure |
|
|
175
230
|
|
|
176
|
-
| Tool | Commands
|
|
177
|
-
|
|
178
|
-
| Claude Code | `.claude/commands/` |
|
|
179
|
-
| Cursor | `.cursor/commands/` |
|
|
180
|
-
| Codex | `.agents/skills/` |
|
|
231
|
+
| Tool | Commands installed to | Compatibility |
|
|
232
|
+
|------|---------------------|---------------|
|
|
233
|
+
| Claude Code | `.claude/commands/` | Full (primary target) |
|
|
234
|
+
| Cursor | `.cursor/commands/` | Knowledge + config (tool hints are Claude-specific) |
|
|
235
|
+
| Codex | `.agents/skills/` | Knowledge + config (tool hints are Claude-specific) |
|
|
181
236
|
|
|
182
|
-
|
|
237
|
+
**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.
|
|
183
238
|
|
|
184
|
-
|
|
185
|
-
codeloop init # Interactive setup
|
|
186
|
-
codeloop init --tools claude,cursor # Skip tool prompt
|
|
187
|
-
codeloop init --starter python # Force specific stack
|
|
239
|
+
## CLI Reference
|
|
188
240
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
codeloop
|
|
241
|
+
```bash
|
|
242
|
+
# Project setup
|
|
243
|
+
codeloop init # Interactive setup
|
|
244
|
+
codeloop init --tools claude,cursor # Skip tool prompt
|
|
245
|
+
codeloop init --starter python # Force specific stack
|
|
246
|
+
codeloop status # Knowledge stats, version check
|
|
247
|
+
codeloop update # Update skills (never touches knowledge)
|
|
248
|
+
|
|
249
|
+
# Live monitoring
|
|
250
|
+
codeloop watch # Background file + git monitor
|
|
251
|
+
codeloop serve # Board UI server (http://localhost:4242)
|
|
252
|
+
|
|
253
|
+
# Skill registry
|
|
254
|
+
codeloop search <query> # Search for skills
|
|
255
|
+
codeloop install <name> # Install a skill
|
|
256
|
+
codeloop list # Show installed skills
|
|
257
|
+
codeloop remove <name> # Uninstall a skill
|
|
258
|
+
codeloop publish # Publish your skill to the registry
|
|
259
|
+
codeloop login # Authenticate with GitHub
|
|
192
260
|
```
|
|
193
261
|
|
|
194
|
-
`init` never overwrites existing knowledge files. Your gotchas and patterns are sacred.
|
|
195
|
-
|
|
196
|
-
`update` refreshes the slash commands to the latest version (version-tagged with `<!-- codeloop-version: X.Y.Z -->`). Knowledge files are never touched.
|
|
197
|
-
|
|
198
262
|
## The Knowledge Files
|
|
199
263
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
**`rules.md`** — Non-negotiable. Always loaded as CRITICAL. Start with 4 universal rules, add yours.
|
|
264
|
+
**`rules.md`** — Non-negotiable. Always loaded as CRITICAL. Start with universal rules, add yours.
|
|
203
265
|
|
|
204
|
-
**`gotchas.md`** — Discovered through work. Each entry has `[freq:N]`.
|
|
266
|
+
**`gotchas.md`** — Discovered through work. Each entry has `[freq:N]`. Severity auto-scales with frequency. Organized by sections matching your scopes.
|
|
205
267
|
|
|
206
268
|
**`patterns.md`** — What works well. HIGH-confidence patterns become expectations — deviations trigger warnings during review.
|
|
207
269
|
|
|
208
|
-
**`principles.md`** — How you want the AI to operate. Plan first? Verify before done?
|
|
270
|
+
**`principles.md`** — How you want the AI to operate. Plan first? Verify before done? Write it here once, it applies everywhere.
|
|
209
271
|
|
|
210
|
-
All
|
|
272
|
+
All plain markdown. No lock-in, no proprietary format. If you stop using codeloop tomorrow, the knowledge stays as useful documentation.
|
|
211
273
|
|
|
212
274
|
## License
|
|
213
275
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { installFromLocal, installFromContent, installBuiltin } from '../registry/installer.js';
|
|
4
|
+
import { findInLocalIndex, loadLocalIndex } from '../registry/local-index.js';
|
|
5
|
+
const REGISTRY_URL = process.env.CODELOOP_REGISTRY_URL || 'https://skills.codeloop.dev';
|
|
6
|
+
export const installCommand = new Command('install')
|
|
7
|
+
.description('Install a skill from the registry, GitHub, or local path')
|
|
8
|
+
.argument('<source>', 'Skill name, github:user/repo/path, or local path')
|
|
9
|
+
.action(async (source) => {
|
|
10
|
+
const projectDir = process.cwd();
|
|
11
|
+
console.log();
|
|
12
|
+
// Determine install source
|
|
13
|
+
if (source.startsWith('./') || source.startsWith('/') || source.startsWith('../')) {
|
|
14
|
+
// Local path install
|
|
15
|
+
console.log(chalk.dim(` Installing from local path: ${source}`));
|
|
16
|
+
const result = installFromLocal(projectDir, source);
|
|
17
|
+
if (!result.success) {
|
|
18
|
+
console.log(chalk.red(` Failed: ${result.error}`));
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
console.log(chalk.green(` Installed ${result.name}@${result.version}`));
|
|
22
|
+
for (const file of result.files) {
|
|
23
|
+
console.log(chalk.dim(` → ${file}`));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else if (source.startsWith('github:')) {
|
|
27
|
+
// GitHub install
|
|
28
|
+
const githubPath = source.slice(7); // Remove "github:"
|
|
29
|
+
console.log(chalk.dim(` Installing from GitHub: ${githubPath}`));
|
|
30
|
+
try {
|
|
31
|
+
// Fetch from GitHub raw content
|
|
32
|
+
const [owner, repo, ...pathParts] = githubPath.split('/');
|
|
33
|
+
const filePath = pathParts.length > 0 ? pathParts.join('/') : 'SKILL.md';
|
|
34
|
+
const url = `https://raw.githubusercontent.com/${owner}/${repo}/main/${filePath}`;
|
|
35
|
+
const res = await fetch(url);
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
// Try HEAD branch
|
|
38
|
+
const headUrl = `https://raw.githubusercontent.com/${owner}/${repo}/HEAD/${filePath}`;
|
|
39
|
+
const headRes = await fetch(headUrl);
|
|
40
|
+
if (!headRes.ok) {
|
|
41
|
+
console.log(chalk.red(` Failed to fetch: ${url} (${res.status})`));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
const content = await headRes.text();
|
|
45
|
+
const result = installFromContent(projectDir, content, `github:${githubPath}`, 'community');
|
|
46
|
+
logResult(result);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const content = await res.text();
|
|
50
|
+
const result = installFromContent(projectDir, content, `github:${githubPath}`, 'community');
|
|
51
|
+
logResult(result);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.log(chalk.red(` Failed: ${error.message}`));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Registry install (by name)
|
|
60
|
+
console.log(chalk.dim(` Looking up: ${source}`));
|
|
61
|
+
// 1. Check local index first
|
|
62
|
+
const localIndex = loadLocalIndex();
|
|
63
|
+
const localEntry = findInLocalIndex(localIndex, source);
|
|
64
|
+
if (localEntry && localEntry.source === 'builtin') {
|
|
65
|
+
// Install from built-in templates
|
|
66
|
+
const result = installBuiltin(projectDir, source);
|
|
67
|
+
logResult(result);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// 2. Try registry API
|
|
71
|
+
try {
|
|
72
|
+
const res = await fetch(`${REGISTRY_URL}/api/skills/${source}`);
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
if (res.status === 404) {
|
|
75
|
+
console.log(chalk.red(` Skill "${source}" not found in registry.`));
|
|
76
|
+
console.log(chalk.dim(` Try: codeloop search "${source}"`));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
console.log(chalk.red(` Registry error: ${res.status}`));
|
|
80
|
+
}
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
const data = await res.json();
|
|
84
|
+
const latestVersion = data.versions?.find((v) => v.dist_tag === 'latest') || data.versions?.[0];
|
|
85
|
+
if (!latestVersion?.artifact_url) {
|
|
86
|
+
console.log(chalk.red(` No downloadable version found for "${source}"`));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
// Download artifact
|
|
90
|
+
const artifactRes = await fetch(latestVersion.artifact_url);
|
|
91
|
+
if (!artifactRes.ok) {
|
|
92
|
+
console.log(chalk.red(` Failed to download artifact: ${artifactRes.status}`));
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
const content = await artifactRes.text();
|
|
96
|
+
const tier = data.skill?.tier || 'community';
|
|
97
|
+
const result = installFromContent(projectDir, content, `registry:${source}`, tier);
|
|
98
|
+
logResult(result);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.log(chalk.red(` Failed to connect to registry: ${error.message}`));
|
|
102
|
+
// Fallback: check if it's a builtin name
|
|
103
|
+
if (localEntry) {
|
|
104
|
+
console.log(chalk.yellow(` Falling back to local index...`));
|
|
105
|
+
const result = installBuiltin(projectDir, source);
|
|
106
|
+
logResult(result);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
console.log();
|
|
114
|
+
});
|
|
115
|
+
function logResult(result) {
|
|
116
|
+
if (!result.success) {
|
|
117
|
+
console.log(chalk.red(` Failed: ${result.error}`));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
console.log(chalk.green(` Installed ${result.name}@${result.version}`));
|
|
121
|
+
for (const file of result.files) {
|
|
122
|
+
console.log(chalk.dim(` → ${file}`));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { loadLockfile } from '../registry/lockfile.js';
|
|
4
|
+
export const listCommand = new Command('list')
|
|
5
|
+
.description('Show installed skills')
|
|
6
|
+
.action(() => {
|
|
7
|
+
const projectDir = process.cwd();
|
|
8
|
+
const lockfile = loadLockfile(projectDir);
|
|
9
|
+
console.log();
|
|
10
|
+
const names = Object.keys(lockfile.installed);
|
|
11
|
+
if (names.length === 0) {
|
|
12
|
+
console.log(chalk.dim(' No skills installed via registry.'));
|
|
13
|
+
console.log(chalk.dim(' Built-in skills are managed by `codeloop init` and `codeloop update`.'));
|
|
14
|
+
console.log();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
console.log(chalk.bold(' Installed Skills'));
|
|
18
|
+
console.log();
|
|
19
|
+
for (const name of names.sort()) {
|
|
20
|
+
const entry = lockfile.installed[name];
|
|
21
|
+
const tierBadge = entry.tier === 'trusted'
|
|
22
|
+
? chalk.green('trusted')
|
|
23
|
+
: entry.tier === 'community'
|
|
24
|
+
? chalk.cyan('community')
|
|
25
|
+
: chalk.yellow('unreviewed');
|
|
26
|
+
console.log(` ${chalk.bold(name)} ${chalk.dim(`v${entry.version}`)} ${tierBadge}`);
|
|
27
|
+
console.log(` ${chalk.dim(`source: ${entry.source}`)}`);
|
|
28
|
+
console.log(` ${chalk.dim(`installed: ${entry.installed}`)}`);
|
|
29
|
+
for (const file of entry.files) {
|
|
30
|
+
console.log(` ${chalk.dim(` → ${file}`)}`);
|
|
31
|
+
}
|
|
32
|
+
console.log();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,uBAAuB,CAAC;KACpC,MAAM,CAAC,GAAG,EAAE;IACX,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAE1C,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,yEAAyE,CAAC,CAAC,CAAC;QAClG,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,EAAE,CAAC;IAEd,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS;YACxC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC;YACxB,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW;gBAC1B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC;gBACzB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAEjC,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC,CAAC;QACpF,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,cAAc,KAAK,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/D,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
const TOKEN_PATH = join(process.env.HOME || '~', '.codeloop', 'auth.json');
|
|
6
|
+
export const loginCommand = new Command('login')
|
|
7
|
+
.description('Authenticate with the skill registry (check status with --status)')
|
|
8
|
+
.option('--token <token>', 'GitHub personal access token')
|
|
9
|
+
.option('--status', 'Check current auth status')
|
|
10
|
+
.action(async (options) => {
|
|
11
|
+
console.log();
|
|
12
|
+
if (options.status) {
|
|
13
|
+
if (!existsSync(TOKEN_PATH)) {
|
|
14
|
+
console.log(chalk.dim(' Not authenticated'));
|
|
15
|
+
console.log(chalk.dim(' Run `codeloop login --token <github-pat>` to authenticate'));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
try {
|
|
19
|
+
const auth = JSON.parse(readFileSync(TOKEN_PATH, 'utf-8'));
|
|
20
|
+
console.log(chalk.green(` Authenticated as: ${auth.username || 'unknown'}`));
|
|
21
|
+
console.log(chalk.dim(` Token stored at: ${TOKEN_PATH}`));
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
console.log(chalk.yellow(' Auth file exists but is invalid'));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
console.log();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!options.token) {
|
|
31
|
+
console.log(chalk.bold(' GitHub Authentication'));
|
|
32
|
+
console.log();
|
|
33
|
+
console.log(' Create a GitHub Personal Access Token at:');
|
|
34
|
+
console.log(chalk.cyan(' https://github.com/settings/tokens/new'));
|
|
35
|
+
console.log();
|
|
36
|
+
console.log(' Required scopes: (none — public read access is sufficient)');
|
|
37
|
+
console.log();
|
|
38
|
+
console.log(' Then run:');
|
|
39
|
+
console.log(chalk.dim(' codeloop login --token ghp_xxxx'));
|
|
40
|
+
console.log();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Verify the token
|
|
44
|
+
console.log(chalk.dim(' Verifying token...'));
|
|
45
|
+
try {
|
|
46
|
+
const res = await fetch('https://api.github.com/user', {
|
|
47
|
+
headers: {
|
|
48
|
+
Authorization: `Bearer ${options.token}`,
|
|
49
|
+
Accept: 'application/json',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
if (!res.ok) {
|
|
53
|
+
console.log(chalk.red(' Invalid token'));
|
|
54
|
+
console.log();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const user = await res.json();
|
|
58
|
+
// Save token
|
|
59
|
+
const authDir = dirname(TOKEN_PATH);
|
|
60
|
+
if (!existsSync(authDir)) {
|
|
61
|
+
mkdirSync(authDir, { recursive: true });
|
|
62
|
+
}
|
|
63
|
+
writeFileSync(TOKEN_PATH, JSON.stringify({
|
|
64
|
+
token: options.token,
|
|
65
|
+
username: user.login,
|
|
66
|
+
github_id: String(user.id),
|
|
67
|
+
authenticated_at: new Date().toISOString(),
|
|
68
|
+
}, null, 2), 'utf-8');
|
|
69
|
+
console.log(chalk.green(` Authenticated as ${user.login}`));
|
|
70
|
+
console.log(chalk.dim(` Token stored at: ${TOKEN_PATH}`));
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
console.log(chalk.red(` Failed to verify token: ${error.message}`));
|
|
74
|
+
}
|
|
75
|
+
console.log();
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|