@sixfactors-ai/codeloop 0.1.1 → 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.
Files changed (119) hide show
  1. package/README.md +133 -71
  2. package/dist/commands/install.d.ts +2 -0
  3. package/dist/commands/install.js +125 -0
  4. package/dist/commands/install.js.map +1 -0
  5. package/dist/commands/list.d.ts +2 -0
  6. package/dist/commands/list.js +35 -0
  7. package/dist/commands/list.js.map +1 -0
  8. package/dist/commands/login.d.ts +2 -0
  9. package/dist/commands/login.js +77 -0
  10. package/dist/commands/login.js.map +1 -0
  11. package/dist/commands/publish.d.ts +2 -0
  12. package/dist/commands/publish.js +125 -0
  13. package/dist/commands/publish.js.map +1 -0
  14. package/dist/commands/remove.d.ts +2 -0
  15. package/dist/commands/remove.js +31 -0
  16. package/dist/commands/remove.js.map +1 -0
  17. package/dist/commands/search.d.ts +2 -0
  18. package/dist/commands/search.js +85 -0
  19. package/dist/commands/search.js.map +1 -0
  20. package/dist/commands/status.d.ts +1 -0
  21. package/dist/commands/status.js +85 -11
  22. package/dist/commands/status.js.map +1 -1
  23. package/dist/commands/update.js +10 -22
  24. package/dist/commands/update.js.map +1 -1
  25. package/dist/commands/watch.d.ts +6 -0
  26. package/dist/commands/watch.js +111 -0
  27. package/dist/commands/watch.js.map +1 -0
  28. package/dist/index.js +17 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/lib/__tests__/scaffold.test.js +24 -0
  31. package/dist/lib/__tests__/scaffold.test.js.map +1 -1
  32. package/dist/lib/__tests__/smoke.test.js +41 -3
  33. package/dist/lib/__tests__/smoke.test.js.map +1 -1
  34. package/dist/lib/__tests__/validate-config.test.d.ts +1 -0
  35. package/dist/lib/__tests__/validate-config.test.js +109 -0
  36. package/dist/lib/__tests__/validate-config.test.js.map +1 -0
  37. package/dist/lib/scaffold.js +32 -3
  38. package/dist/lib/scaffold.js.map +1 -1
  39. package/dist/registry/__tests__/installer.test.d.ts +1 -0
  40. package/dist/registry/__tests__/installer.test.js +122 -0
  41. package/dist/registry/__tests__/installer.test.js.map +1 -0
  42. package/dist/registry/__tests__/local-index.test.d.ts +1 -0
  43. package/dist/registry/__tests__/local-index.test.js +73 -0
  44. package/dist/registry/__tests__/local-index.test.js.map +1 -0
  45. package/dist/registry/__tests__/lockfile.test.d.ts +1 -0
  46. package/dist/registry/__tests__/lockfile.test.js +93 -0
  47. package/dist/registry/__tests__/lockfile.test.js.map +1 -0
  48. package/dist/registry/__tests__/security.test.d.ts +1 -0
  49. package/dist/registry/__tests__/security.test.js +100 -0
  50. package/dist/registry/__tests__/security.test.js.map +1 -0
  51. package/dist/registry/__tests__/skill-schema.test.d.ts +1 -0
  52. package/dist/registry/__tests__/skill-schema.test.js +102 -0
  53. package/dist/registry/__tests__/skill-schema.test.js.map +1 -0
  54. package/dist/registry/index.d.ts +7 -0
  55. package/dist/registry/index.js +8 -0
  56. package/dist/registry/index.js.map +1 -0
  57. package/dist/registry/installer.d.ts +30 -0
  58. package/dist/registry/installer.js +133 -0
  59. package/dist/registry/installer.js.map +1 -0
  60. package/dist/registry/local-index.d.ts +32 -0
  61. package/dist/registry/local-index.js +58 -0
  62. package/dist/registry/local-index.js.map +1 -0
  63. package/dist/registry/lockfile.d.ts +40 -0
  64. package/dist/registry/lockfile.js +85 -0
  65. package/dist/registry/lockfile.js.map +1 -0
  66. package/dist/registry/security.d.ts +25 -0
  67. package/dist/registry/security.js +100 -0
  68. package/dist/registry/security.js.map +1 -0
  69. package/dist/registry/skill-schema.d.ts +30 -0
  70. package/dist/registry/skill-schema.js +95 -0
  71. package/dist/registry/skill-schema.js.map +1 -0
  72. package/dist/ui/404.html +1 -1
  73. package/dist/ui/index.html +1 -1
  74. package/dist/ui/index.txt +1 -1
  75. package/dist/watch/__tests__/config.test.d.ts +1 -0
  76. package/dist/watch/__tests__/config.test.js +53 -0
  77. package/dist/watch/__tests__/config.test.js.map +1 -0
  78. package/dist/watch/__tests__/signals.test.d.ts +1 -0
  79. package/dist/watch/__tests__/signals.test.js +41 -0
  80. package/dist/watch/__tests__/signals.test.js.map +1 -0
  81. package/dist/watch/__tests__/triggers.test.d.ts +1 -0
  82. package/dist/watch/__tests__/triggers.test.js +92 -0
  83. package/dist/watch/__tests__/triggers.test.js.map +1 -0
  84. package/dist/watch/index.d.ts +21 -0
  85. package/dist/watch/index.js +88 -0
  86. package/dist/watch/index.js.map +1 -0
  87. package/dist/watch/reporter.d.ts +11 -0
  88. package/dist/watch/reporter.js +44 -0
  89. package/dist/watch/reporter.js.map +1 -0
  90. package/dist/watch/signals.d.ts +38 -0
  91. package/dist/watch/signals.js +119 -0
  92. package/dist/watch/signals.js.map +1 -0
  93. package/dist/watch/triggers.d.ts +10 -0
  94. package/dist/watch/triggers.js +67 -0
  95. package/dist/watch/triggers.js.map +1 -0
  96. package/package.json +3 -2
  97. package/registry/index.json +106 -0
  98. package/starters/generic.yaml +37 -0
  99. package/starters/go.yaml +39 -0
  100. package/starters/node-typescript.yaml +39 -0
  101. package/starters/python.yaml +42 -0
  102. package/templates/commands/debug.md +142 -0
  103. package/templates/commands/deploy.md +144 -0
  104. package/templates/commands/design.md +102 -0
  105. package/templates/commands/manage.md +1 -1
  106. package/templates/commands/plan.md +4 -3
  107. package/templates/commands/qa.md +155 -0
  108. package/templates/commands/ship.md +187 -0
  109. package/templates/commands/test.md +133 -0
  110. package/templates/seeds/go-gotchas.md +28 -0
  111. package/templates/seeds/go-patterns.md +22 -0
  112. package/templates/seeds/node-typescript-gotchas.md +30 -0
  113. package/templates/seeds/node-typescript-patterns.md +27 -0
  114. package/templates/seeds/python-gotchas.md +30 -0
  115. package/templates/seeds/python-patterns.md +19 -0
  116. package/templates/seeds/universal-gotchas.md +11 -0
  117. package/templates/seeds/universal-patterns.md +11 -0
  118. /package/dist/ui/_next/static/{uiiPJR68HihKQsXtPj0fm → Z7X6LpFN441Kvx1ZYF2iY}/_buildManifest.js +0 -0
  119. /package/dist/ui/_next/static/{uiiPJR68HihKQsXtPj0fm → Z7X6LpFN441Kvx1ZYF2iY}/_ssgManifest.js +0 -0
package/README.md CHANGED
@@ -1,43 +1,43 @@
1
1
  # codeloop
2
2
 
3
- **Code agents that project manage themselves.**
3
+ **The full dev lifecycle for AI coding agents.**
4
4
 
5
- Your AI agent plans the work, tracks its own tasks, and learns from every mistake — across sessions, across tools, without you babysitting it.
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
7
  ![Codeloop Board](https://codeloop.sixfactors.ai/board.png)
8
8
 
9
- codeloop gives your project a memory that survives across sessions — and a live dashboard where you watch the agent think.
10
-
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
- Your team's hard-won knowledge the gotchas, the patterns, the "don't do that, here's why" lives in people's heads. Not where the AI can use it.
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 Loop
15
+ ## The Pipeline
18
16
 
19
- codeloop creates a closed feedback loop between you and your AI agent:
17
+ codeloop gives your project ten slash commands that cover the full development lifecycle:
20
18
 
21
19
  ```
22
- PlanBuildCommitReflect
23
- ↑ |
24
- └─────────────────────────┘
25
- lessons feed back in
20
+ /design/plan/manage/test → /commit → /qa → /deploy → /debug → /reflect → /ship
26
21
  ```
27
22
 
28
- Four slash commands. That's the entire interface.
29
-
30
- **`/plan`** reads your project's known gotchas before you start. "Last time we touched auth, we forgot to scope queries by workspace." The agent plans around landmines it hasn't personally stepped on yet.
31
-
32
- **`/commit`** does a three-phase commit: first it **reviews** your diff against learned rubrics (not just lint rules — *your team's actual mistakes*), then it **reflects** on what happened this session ("we discovered that collection names are inconsistent — save this?"), then it commits. One command, three layers of quality.
33
-
34
- **`/reflect`** is the deep version. End of a long session, multiple commits, hard-fought bugs. It scans everything that happened and proposes lessons to save. You pick what matters. It writes to your knowledge base.
35
-
36
- **`/manage`** tracks the plan. Check off steps, add new ones, get a summary of where things stand.
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
- Here's where it gets interesting. Every gotcha has a frequency counter:
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 isn't one-size-fits-all either. Changed a backend file? It loads backend gotchas. Frontend only? It skips database warnings entirely. Scopes in your config file control what's relevant:
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
- ## What Gets Created
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, diff scan rules
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 ← Operating principles for the AI agent
87
+ principles.md ← How you want the AI to operate
88
88
 
89
- .claude/commands/ ← Slash commands (Claude Code)
90
- .cursor/commands/ ← Slash commands (Cursor)
91
- .agents/skills/ ← Skills (Codex)
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 patterns, same rules.
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` is the brain. The AI reads it directly — no runtime, no server, just a YAML file the LLM parses.
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.*", "**/*.spec.*"]
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`, this happens:
158
+ When you type `/commit`:
141
159
 
142
160
  ```
143
161
  Phase 1: Review
144
- ├─ Map changed files → scopes (from config.yaml)
145
- ├─ Load gotchas for those scopes (freq ≥ 3 = CRITICAL, 1-2 = WARNING)
146
- ├─ Load patterns (HIGH confidence = expected, deviation = WARNING)
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 .codeloop/gotchas.md or patterns.md
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. No silent failures.
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 your tools:
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 go to | Format |
177
- |------|---------------|--------|
178
- | Claude Code | `.claude/commands/` | Markdown + frontmatter |
179
- | Cursor | `.cursor/commands/` | Markdown + frontmatter |
180
- | Codex | `.agents/skills/` | SKILL.md with YAML frontmatter |
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
- ## CLI
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
- ```bash
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
- codeloop status # Knowledge stats, version check
190
- codeloop update # Update skills (never touches knowledge)
191
- codeloop update --dry-run # Preview what would change
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
- These are the files that make your project smarter:
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]`. The system auto-promotes severity as frequency climbs. Organized by sections that match your scopes.
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? Subagents for research? Write it here once, it applies everywhere.
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 of these are plain markdown. No lock-in, no proprietary format. If you stop using codeloop tomorrow, the knowledge stays in your repo as useful documentation.
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,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const installCommand: Command;
@@ -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,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const listCommand: Command;
@@ -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,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const loginCommand: Command;
@@ -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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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare const publishCommand: Command;