@pebblehouse/odin-cli 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 (2) hide show
  1. package/dist/index.js +224 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import { Command as Command7 } from "commander";
4
+ import { Command as Command12 } from "commander";
5
5
 
6
6
  // src/auth/login.ts
7
7
  import { createServer } from "http";
@@ -209,6 +209,13 @@ docsCmd.command("create <slug> <type>").description("Create a document").require
209
209
  process.stdout.write(JSON.stringify(res) + "\n");
210
210
  if (res.error) process.exit(1);
211
211
  });
212
+ docsCmd.command("delete <slug> <type>").description("Delete a document").action(async (slug, type) => {
213
+ const res = await apiRequest(`/pebbles/${slug}/documents/${type}`, {
214
+ method: "DELETE"
215
+ });
216
+ process.stdout.write(JSON.stringify(res) + "\n");
217
+ if (res.error) process.exit(1);
218
+ });
212
219
  docsCmd.command("update <slug> <type>").description("Update document content").requiredOption("--file <path>", "Read content from file").option("--source <source>", "Source", "manual").action(async (slug, type, opts) => {
213
220
  const content = readFileSync2(opts.file, "utf-8");
214
221
  const res = await apiRequest(`/pebbles/${slug}/documents/${type}`, {
@@ -227,6 +234,11 @@ decisionsCmd.command("list <slug>").description("List decisions for a pebble").a
227
234
  process.stdout.write(JSON.stringify(res) + "\n");
228
235
  if (res.error) process.exit(1);
229
236
  });
237
+ decisionsCmd.command("get <slug> <id>").description("Get a decision by ID").action(async (slug, id) => {
238
+ const res = await apiRequest(`/pebbles/${slug}/decisions/${id}`);
239
+ process.stdout.write(JSON.stringify(res) + "\n");
240
+ if (res.error) process.exit(1);
241
+ });
230
242
  decisionsCmd.command("log <slug> <title>").description("Log a decision").option("--rationale <rationale>", "Decision rationale").option("--alternatives <alternatives>", "Alternatives considered").option("--session-id <id>", "Link to active session").action(async (slug, title, opts) => {
231
243
  const res = await apiRequest(`/pebbles/${slug}/decisions`, {
232
244
  method: "POST",
@@ -262,6 +274,11 @@ sessionsCmd.command("start <slug>").description("Start a session").option("--sou
262
274
  process.stdout.write(JSON.stringify(res) + "\n");
263
275
  if (res.error) process.exit(1);
264
276
  });
277
+ sessionsCmd.command("list <slug>").description("List sessions for a pebble").action(async (slug) => {
278
+ const res = await apiRequest(`/sessions/by-pebble/${slug}`);
279
+ process.stdout.write(JSON.stringify(res) + "\n");
280
+ if (res.error) process.exit(1);
281
+ });
265
282
  sessionsCmd.command("end <id>").description("End a session").option("--summary <summary>", "Session summary").option("--status <status>", "Final status", "completed").action(async (id, opts) => {
266
283
  const res = await apiRequest(`/sessions/${id}`, {
267
284
  method: "PUT",
@@ -281,11 +298,210 @@ var searchCmd = new Command6("search").description("Full-text search across Odin
281
298
  if (res.error) process.exit(1);
282
299
  });
283
300
 
301
+ // src/commands/plans.ts
302
+ import { Command as Command7 } from "commander";
303
+ import { readFileSync as readFileSync3 } from "fs";
304
+ var plansCmd = new Command7("plans").description("Manage plans");
305
+ plansCmd.command("list <slug>").description("List plans for a pebble").action(async (slug) => {
306
+ const res = await apiRequest(`/pebbles/${slug}/plans`);
307
+ process.stdout.write(JSON.stringify(res) + "\n");
308
+ if (res.error) process.exit(1);
309
+ });
310
+ plansCmd.command("get <slug> <id>").description("Get plan with phases").action(async (slug, id) => {
311
+ const planRes = await apiRequest(`/pebbles/${slug}/plans/${id}`);
312
+ if (planRes.error) {
313
+ process.stdout.write(JSON.stringify(planRes) + "\n");
314
+ process.exit(1);
315
+ }
316
+ const phasesRes = await apiRequest(`/pebbles/${slug}/plans/${id}/phases`);
317
+ const result = {
318
+ data: { ...planRes.data, phases: phasesRes.data ?? [] },
319
+ error: null
320
+ };
321
+ process.stdout.write(JSON.stringify(result) + "\n");
322
+ });
323
+ plansCmd.command("create <slug> <title>").description("Create a plan").option("--description <description>", "Plan description").option("--file <path>", "Read description from file").option("--source <source>", "Source", "claude-code").action(async (slug, title, opts) => {
324
+ const description = opts.file ? readFileSync3(opts.file, "utf-8") : opts.description ?? null;
325
+ const res = await apiRequest(`/pebbles/${slug}/plans`, {
326
+ method: "POST",
327
+ body: { title, description, source: opts.source }
328
+ });
329
+ process.stdout.write(JSON.stringify(res) + "\n");
330
+ if (res.error) process.exit(1);
331
+ });
332
+ plansCmd.command("delete <slug> <id>").description("Delete a plan").action(async (slug, id) => {
333
+ const res = await apiRequest(`/pebbles/${slug}/plans/${id}`, {
334
+ method: "DELETE"
335
+ });
336
+ process.stdout.write(JSON.stringify(res) + "\n");
337
+ if (res.error) process.exit(1);
338
+ });
339
+ plansCmd.command("add-phase <slug> <planId> <title>").description("Add a phase to a plan").requiredOption("--phase-number <number>", "Phase number", parseInt).option("--description <description>", "Phase description").action(async (slug, planId, title, opts) => {
340
+ const res = await apiRequest(`/pebbles/${slug}/plans/${planId}/phases`, {
341
+ method: "POST",
342
+ body: {
343
+ phase_number: opts.phaseNumber,
344
+ title,
345
+ description: opts.description ?? null
346
+ }
347
+ });
348
+ process.stdout.write(JSON.stringify(res) + "\n");
349
+ if (res.error) process.exit(1);
350
+ });
351
+ plansCmd.command("update-phase <slug> <planId> <phaseId>").description("Update a phase").option("--title <title>", "Phase title").option("--status <status>", "Phase status (pending|in_progress|completed|skipped)").option("--notes <notes>", "Phase notes").option("--description <description>", "Phase description").action(async (slug, planId, phaseId, opts) => {
352
+ const body = {};
353
+ if (opts.title) body.title = opts.title;
354
+ if (opts.status) body.status = opts.status;
355
+ if (opts.notes) body.notes = opts.notes;
356
+ if (opts.description) body.description = opts.description;
357
+ const res = await apiRequest(`/pebbles/${slug}/plans/${planId}/phases/${phaseId}`, {
358
+ method: "PUT",
359
+ body
360
+ });
361
+ process.stdout.write(JSON.stringify(res) + "\n");
362
+ if (res.error) process.exit(1);
363
+ });
364
+ plansCmd.command("delete-phase <slug> <planId> <phaseId>").description("Delete a phase").action(async (slug, planId, phaseId) => {
365
+ const res = await apiRequest(`/pebbles/${slug}/plans/${planId}/phases/${phaseId}`, {
366
+ method: "DELETE"
367
+ });
368
+ process.stdout.write(JSON.stringify(res) + "\n");
369
+ if (res.error) process.exit(1);
370
+ });
371
+
372
+ // src/commands/conversations.ts
373
+ import { Command as Command8 } from "commander";
374
+ var conversationsCmd = new Command8("conversations").description("Manage conversations");
375
+ conversationsCmd.command("list <slug>").description("List conversations for a pebble").action(async (slug) => {
376
+ const res = await apiRequest(`/pebbles/${slug}/conversations`);
377
+ process.stdout.write(JSON.stringify(res) + "\n");
378
+ if (res.error) process.exit(1);
379
+ });
380
+ conversationsCmd.command("get <slug> <id>").description("Get a conversation by ID").action(async (slug, id) => {
381
+ const res = await apiRequest(`/pebbles/${slug}/conversations/${id}`);
382
+ process.stdout.write(JSON.stringify(res) + "\n");
383
+ if (res.error) process.exit(1);
384
+ });
385
+ conversationsCmd.command("create <slug> <title>").description("Create a conversation").option("--summary <summary>", "Conversation summary").option("--source-url <url>", "Source URL").option("--session-id <id>", "Link to active session").action(async (slug, title, opts) => {
386
+ const res = await apiRequest(`/pebbles/${slug}/conversations`, {
387
+ method: "POST",
388
+ body: {
389
+ title,
390
+ summary: opts.summary ?? null,
391
+ source_url: opts.sourceUrl ?? null,
392
+ session_id: opts.sessionId ?? null
393
+ }
394
+ });
395
+ process.stdout.write(JSON.stringify(res) + "\n");
396
+ if (res.error) process.exit(1);
397
+ });
398
+ conversationsCmd.command("update <slug> <id>").description("Update a conversation").option("--title <title>", "New title").option("--summary <summary>", "New summary").option("--source-url <url>", "New source URL").action(async (slug, id, opts) => {
399
+ const body = {};
400
+ if (opts.title) body.title = opts.title;
401
+ if (opts.summary) body.summary = opts.summary;
402
+ if (opts.sourceUrl) body.source_url = opts.sourceUrl;
403
+ const res = await apiRequest(`/pebbles/${slug}/conversations/${id}`, {
404
+ method: "PUT",
405
+ body
406
+ });
407
+ process.stdout.write(JSON.stringify(res) + "\n");
408
+ if (res.error) process.exit(1);
409
+ });
410
+ conversationsCmd.command("delete <slug> <id>").description("Delete a conversation").action(async (slug, id) => {
411
+ const res = await apiRequest(`/pebbles/${slug}/conversations/${id}`, {
412
+ method: "DELETE"
413
+ });
414
+ process.stdout.write(JSON.stringify(res) + "\n");
415
+ if (res.error) process.exit(1);
416
+ });
417
+
418
+ // src/commands/specs.ts
419
+ import { Command as Command9 } from "commander";
420
+ import { readFileSync as readFileSync4 } from "fs";
421
+ var specsCmd = new Command9("specs").description("Manage superpowers specs");
422
+ specsCmd.command("list <slug>").description("List specs for a pebble").action(async (slug) => {
423
+ const res = await apiRequest(`/pebbles/${slug}/superpowers-specs`);
424
+ process.stdout.write(JSON.stringify(res) + "\n");
425
+ if (res.error) process.exit(1);
426
+ });
427
+ specsCmd.command("get <slug> <id>").description("Get a spec by ID").action(async (slug, id) => {
428
+ const res = await apiRequest(`/pebbles/${slug}/superpowers-specs/${id}`);
429
+ process.stdout.write(JSON.stringify(res) + "\n");
430
+ if (res.error) process.exit(1);
431
+ });
432
+ specsCmd.command("create <slug> <title>").description("Create a spec").requiredOption("--spec-type <type>", "Spec type (e.g. brainstorm, plan, research)").option("--content <content>", "Spec content").option("--file <path>", "Read content from file").option("--session-id <id>", "Link to active session").action(async (slug, title, opts) => {
433
+ const content = opts.file ? readFileSync4(opts.file, "utf-8") : opts.content ?? "";
434
+ const res = await apiRequest(`/pebbles/${slug}/superpowers-specs`, {
435
+ method: "POST",
436
+ body: {
437
+ title,
438
+ spec_type: opts.specType,
439
+ content,
440
+ session_id: opts.sessionId ?? null
441
+ }
442
+ });
443
+ process.stdout.write(JSON.stringify(res) + "\n");
444
+ if (res.error) process.exit(1);
445
+ });
446
+ specsCmd.command("update <slug> <id>").description("Update a spec").option("--title <title>", "New title").option("--spec-type <type>", "New spec type").option("--content <content>", "New content").option("--file <path>", "Read content from file").action(async (slug, id, opts) => {
447
+ const body = {};
448
+ if (opts.title) body.title = opts.title;
449
+ if (opts.specType) body.spec_type = opts.specType;
450
+ if (opts.file) body.content = readFileSync4(opts.file, "utf-8");
451
+ else if (opts.content) body.content = opts.content;
452
+ const res = await apiRequest(`/pebbles/${slug}/superpowers-specs/${id}`, {
453
+ method: "PUT",
454
+ body
455
+ });
456
+ process.stdout.write(JSON.stringify(res) + "\n");
457
+ if (res.error) process.exit(1);
458
+ });
459
+ specsCmd.command("delete <slug> <id>").description("Delete a spec").action(async (slug, id) => {
460
+ const res = await apiRequest(`/pebbles/${slug}/superpowers-specs/${id}`, {
461
+ method: "DELETE"
462
+ });
463
+ process.stdout.write(JSON.stringify(res) + "\n");
464
+ if (res.error) process.exit(1);
465
+ });
466
+
467
+ // src/commands/executions.ts
468
+ import { Command as Command10 } from "commander";
469
+ var executionsCmd = new Command10("executions").description("View Claude Code executions");
470
+ executionsCmd.command("list <slug>").description("List executions for a pebble").option("--session-id <id>", "Filter by session ID").option("--limit <n>", "Max results", "50").option("--offset <n>", "Offset for pagination", "0").action(async (slug, opts) => {
471
+ const params = {
472
+ limit: opts.limit,
473
+ offset: opts.offset
474
+ };
475
+ if (opts.sessionId) params.session_id = opts.sessionId;
476
+ const res = await apiRequest(`/pebbles/${slug}/executions`, { params });
477
+ process.stdout.write(JSON.stringify(res) + "\n");
478
+ if (res.error) process.exit(1);
479
+ });
480
+ executionsCmd.command("get <slug> <id>").description("Get a single execution").action(async (slug, id) => {
481
+ const res = await apiRequest(`/pebbles/${slug}/executions/${id}`);
482
+ process.stdout.write(JSON.stringify(res) + "\n");
483
+ if (res.error) process.exit(1);
484
+ });
485
+
486
+ // src/commands/versions.ts
487
+ import { Command as Command11 } from "commander";
488
+ var versionsCmd = new Command11("versions").description("View document version history");
489
+ versionsCmd.command("list <slug> <docType>").description("List versions for a document").action(async (slug, docType) => {
490
+ const res = await apiRequest(`/pebbles/${slug}/documents/${docType}/versions`);
491
+ process.stdout.write(JSON.stringify(res) + "\n");
492
+ if (res.error) process.exit(1);
493
+ });
494
+ versionsCmd.command("get <slug> <docType> <versionId>").description("Get a specific document version").action(async (slug, docType, versionId) => {
495
+ const res = await apiRequest(`/pebbles/${slug}/documents/${docType}/versions/${versionId}`);
496
+ process.stdout.write(JSON.stringify(res) + "\n");
497
+ if (res.error) process.exit(1);
498
+ });
499
+
284
500
  // src/index.ts
285
501
  var GOLD = "\x1B[33m";
286
502
  var DIM = "\x1B[2m";
287
503
  var RESET = "\x1B[0m";
288
- var VERSION = "0.1.0";
504
+ var VERSION = "0.2.0";
289
505
  function printBanner() {
290
506
  const cwd = process.cwd();
291
507
  console.error(`${GOLD}
@@ -299,7 +515,7 @@ ${RESET}
299
515
  ${DIM}${cwd}${RESET}
300
516
  `);
301
517
  }
302
- var program = new Command7();
518
+ var program = new Command12();
303
519
  program.name("odin").description("CLI for Odin \u2014 the knowledge backbone for Pebble House").version(VERSION);
304
520
  program.command("login").description("Authenticate with Odin via browser").action(async () => {
305
521
  printBanner();
@@ -321,6 +537,11 @@ program.addCommand(decisionsCmd);
321
537
  program.addCommand(contextCmd);
322
538
  program.addCommand(sessionsCmd);
323
539
  program.addCommand(searchCmd);
540
+ program.addCommand(plansCmd);
541
+ program.addCommand(conversationsCmd);
542
+ program.addCommand(specsCmd);
543
+ program.addCommand(executionsCmd);
544
+ program.addCommand(versionsCmd);
324
545
  program.parseAsync(process.argv).catch((err) => {
325
546
  console.error(err instanceof Error ? err.message : err);
326
547
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pebblehouse/odin-cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "CLI for Odin — the knowledge backbone for Pebble House",
6
6
  "bin": {