@pebblehouse/odin-cli 0.4.2 → 0.6.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 +37 -204
  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 Command14 } from "commander";
4
+ import { Command as Command10 } from "commander";
5
5
 
6
6
  // src/auth/login.ts
7
7
  import { createServer } from "http";
@@ -311,14 +311,13 @@ decisionsCmd.command("get <slug> <id>").description("Get a decision by ID").acti
311
311
  process.stdout.write(JSON.stringify(res) + "\n");
312
312
  if (res.error) process.exit(1);
313
313
  });
314
- 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) => {
314
+ decisionsCmd.command("log <slug> <title>").description("Log a decision").option("--rationale <rationale>", "Decision rationale").option("--alternatives <alternatives>", "Alternatives considered").action(async (slug, title, opts) => {
315
315
  const res = await apiRequest(`/pebbles/${slug}/decisions`, {
316
316
  method: "POST",
317
317
  body: {
318
318
  title,
319
319
  rationale: opts.rationale,
320
- alternatives_considered: opts.alternatives,
321
- session_id: opts.sessionId
320
+ alternatives_considered: opts.alternatives
322
321
  }
323
322
  });
324
323
  process.stdout.write(JSON.stringify(res) + "\n");
@@ -327,42 +326,18 @@ decisionsCmd.command("log <slug> <title>").description("Log a decision").option(
327
326
 
328
327
  // src/commands/context.ts
329
328
  import { Command as Command4 } from "commander";
330
- var contextCmd = new Command4("context").description("Get Tier 1 context for a pebble").argument("<slug>", "Pebble slug").option("--limit <n>", "Number of context entries", "50").action(async (slug, opts) => {
331
- const res = await apiRequest(`/pebbles/${slug}/context`, {
332
- params: { limit: opts.limit }
333
- });
334
- process.stdout.write(JSON.stringify(res) + "\n");
335
- if (res.error) process.exit(1);
336
- });
337
-
338
- // src/commands/sessions.ts
339
- import { Command as Command5 } from "commander";
340
- var sessionsCmd = new Command5("sessions").description("Manage sessions");
341
- sessionsCmd.command("start <slug>").description("Start a session").option("--source <source>", "Session source", "claude-code").action(async (slug, opts) => {
342
- const res = await apiRequest("/sessions", {
343
- method: "POST",
344
- body: { pebble_slug: slug, source: opts.source }
345
- });
346
- process.stdout.write(JSON.stringify(res) + "\n");
347
- if (res.error) process.exit(1);
348
- });
349
- sessionsCmd.command("list <slug>").description("List sessions for a pebble").action(async (slug) => {
350
- const res = await apiRequest(`/sessions/by-pebble/${slug}`);
351
- process.stdout.write(JSON.stringify(res) + "\n");
352
- if (res.error) process.exit(1);
353
- });
354
- sessionsCmd.command("end <id>").description("End a session").option("--summary <summary>", "Session summary").option("--status <status>", "Final status", "completed").action(async (id, opts) => {
355
- const res = await apiRequest(`/sessions/${id}`, {
356
- method: "PUT",
357
- body: { summary: opts.summary, status: opts.status }
358
- });
359
- process.stdout.write(JSON.stringify(res) + "\n");
360
- if (res.error) process.exit(1);
329
+ var contextCmd = new Command4("context").description("Get Tier 1 context for a pebble").argument("<slug>", "Pebble slug").action(async (slug) => {
330
+ console.error(`[odin context] T1 context endpoint is being rebuilt (Phase 5).`);
331
+ console.error(`In the meantime, use:`);
332
+ console.error(` odin guidelines list`);
333
+ console.error(` odin docs get ${slug} <type>`);
334
+ console.error(` odin decisions list ${slug}`);
335
+ process.exit(0);
361
336
  });
362
337
 
363
338
  // src/commands/search.ts
364
- import { Command as Command6 } from "commander";
365
- var searchCmd = new Command6("search").description("Full-text search across Odin").argument("<query>", "Search query").option("--pebble <slug>", "Scope to a pebble").action(async (query, opts) => {
339
+ import { Command as Command5 } from "commander";
340
+ var searchCmd = new Command5("search").description("Full-text search across Odin").argument("<query>", "Search query").option("--pebble <slug>", "Scope to a pebble").action(async (query, opts) => {
366
341
  const params = { q: query };
367
342
  if (opts.pebble) params.pebble = opts.pebble;
368
343
  const res = await apiRequest("/search", { params });
@@ -371,9 +346,9 @@ var searchCmd = new Command6("search").description("Full-text search across Odin
371
346
  });
372
347
 
373
348
  // src/commands/plans.ts
374
- import { Command as Command7 } from "commander";
349
+ import { Command as Command6 } from "commander";
375
350
  import { readFileSync as readFileSync4 } from "fs";
376
- var plansCmd = new Command7("plans").description("Manage plans");
351
+ var plansCmd = new Command6("plans").description("Manage plans");
377
352
  plansCmd.command("list <slug>").description("List plans for a pebble").action(async (slug) => {
378
353
  const res = await apiRequest(`/pebbles/${slug}/plans`);
379
354
  process.stdout.write(JSON.stringify(res) + "\n");
@@ -452,7 +427,7 @@ plansCmd.command("delete-phase <slug> <planId> <phaseId>").description("Delete a
452
427
  process.stdout.write(JSON.stringify(res) + "\n");
453
428
  if (res.error) process.exit(1);
454
429
  });
455
- plansCmd.command("add-phase-link <slug> <planId> <phaseId>").description("Add a link from a phase to a spec or document").requiredOption("--link-type <type>", "Link type (spec|plan_doc)").requiredOption("--target-type <type>", "Target type (agent_spec|document)").requiredOption("--target-id <id>", "Target entity UUID").action(async (slug, planId, phaseId, opts) => {
430
+ plansCmd.command("add-phase-link <slug> <planId> <phaseId>").description("Add a link from a phase to a spec or document").requiredOption("--link-type <type>", "Link type (spec|plan_doc)").requiredOption("--target-type <type>", "Target type (artifact|document)").requiredOption("--target-id <id>", "Target entity UUID").action(async (slug, planId, phaseId, opts) => {
456
431
  const res = await apiRequest(`/pebbles/${slug}/plans/${planId}/phases/${phaseId}/links`, {
457
432
  method: "POST",
458
433
  body: {
@@ -472,154 +447,61 @@ plansCmd.command("remove-phase-link <slug> <planId> <phaseId> <linkId>").descrip
472
447
  if (res.error) process.exit(1);
473
448
  });
474
449
 
475
- // src/commands/conversations.ts
476
- import { Command as Command8 } from "commander";
477
- function collect(value, previous) {
478
- return previous.concat([value]);
479
- }
480
- var conversationsCmd = new Command8("conversations").description("Manage conversations");
481
- conversationsCmd.command("list <slug>").description("List conversations for a pebble").action(async (slug) => {
482
- const res = await apiRequest(`/pebbles/${slug}/conversations`);
483
- process.stdout.write(JSON.stringify(res) + "\n");
484
- if (res.error) process.exit(1);
485
- });
486
- conversationsCmd.command("get <slug> <id>").description("Get a conversation by ID").action(async (slug, id) => {
487
- const res = await apiRequest(`/pebbles/${slug}/conversations/${id}`);
488
- process.stdout.write(JSON.stringify(res) + "\n");
489
- if (res.error) process.exit(1);
490
- });
491
- conversationsCmd.command("create <slug> <title>").description("Create a conversation").option("--summary <summary>", "Conversation summary").option("--key-point <point>", "Key point (repeatable)", collect, []).option("--decision <decision>", "Decision made (repeatable)", collect, []).option("--source-url <url>", "Source URL").option("--session-id <id>", "Link to active session").action(async (slug, title, opts) => {
492
- const res = await apiRequest(`/pebbles/${slug}/conversations`, {
493
- method: "POST",
494
- body: {
495
- title,
496
- summary: opts.summary ?? null,
497
- key_points: opts.keyPoint,
498
- decisions_made: opts.decision,
499
- source_url: opts.sourceUrl ?? null,
500
- session_id: opts.sessionId ?? null
501
- }
502
- });
503
- process.stdout.write(JSON.stringify(res) + "\n");
504
- if (res.error) process.exit(1);
505
- });
506
- conversationsCmd.command("update <slug> <id>").description("Update a conversation").option("--title <title>", "New title").option("--summary <summary>", "New summary").option("--key-point <point>", "Key point (repeatable, replaces existing)", collect, []).option("--decision <decision>", "Decision made (repeatable, replaces existing)", collect, []).option("--source-url <url>", "New source URL").action(async (slug, id, opts) => {
507
- const body = {};
508
- if (opts.title) body.title = opts.title;
509
- if (opts.summary) body.summary = opts.summary;
510
- if (opts.keyPoint.length > 0) body.key_points = opts.keyPoint;
511
- if (opts.decision.length > 0) body.decisions_made = opts.decision;
512
- if (opts.sourceUrl) body.source_url = opts.sourceUrl;
513
- const res = await apiRequest(`/pebbles/${slug}/conversations/${id}`, {
514
- method: "PUT",
515
- body
516
- });
517
- process.stdout.write(JSON.stringify(res) + "\n");
518
- if (res.error) process.exit(1);
519
- });
520
- conversationsCmd.command("delete <slug> <id>").description("Delete a conversation").action(async (slug, id) => {
521
- const res = await apiRequest(`/pebbles/${slug}/conversations/${id}`, {
522
- method: "DELETE"
523
- });
524
- process.stdout.write(JSON.stringify(res) + "\n");
525
- if (res.error) process.exit(1);
526
- });
527
-
528
- // src/commands/specs.ts
529
- import { Command as Command9 } from "commander";
450
+ // src/commands/artifacts.ts
451
+ import { Command as Command7 } from "commander";
530
452
  import { readFileSync as readFileSync5 } from "fs";
531
- var specsCmd = new Command9("specs").description("Manage agent specs");
532
- specsCmd.command("list <slug>").description("List specs for a pebble").option("--source <source>", "Filter by source (claude-code, superpowers, etc.)").action(async (slug, opts) => {
453
+ var artifactsCmd = new Command7("artifacts").description("Manage artifacts");
454
+ artifactsCmd.command("list <slug>").description("List artifacts for a pebble").option("--source <source>", "Filter by source (claude-code, superpowers, etc.)").action(async (slug, opts) => {
533
455
  const params = {};
534
456
  if (opts.source) params.source = opts.source;
535
- const res = await apiRequest(`/pebbles/${slug}/agent-specs`, { params });
457
+ const res = await apiRequest(`/pebbles/${slug}/artifacts`, { params });
536
458
  process.stdout.write(JSON.stringify(res) + "\n");
537
459
  if (res.error) process.exit(1);
538
460
  });
539
- specsCmd.command("get <slug> <id>").description("Get a spec by ID").action(async (slug, id) => {
540
- const res = await apiRequest(`/pebbles/${slug}/agent-specs/${id}`);
461
+ artifactsCmd.command("get <slug> <id>").description("Get an artifact by ID").action(async (slug, id) => {
462
+ const res = await apiRequest(`/pebbles/${slug}/artifacts/${id}`);
541
463
  process.stdout.write(JSON.stringify(res) + "\n");
542
464
  if (res.error) process.exit(1);
543
465
  });
544
- specsCmd.command("create <slug> <title>").description("Create a spec").requiredOption("--spec-type <type>", "Spec type (e.g. brainstorm, plan, research)").option("--source <source>", "Source agent", "claude-code").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) => {
466
+ artifactsCmd.command("create <slug> <title>").description("Create an artifact").requiredOption("--type <type>", "Artifact type (e.g. brainstorm, plan, research, spec)").option("--source <source>", "Source agent", "claude-code").option("--content <content>", "Artifact content").option("--file <path>", "Read content from file").action(async (slug, title, opts) => {
545
467
  const content = opts.file ? readFileSync5(opts.file, "utf-8") : opts.content ?? "";
546
- const res = await apiRequest(`/pebbles/${slug}/agent-specs`, {
468
+ const res = await apiRequest(`/pebbles/${slug}/artifacts`, {
547
469
  method: "POST",
548
470
  body: {
549
471
  title,
550
- spec_type: opts.specType,
472
+ type: opts.type,
551
473
  source: opts.source,
552
- content,
553
- session_id: opts.sessionId ?? null
474
+ content
554
475
  }
555
476
  });
556
477
  process.stdout.write(JSON.stringify(res) + "\n");
557
478
  if (res.error) process.exit(1);
558
479
  });
559
- specsCmd.command("update <slug> <id>").description("Update a spec").option("--title <title>", "New title").option("--spec-type <type>", "New spec type").option("--source <source>", "New source").option("--content <content>", "New content").option("--file <path>", "Read content from file").action(async (slug, id, opts) => {
480
+ artifactsCmd.command("update <slug> <id>").description("Update an artifact").option("--title <title>", "New title").option("--type <type>", "New type").option("--source <source>", "New source").option("--content <content>", "New content").option("--file <path>", "Read content from file").action(async (slug, id, opts) => {
560
481
  const body = {};
561
482
  if (opts.title) body.title = opts.title;
562
- if (opts.specType) body.spec_type = opts.specType;
483
+ if (opts.type) body.type = opts.type;
563
484
  if (opts.source) body.source = opts.source;
564
485
  if (opts.file) body.content = readFileSync5(opts.file, "utf-8");
565
486
  else if (opts.content) body.content = opts.content;
566
- const res = await apiRequest(`/pebbles/${slug}/agent-specs/${id}`, {
487
+ const res = await apiRequest(`/pebbles/${slug}/artifacts/${id}`, {
567
488
  method: "PUT",
568
489
  body
569
490
  });
570
491
  process.stdout.write(JSON.stringify(res) + "\n");
571
492
  if (res.error) process.exit(1);
572
493
  });
573
- specsCmd.command("delete <slug> <id>").description("Delete a spec").action(async (slug, id) => {
574
- const res = await apiRequest(`/pebbles/${slug}/agent-specs/${id}`, {
494
+ artifactsCmd.command("delete <slug> <id>").description("Delete an artifact").action(async (slug, id) => {
495
+ const res = await apiRequest(`/pebbles/${slug}/artifacts/${id}`, {
575
496
  method: "DELETE"
576
497
  });
577
498
  process.stdout.write(JSON.stringify(res) + "\n");
578
499
  if (res.error) process.exit(1);
579
500
  });
580
501
 
581
- // src/commands/executions.ts
582
- import { Command as Command10 } from "commander";
583
- var executionsCmd = new Command10("executions").description("View Claude Code executions");
584
- executionsCmd.command("create <slug>").description("Create an execution record").requiredOption("--tool-name <name>", "Tool name").option("--session-id <id>", "Session ID").option("--summary-text <text>", "Summary text").option("--execution-type <type>", "Execution type (task|discovery|system|plan)").option("--raw-input <json>", "Raw input JSON").option("--raw-output <json>", "Raw output JSON").option("--files-read <files...>", "Files read").option("--files-modified <files...>", "Files modified").option("--prompt-number <n>", "Prompt number").option("--content-hash <hash>", "Content hash for dedup").action(async (slug, opts) => {
585
- const body = {
586
- tool_name: opts.toolName
587
- };
588
- if (opts.sessionId) body.session_id = opts.sessionId;
589
- if (opts.summaryText) body.summary_text = opts.summaryText;
590
- if (opts.executionType) body.execution_type = opts.executionType;
591
- if (opts.rawInput) body.raw_input = opts.rawInput;
592
- if (opts.rawOutput) body.raw_output = opts.rawOutput;
593
- if (opts.filesRead) body.files_read = opts.filesRead;
594
- if (opts.filesModified) body.files_modified = opts.filesModified;
595
- if (opts.promptNumber) body.prompt_number = parseInt(opts.promptNumber, 10);
596
- if (opts.contentHash) body.content_hash = opts.contentHash;
597
- const res = await apiRequest(`/pebbles/${slug}/executions`, {
598
- method: "POST",
599
- body
600
- });
601
- process.stdout.write(JSON.stringify(res) + "\n");
602
- if (res.error) process.exit(1);
603
- });
604
- 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) => {
605
- const params = {
606
- limit: opts.limit,
607
- offset: opts.offset
608
- };
609
- if (opts.sessionId) params.session_id = opts.sessionId;
610
- const res = await apiRequest(`/pebbles/${slug}/executions`, { params });
611
- process.stdout.write(JSON.stringify(res) + "\n");
612
- if (res.error) process.exit(1);
613
- });
614
- executionsCmd.command("get <slug> <id>").description("Get a single execution").action(async (slug, id) => {
615
- const res = await apiRequest(`/pebbles/${slug}/executions/${id}`);
616
- process.stdout.write(JSON.stringify(res) + "\n");
617
- if (res.error) process.exit(1);
618
- });
619
-
620
502
  // src/commands/versions.ts
621
- import { Command as Command11 } from "commander";
622
- var versionsCmd = new Command11("versions").description("View document version history");
503
+ import { Command as Command8 } from "commander";
504
+ var versionsCmd = new Command8("versions").description("View document version history");
623
505
  versionsCmd.command("list <slug> <docType>").description("List versions for a document").action(async (slug, docType) => {
624
506
  const res = await apiRequest(`/pebbles/${slug}/documents/${docType}/versions`);
625
507
  process.stdout.write(JSON.stringify(res) + "\n");
@@ -632,9 +514,9 @@ versionsCmd.command("get <slug> <docType> <versionId>").description("Get a speci
632
514
  });
633
515
 
634
516
  // src/commands/guidelines.ts
635
- import { Command as Command12 } from "commander";
517
+ import { Command as Command9 } from "commander";
636
518
  import { readFileSync as readFileSync6 } from "fs";
637
- var guidelinesCmd = new Command12("guidelines").description("Manage global guidelines");
519
+ var guidelinesCmd = new Command9("guidelines").description("Manage global guidelines");
638
520
  guidelinesCmd.command("list").description("List guidelines").option("--category <category>", "Filter by category").option("--status <status>", "Filter by status (default: active)").option("--all", "Include deprecated guidelines").action(async (opts) => {
639
521
  const params = new URLSearchParams();
640
522
  if (opts.category) params.set("category", opts.category);
@@ -695,51 +577,6 @@ guidelinesCmd.command("deprecate <id>").description("Deprecate a guideline").act
695
577
  if (res.error) process.exit(1);
696
578
  });
697
579
 
698
- // src/commands/observations.ts
699
- import { Command as Command13 } from "commander";
700
- var observationsCmd = new Command13("observations").description(
701
- "View and synthesize observations"
702
- );
703
- observationsCmd.command("list <slug>").description("List observations for a pebble").option("--limit <n>", "Max results", "50").option("--offset <n>", "Offset for pagination", "0").action(async (slug, opts) => {
704
- const res = await apiRequest(
705
- `/pebbles/${slug}/observations`,
706
- {
707
- params: { limit: opts.limit, offset: opts.offset }
708
- }
709
- );
710
- process.stdout.write(JSON.stringify(res) + "\n");
711
- if (res.error) process.exit(1);
712
- });
713
- observationsCmd.command("synthesize [slug]").description("Trigger observation synthesis (requires running worker)").action(async (slug) => {
714
- try {
715
- const body = {};
716
- if (slug) body.slug = slug;
717
- const res = await fetch("http://127.0.0.1:7433/synthesize", {
718
- method: "POST",
719
- headers: { "Content-Type": "application/json" },
720
- body: JSON.stringify(body)
721
- });
722
- if (!res.ok) {
723
- const text = await res.text();
724
- console.error(`Worker returned ${res.status}: ${text}`);
725
- process.exit(1);
726
- }
727
- const data = await res.json();
728
- process.stdout.write(JSON.stringify(data) + "\n");
729
- } catch (err) {
730
- if (err instanceof Error && (err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed"))) {
731
- console.error(
732
- "Worker not running. Start a Claude Code session to launch the worker."
733
- );
734
- } else {
735
- console.error(
736
- `Failed: ${err instanceof Error ? err.message : err}`
737
- );
738
- }
739
- process.exit(1);
740
- }
741
- });
742
-
743
580
  // src/index.ts
744
581
  import { readFileSync as readFileSync7 } from "fs";
745
582
  import { fileURLToPath } from "url";
@@ -763,7 +600,7 @@ ${RESET}
763
600
  ${DIM}${cwd}${RESET}
764
601
  `);
765
602
  }
766
- var program = new Command14();
603
+ var program = new Command10();
767
604
  program.name("odin").description("CLI for Odin \u2014 the knowledge backbone for Pebble House").version(VERSION);
768
605
  program.command("login").description("Authenticate with Odin via browser").action(async () => {
769
606
  printBanner();
@@ -783,15 +620,11 @@ program.addCommand(pebblesCmd);
783
620
  program.addCommand(docsCmd);
784
621
  program.addCommand(decisionsCmd);
785
622
  program.addCommand(contextCmd);
786
- program.addCommand(sessionsCmd);
787
623
  program.addCommand(searchCmd);
788
624
  program.addCommand(plansCmd);
789
- program.addCommand(conversationsCmd);
790
- program.addCommand(specsCmd);
791
- program.addCommand(executionsCmd);
625
+ program.addCommand(artifactsCmd);
792
626
  program.addCommand(versionsCmd);
793
627
  program.addCommand(guidelinesCmd);
794
- program.addCommand(observationsCmd);
795
628
  process.on("exit", () => {
796
629
  process.stderr.write("\n\n\n\n\n");
797
630
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pebblehouse/odin-cli",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "CLI for Odin — the knowledge backbone for Pebble House",
6
6
  "bin": {