opencodekit 0.16.15 → 0.16.18

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 (85) hide show
  1. package/README.md +77 -242
  2. package/dist/index.js +19 -6
  3. package/dist/template/.opencode/AGENTS.md +72 -236
  4. package/dist/template/.opencode/README.md +49 -482
  5. package/dist/template/.opencode/agent/build.md +71 -345
  6. package/dist/template/.opencode/agent/explore.md +47 -139
  7. package/dist/template/.opencode/agent/general.md +61 -172
  8. package/dist/template/.opencode/agent/looker.md +65 -161
  9. package/dist/template/.opencode/agent/painter.md +46 -200
  10. package/dist/template/.opencode/agent/plan.md +37 -220
  11. package/dist/template/.opencode/agent/review.md +72 -153
  12. package/dist/template/.opencode/agent/scout.md +44 -486
  13. package/dist/template/.opencode/agent/vision.md +63 -178
  14. package/dist/template/.opencode/command/create.md +75 -307
  15. package/dist/template/.opencode/command/design.md +53 -589
  16. package/dist/template/.opencode/command/handoff.md +76 -180
  17. package/dist/template/.opencode/command/init.md +45 -211
  18. package/dist/template/.opencode/command/plan.md +62 -514
  19. package/dist/template/.opencode/command/pr.md +56 -226
  20. package/dist/template/.opencode/command/research.md +55 -266
  21. package/dist/template/.opencode/command/resume.md +33 -138
  22. package/dist/template/.opencode/command/review-codebase.md +54 -202
  23. package/dist/template/.opencode/command/ship.md +78 -127
  24. package/dist/template/.opencode/command/start.md +47 -577
  25. package/dist/template/.opencode/command/status.md +60 -353
  26. package/dist/template/.opencode/command/ui-review.md +52 -298
  27. package/dist/template/.opencode/command/verify.md +36 -250
  28. package/dist/template/.opencode/memory.db-shm +0 -0
  29. package/dist/template/.opencode/memory.db-wal +0 -0
  30. package/dist/template/.opencode/opencode.json +133 -35
  31. package/dist/template/.opencode/plugin/README.md +40 -166
  32. package/dist/template/.opencode/plugin/compaction.ts +162 -131
  33. package/dist/template/.opencode/plugin/lib/memory-db.ts +112 -0
  34. package/dist/template/.opencode/plugin/swarm-enforcer.ts +182 -27
  35. package/dist/template/.opencode/skill/augment-context-engine/SKILL.md +112 -0
  36. package/dist/template/.opencode/skill/augment-context-engine/mcp.json +6 -0
  37. package/dist/template/.opencode/skill/core-data-expert/SKILL.md +82 -0
  38. package/dist/template/.opencode/skill/core-data-expert/references/batch-operations.md +543 -0
  39. package/dist/template/.opencode/skill/core-data-expert/references/cloudkit-integration.md +259 -0
  40. package/dist/template/.opencode/skill/core-data-expert/references/concurrency.md +522 -0
  41. package/dist/template/.opencode/skill/core-data-expert/references/fetch-requests.md +643 -0
  42. package/dist/template/.opencode/skill/core-data-expert/references/glossary.md +233 -0
  43. package/dist/template/.opencode/skill/core-data-expert/references/migration.md +393 -0
  44. package/dist/template/.opencode/skill/core-data-expert/references/model-configuration.md +597 -0
  45. package/dist/template/.opencode/skill/core-data-expert/references/performance.md +300 -0
  46. package/dist/template/.opencode/skill/core-data-expert/references/persistent-history.md +553 -0
  47. package/dist/template/.opencode/skill/core-data-expert/references/project-audit.md +60 -0
  48. package/dist/template/.opencode/skill/core-data-expert/references/saving.md +574 -0
  49. package/dist/template/.opencode/skill/core-data-expert/references/stack-setup.md +625 -0
  50. package/dist/template/.opencode/skill/core-data-expert/references/testing.md +300 -0
  51. package/dist/template/.opencode/skill/core-data-expert/references/threading.md +589 -0
  52. package/dist/template/.opencode/skill/swift-concurrency/SKILL.md +246 -0
  53. package/dist/template/.opencode/skill/swift-concurrency/references/actors.md +640 -0
  54. package/dist/template/.opencode/skill/swift-concurrency/references/async-algorithms.md +822 -0
  55. package/dist/template/.opencode/skill/swift-concurrency/references/async-await-basics.md +249 -0
  56. package/dist/template/.opencode/skill/swift-concurrency/references/async-sequences.md +670 -0
  57. package/dist/template/.opencode/skill/swift-concurrency/references/core-data.md +533 -0
  58. package/dist/template/.opencode/skill/swift-concurrency/references/glossary.md +128 -0
  59. package/dist/template/.opencode/skill/swift-concurrency/references/linting.md +142 -0
  60. package/dist/template/.opencode/skill/swift-concurrency/references/memory-management.md +542 -0
  61. package/dist/template/.opencode/skill/swift-concurrency/references/migration.md +1076 -0
  62. package/dist/template/.opencode/skill/swift-concurrency/references/performance.md +574 -0
  63. package/dist/template/.opencode/skill/swift-concurrency/references/sendable.md +578 -0
  64. package/dist/template/.opencode/skill/swift-concurrency/references/tasks.md +604 -0
  65. package/dist/template/.opencode/skill/swift-concurrency/references/testing.md +565 -0
  66. package/dist/template/.opencode/skill/swift-concurrency/references/threading.md +452 -0
  67. package/dist/template/.opencode/skill/swiftui-expert-skill/SKILL.md +290 -0
  68. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-advanced.md +351 -0
  69. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-basics.md +284 -0
  70. package/dist/template/.opencode/skill/swiftui-expert-skill/references/animation-transitions.md +326 -0
  71. package/dist/template/.opencode/skill/swiftui-expert-skill/references/image-optimization.md +286 -0
  72. package/dist/template/.opencode/skill/swiftui-expert-skill/references/layout-best-practices.md +312 -0
  73. package/dist/template/.opencode/skill/swiftui-expert-skill/references/liquid-glass.md +377 -0
  74. package/dist/template/.opencode/skill/swiftui-expert-skill/references/list-patterns.md +153 -0
  75. package/dist/template/.opencode/skill/swiftui-expert-skill/references/modern-apis.md +400 -0
  76. package/dist/template/.opencode/skill/swiftui-expert-skill/references/performance-patterns.md +377 -0
  77. package/dist/template/.opencode/skill/swiftui-expert-skill/references/scroll-patterns.md +305 -0
  78. package/dist/template/.opencode/skill/swiftui-expert-skill/references/sheet-navigation-patterns.md +292 -0
  79. package/dist/template/.opencode/skill/swiftui-expert-skill/references/state-management.md +447 -0
  80. package/dist/template/.opencode/skill/swiftui-expert-skill/references/text-formatting.md +285 -0
  81. package/dist/template/.opencode/skill/swiftui-expert-skill/references/view-structure.md +276 -0
  82. package/dist/template/.opencode/tool/action-queue.ts +308 -0
  83. package/dist/template/.opencode/tool/swarm.ts +65 -40
  84. package/package.json +16 -3
  85. package/dist/template/.opencode/.agents/skills/context7/SKILL.md +0 -88
@@ -0,0 +1,308 @@
1
+ import { execFile } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { promisify } from "node:util";
5
+ import { tool } from "@opencode-ai/plugin";
6
+ import {
7
+ type ActionQueueItemInput,
8
+ clearActionQueueItems,
9
+ listActionQueueItems,
10
+ replaceActionQueueItems,
11
+ } from "../plugin/lib/memory-db.js";
12
+
13
+ const execFileAsync = promisify(execFile);
14
+ const SWARM_PROGRESS_FILE = ".beads/swarm-progress.jsonl";
15
+
16
+ type QueueOperation = "status" | "refresh" | "clear";
17
+
18
+ interface QueueWorkerEntry {
19
+ timestamp?: string;
20
+ team_name?: string;
21
+ worker_id?: string;
22
+ phase?: string;
23
+ progress?: number;
24
+ status?: string;
25
+ file?: string;
26
+ }
27
+
28
+ interface QueueBeadTask {
29
+ id: string;
30
+ title: string;
31
+ status?: string;
32
+ priority?: number;
33
+ }
34
+
35
+ function parsePayload(payload: string | null): Record<string, unknown> {
36
+ if (!payload) return {};
37
+ try {
38
+ const parsed = JSON.parse(payload) as Record<string, unknown>;
39
+ return parsed;
40
+ } catch {
41
+ return {};
42
+ }
43
+ }
44
+
45
+ function buildSnapshot(
46
+ items: ActionQueueItemInput[] | ReturnType<typeof listActionQueueItems>,
47
+ ) {
48
+ const normalized = items.map((item) => ({
49
+ id: item.id,
50
+ source: item.source,
51
+ status: item.status,
52
+ title: item.title,
53
+ owner: item.owner ?? null,
54
+ payload:
55
+ "payload" in item && typeof item.payload === "string"
56
+ ? parsePayload(item.payload)
57
+ : (item.payload ?? {}),
58
+ }));
59
+
60
+ const pendingApprovals = normalized.filter(
61
+ (item) => item.source === "approval" && item.status === "pending",
62
+ );
63
+ const readyTasks = normalized.filter(
64
+ (item) => item.source === "bead" && item.status === "ready",
65
+ );
66
+ const idleWorkers = normalized.filter(
67
+ (item) => item.source === "worker" && item.status === "idle",
68
+ );
69
+
70
+ return {
71
+ generated_at: new Date().toISOString(),
72
+ pending_approvals: pendingApprovals,
73
+ ready_tasks: readyTasks,
74
+ idle_workers: idleWorkers,
75
+ counts: {
76
+ pending_approvals: pendingApprovals.length,
77
+ ready_tasks: readyTasks.length,
78
+ idle_workers: idleWorkers.length,
79
+ total: normalized.length,
80
+ },
81
+ };
82
+ }
83
+
84
+ async function readReadyTasks(worktree: string): Promise<QueueBeadTask[]> {
85
+ try {
86
+ const { stdout } = await execFileAsync("br", ["ready", "--json"], {
87
+ cwd: worktree,
88
+ timeout: 15000,
89
+ });
90
+ const parsed = JSON.parse(stdout) as QueueBeadTask[];
91
+ return Array.isArray(parsed) ? parsed : [];
92
+ } catch {
93
+ try {
94
+ const { stdout } = await execFileAsync("br", ["ready"], {
95
+ cwd: worktree,
96
+ timeout: 15000,
97
+ });
98
+ const tasks: QueueBeadTask[] = [];
99
+ for (const line of stdout.split("\n")) {
100
+ const match = line.match(
101
+ /^#?(\S+)\s+\[(\w+)\]\s+(?:\(P(\d)\))?\s*(.+)$/,
102
+ );
103
+ if (!match) continue;
104
+ tasks.push({
105
+ id: match[1],
106
+ status: match[2],
107
+ priority: match[3] ? Number.parseInt(match[3], 10) : 2,
108
+ title: match[4],
109
+ });
110
+ }
111
+ return tasks;
112
+ } catch {
113
+ return [];
114
+ }
115
+ }
116
+ }
117
+
118
+ async function readWorkerEntries(
119
+ worktree: string,
120
+ ): Promise<QueueWorkerEntry[]> {
121
+ const progressPath = path.join(worktree, SWARM_PROGRESS_FILE);
122
+ try {
123
+ const content = await fs.readFile(progressPath, "utf-8");
124
+ const entries = content
125
+ .trim()
126
+ .split("\n")
127
+ .filter(Boolean)
128
+ .map((line) => JSON.parse(line) as QueueWorkerEntry);
129
+
130
+ const latestByWorker = new Map<string, QueueWorkerEntry>();
131
+ for (const entry of entries) {
132
+ if (!entry.worker_id) continue;
133
+ const previous = latestByWorker.get(entry.worker_id);
134
+ if (!previous) {
135
+ latestByWorker.set(entry.worker_id, entry);
136
+ continue;
137
+ }
138
+
139
+ const currentEpoch = Date.parse(entry.timestamp || "");
140
+ const previousEpoch = Date.parse(previous.timestamp || "");
141
+ if (Number.isNaN(previousEpoch) || currentEpoch >= previousEpoch) {
142
+ latestByWorker.set(entry.worker_id, entry);
143
+ }
144
+ }
145
+
146
+ return Array.from(latestByWorker.values());
147
+ } catch {
148
+ return [];
149
+ }
150
+ }
151
+
152
+ function toQueueItems(
153
+ readyTasks: QueueBeadTask[],
154
+ workerEntries: QueueWorkerEntry[],
155
+ ): ActionQueueItemInput[] {
156
+ const items: ActionQueueItemInput[] = [];
157
+
158
+ for (const task of readyTasks) {
159
+ items.push({
160
+ id: `bead:${task.id}`,
161
+ source: "bead",
162
+ status: "ready",
163
+ title: task.title,
164
+ owner: task.id,
165
+ payload: {
166
+ bead_id: task.id,
167
+ priority: task.priority ?? null,
168
+ status: task.status ?? "ready",
169
+ },
170
+ });
171
+ }
172
+
173
+ for (const worker of workerEntries) {
174
+ const workerId = worker.worker_id || "unknown";
175
+ const status = (worker.status || "").toLowerCase();
176
+ const phase = (worker.phase || "").toLowerCase();
177
+ const needsApproval =
178
+ status.includes("approval") ||
179
+ status === "awaiting_approval" ||
180
+ status === "needs_approval" ||
181
+ phase.includes("approval");
182
+
183
+ if (status === "idle") {
184
+ items.push({
185
+ id: `worker:${workerId}`,
186
+ source: "worker",
187
+ status: "idle",
188
+ title: `Worker ${workerId} is idle`,
189
+ owner: workerId,
190
+ payload: {
191
+ phase: worker.phase || null,
192
+ progress: worker.progress ?? null,
193
+ file: worker.file || null,
194
+ timestamp: worker.timestamp || null,
195
+ },
196
+ });
197
+ }
198
+
199
+ if (needsApproval) {
200
+ items.push({
201
+ id: `approval:${workerId}`,
202
+ source: "approval",
203
+ status: "pending",
204
+ title: `Approval needed for worker ${workerId}`,
205
+ owner: workerId,
206
+ payload: {
207
+ phase: worker.phase || null,
208
+ status: worker.status || null,
209
+ progress: worker.progress ?? null,
210
+ file: worker.file || null,
211
+ timestamp: worker.timestamp || null,
212
+ },
213
+ });
214
+ }
215
+ }
216
+
217
+ return items;
218
+ }
219
+
220
+ async function refreshSnapshot(worktree: string) {
221
+ const [readyTasks, workerEntries] = await Promise.all([
222
+ readReadyTasks(worktree),
223
+ readWorkerEntries(worktree),
224
+ ]);
225
+
226
+ const items = toQueueItems(readyTasks, workerEntries);
227
+ replaceActionQueueItems(items);
228
+
229
+ return buildSnapshot(items);
230
+ }
231
+
232
+ export default tool({
233
+ description: `Unified action queue for operators.
234
+
235
+ Returns a consumable queue with:
236
+ - pending approvals
237
+ - ready tasks
238
+ - idle workers
239
+
240
+ Operations:
241
+ - status: Read last stored queue snapshot
242
+ - refresh: Recompute queue from Beads + swarm progress and store snapshot
243
+ - clear: Clear stored queue snapshot`,
244
+ args: {
245
+ op: tool.schema
246
+ .enum(["status", "refresh", "clear"])
247
+ .optional()
248
+ .default("status")
249
+ .describe("Operation: status, refresh, clear"),
250
+ },
251
+ execute: async (args: { op?: QueueOperation }, ctx) => {
252
+ const op = args.op || "status";
253
+ const worktree = ctx.worktree || process.cwd();
254
+
255
+ if (op === "clear") {
256
+ clearActionQueueItems();
257
+ return JSON.stringify(
258
+ {
259
+ op: "clear",
260
+ result: "ok",
261
+ cleared: true,
262
+ queue: buildSnapshot([]),
263
+ },
264
+ null,
265
+ 2,
266
+ );
267
+ }
268
+
269
+ if (op === "refresh") {
270
+ const queue = await refreshSnapshot(worktree);
271
+ return JSON.stringify(
272
+ {
273
+ op: "refresh",
274
+ result: "ok",
275
+ queue,
276
+ },
277
+ null,
278
+ 2,
279
+ );
280
+ }
281
+
282
+ const stored = listActionQueueItems();
283
+ if (stored.length === 0) {
284
+ const queue = await refreshSnapshot(worktree);
285
+ return JSON.stringify(
286
+ {
287
+ op: "status",
288
+ result: "ok",
289
+ source: "live-refresh",
290
+ queue,
291
+ },
292
+ null,
293
+ 2,
294
+ );
295
+ }
296
+
297
+ return JSON.stringify(
298
+ {
299
+ op: "status",
300
+ result: "ok",
301
+ source: "snapshot",
302
+ queue: buildSnapshot(stored),
303
+ },
304
+ null,
305
+ 2,
306
+ );
307
+ },
308
+ });
@@ -1,10 +1,10 @@
1
- import { exec } from "node:child_process";
1
+ import { execFile } from "node:child_process";
2
2
  import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { promisify } from "node:util";
5
5
  import { tool } from "@opencode-ai/plugin";
6
6
 
7
- const execAsync = promisify(exec);
7
+ const execFileAsync = promisify(execFile);
8
8
 
9
9
  /**
10
10
  * Unified swarm orchestration tool.
@@ -38,7 +38,7 @@ Usage:
38
38
  // Monitor args
39
39
  team: tool.schema.string().optional().describe("Team name (monitor)"),
40
40
  action: tool.schema
41
- .string()
41
+ .enum(["update", "render", "status", "clear", "push", "pull"])
42
42
  .optional()
43
43
  .describe(
44
44
  "Monitor action: update, render, status, clear | Sync action: push, pull",
@@ -82,7 +82,7 @@ Usage:
82
82
  .describe("Write to file (delegate)"),
83
83
  // Sync args
84
84
  filter: tool.schema
85
- .string()
85
+ .enum(["open", "in_progress", "all"])
86
86
  .optional()
87
87
  .describe("Filter: open, in_progress, all (sync)"),
88
88
  },
@@ -96,7 +96,7 @@ Usage:
96
96
  case "monitor":
97
97
  return monitorOperation(args, worktree);
98
98
  case "delegate":
99
- return delegateOperation(args);
99
+ return delegateOperation(args, worktree);
100
100
  case "sync":
101
101
  return syncOperation(args, worktree);
102
102
  default:
@@ -240,10 +240,21 @@ interface ProgressEntry {
240
240
  file?: string;
241
241
  }
242
242
 
243
+ type MonitorAction = "update" | "render" | "status" | "clear";
244
+ type SyncAction = "push" | "pull";
245
+ type SyncFilter = "open" | "in_progress" | "all";
246
+
247
+ const MONITOR_ACTIONS = new Set<MonitorAction>([
248
+ "update",
249
+ "render",
250
+ "status",
251
+ "clear",
252
+ ]);
253
+
243
254
  async function monitorOperation(
244
255
  args: {
245
256
  team?: string;
246
- action?: string;
257
+ action?: MonitorAction | SyncAction;
247
258
  worker_id?: string;
248
259
  phase?: string;
249
260
  progress?: number;
@@ -253,7 +264,10 @@ async function monitorOperation(
253
264
  worktree: string,
254
265
  ): Promise<string> {
255
266
  const team = args.team || "default";
256
- const action = args.action || "status";
267
+ if (args.action && !MONITOR_ACTIONS.has(args.action as MonitorAction)) {
268
+ return `Invalid monitor action: ${args.action}`;
269
+ }
270
+ const action: MonitorAction = (args.action as MonitorAction) || "status";
257
271
 
258
272
  switch (action) {
259
273
  case "update":
@@ -367,16 +381,19 @@ async function clearTeam(team: string, worktree: string): Promise<string> {
367
381
  // DELEGATE OPERATION (from swarm-delegate.ts)
368
382
  // ============================================================
369
383
 
370
- function delegateOperation(args: {
371
- bead_id?: string;
372
- title?: string;
373
- outcome?: string;
374
- must_do?: string;
375
- must_not?: string;
376
- checks?: string;
377
- context?: string;
378
- write?: boolean;
379
- }): string {
384
+ async function delegateOperation(
385
+ args: {
386
+ bead_id?: string;
387
+ title?: string;
388
+ outcome?: string;
389
+ must_do?: string;
390
+ must_not?: string;
391
+ checks?: string;
392
+ context?: string;
393
+ write?: boolean;
394
+ },
395
+ worktree: string,
396
+ ): Promise<string> {
380
397
  if (!args.bead_id) return "Error: bead_id required";
381
398
  if (!args.outcome) return "Error: outcome required";
382
399
 
@@ -405,24 +422,21 @@ function delegateOperation(args: {
405
422
 
406
423
  if (!args.write) return packet;
407
424
 
408
- // Write to artifact file (sync for simplicity)
409
- const artifactDir = path.join(
410
- process.cwd(),
411
- ".beads",
412
- "artifacts",
413
- args.bead_id,
414
- );
425
+ const artifactDir = path.join(worktree, ".beads", "artifacts", args.bead_id);
415
426
  const outPath = path.join(artifactDir, "delegation.md");
416
- fs.mkdir(artifactDir, { recursive: true })
417
- .then(() =>
418
- fs.appendFile(
419
- outPath,
420
- `\n---\nGenerated: ${new Date().toISOString()}\n---\n\n${packet}\n`,
421
- ),
422
- )
423
- .catch(() => {});
424
427
 
425
- return `✓ Delegation packet written to ${outPath}\n\n${packet}`;
428
+ try {
429
+ await fs.mkdir(artifactDir, { recursive: true });
430
+ await fs.appendFile(
431
+ outPath,
432
+ `\n---\nGenerated: ${new Date().toISOString()}\n---\n\n${packet}\n`,
433
+ "utf-8",
434
+ );
435
+ return `✓ Delegation packet written to ${outPath}\n\n${packet}`;
436
+ } catch (error: unknown) {
437
+ const message = error instanceof Error ? error.message : String(error);
438
+ return `Error writing delegation packet: ${message}`;
439
+ }
426
440
  }
427
441
 
428
442
  // ============================================================
@@ -446,10 +460,14 @@ interface BeadTask {
446
460
  }
447
461
 
448
462
  async function syncOperation(
449
- args: { action?: string; filter?: string },
463
+ args: { action?: MonitorAction | SyncAction; filter?: SyncFilter },
450
464
  worktree: string,
451
465
  ): Promise<string> {
452
- const action = args.action || "push";
466
+ if (args.action && args.action !== "push" && args.action !== "pull") {
467
+ return `Invalid sync action: ${args.action}`;
468
+ }
469
+
470
+ const action: SyncAction = (args.action as SyncAction) || "push";
453
471
 
454
472
  if (action === "push") {
455
473
  return pushBeadsToTodos(worktree, args.filter || "open");
@@ -462,12 +480,17 @@ async function syncOperation(
462
480
 
463
481
  async function pushBeadsToTodos(
464
482
  worktree: string,
465
- filter: string,
483
+ filter: SyncFilter,
466
484
  ): Promise<string> {
467
485
  try {
468
- const statusFilter = filter === "all" ? "" : `--status ${filter}`;
469
- const { stdout } = await execAsync(`br list ${statusFilter} --json`, {
486
+ const args = ["list", "--json"];
487
+ if (filter !== "all") {
488
+ args.push("--status", filter);
489
+ }
490
+
491
+ const { stdout } = await execFileAsync("br", args, {
470
492
  cwd: worktree,
493
+ timeout: 15000,
471
494
  });
472
495
 
473
496
  let tasks: BeadTask[];
@@ -532,10 +555,12 @@ async function pullTodosToBeads(worktree: string): Promise<string> {
532
555
  for (const todo of todos) {
533
556
  if (todo.beadId && todo.status === "completed") {
534
557
  try {
535
- await execAsync(
536
- `br close ${todo.beadId} --reason "Completed via todo"`,
558
+ await execFileAsync(
559
+ "br",
560
+ ["close", todo.beadId, "--reason", "Completed via todo"],
537
561
  {
538
562
  cwd: worktree,
563
+ timeout: 15000,
539
564
  },
540
565
  );
541
566
  updated++;
package/package.json CHANGED
@@ -1,8 +1,15 @@
1
1
  {
2
2
  "name": "opencodekit",
3
- "version": "0.16.15",
3
+ "version": "0.16.18",
4
4
  "description": "CLI tool for bootstrapping and managing OpenCodeKit projects",
5
- "keywords": ["agents", "cli", "mcp", "opencode", "opencodekit", "template"],
5
+ "keywords": [
6
+ "agents",
7
+ "cli",
8
+ "mcp",
9
+ "opencode",
10
+ "opencodekit",
11
+ "template"
12
+ ],
6
13
  "license": "MIT",
7
14
  "author": "OpenCodeKit",
8
15
  "repository": {
@@ -12,7 +19,10 @@
12
19
  "bin": {
13
20
  "ock": "dist/index.js"
14
21
  },
15
- "files": ["dist", "README.md"],
22
+ "files": [
23
+ "dist",
24
+ "README.md"
25
+ ],
16
26
  "type": "module",
17
27
  "publishConfig": {
18
28
  "access": "public",
@@ -26,6 +36,9 @@
26
36
  "typecheck": "tsc --noEmit",
27
37
  "test": "bun test",
28
38
  "test:watch": "bun test --watch",
39
+ "validate:command-doc": "bun run src/validation/command-doc.ts --check",
40
+ "validate:docs-drift": "bun run src/validation/docs-drift.ts --check",
41
+ "validate:governance": "npm run validate:command-doc && npm run validate:docs-drift",
29
42
  "lint": "oxlint .",
30
43
  "lint:fix": "oxlint --fix .",
31
44
  "format": "oxfmt",
@@ -1,88 +0,0 @@
1
- ---
2
- name: context7
3
- description: Retrieve up-to-date documentation for software libraries, frameworks, and components via the Context7 API. This skill should be used when looking up documentation for any programming library or framework, finding code examples for specific APIs or features, verifying correct usage of library functions, or obtaining current information about library APIs that may have changed since training.
4
- ---
5
-
6
- # Context7
7
-
8
- ## Overview
9
-
10
- This skill enables retrieval of current documentation for software libraries and components by querying the Context7 API via curl. Use it instead of relying on potentially outdated training data.
11
-
12
- ## Workflow
13
-
14
- ### Step 1: Search for the Library
15
-
16
- To find the Context7 library ID, query the search endpoint:
17
-
18
- ```bash
19
- curl -s "https://context7.com/api/v2/libs/search?libraryName=LIBRARY_NAME&query=TOPIC" | jq '.results[0]'
20
- ```
21
-
22
- **Parameters:**
23
-
24
- - `libraryName` (required): The library name to search for (e.g., "react", "nextjs", "fastapi", "axios")
25
- - `query` (required): A description of the topic for relevance ranking
26
-
27
- **Response fields:**
28
-
29
- - `id`: Library identifier for the context endpoint (e.g., `/websites/react_dev_reference`)
30
- - `title`: Human-readable library name
31
- - `description`: Brief description of the library
32
- - `totalSnippets`: Number of documentation snippets available
33
-
34
- ### Step 2: Fetch Documentation
35
-
36
- To retrieve documentation, use the library ID from step 1:
37
-
38
- ```bash
39
- curl -s "https://context7.com/api/v2/context?libraryId=LIBRARY_ID&query=TOPIC&type=txt"
40
- ```
41
-
42
- **Parameters:**
43
-
44
- - `libraryId` (required): The library ID from search results
45
- - `query` (required): The specific topic to retrieve documentation for
46
- - `type` (optional): Response format - `json` (default) or `txt` (plain text, more readable)
47
-
48
- ## Examples
49
-
50
- ### React hooks documentation
51
-
52
- ```bash
53
- # Find React library ID
54
- curl -s "https://context7.com/api/v2/libs/search?libraryName=react&query=hooks" | jq '.results[0].id'
55
- # Returns: "/websites/react_dev_reference"
56
-
57
- # Fetch useState documentation
58
- curl -s "https://context7.com/api/v2/context?libraryId=/websites/react_dev_reference&query=useState&type=txt"
59
- ```
60
-
61
- ### Next.js routing documentation
62
-
63
- ```bash
64
- # Find Next.js library ID
65
- curl -s "https://context7.com/api/v2/libs/search?libraryName=nextjs&query=routing" | jq '.results[0].id'
66
-
67
- # Fetch app router documentation
68
- curl -s "https://context7.com/api/v2/context?libraryId=/vercel/next.js&query=app+router&type=txt"
69
- ```
70
-
71
- ### FastAPI dependency injection
72
-
73
- ```bash
74
- # Find FastAPI library ID
75
- curl -s "https://context7.com/api/v2/libs/search?libraryName=fastapi&query=dependencies" | jq '.results[0].id'
76
-
77
- # Fetch dependency injection documentation
78
- curl -s "https://context7.com/api/v2/context?libraryId=/fastapi/fastapi&query=dependency+injection&type=txt"
79
- ```
80
-
81
- ## Tips
82
-
83
- - Use `type=txt` for more readable output
84
- - Use `jq` to filter and format JSON responses
85
- - Be specific with the `query` parameter to improve relevance ranking
86
- - If the first search result is not correct, check additional results in the array
87
- - URL-encode query parameters containing spaces (use `+` or `%20`)
88
- - No API key is required for basic usage (rate-limited)