@pebblehouse/odin-cli 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +296 -6
- 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
|
|
4
|
+
import { Command as Command18 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/auth/login.ts
|
|
7
7
|
import { createServer } from "http";
|
|
@@ -464,11 +464,23 @@ plansCmd.command("create <slug> <title>").description("Create a plan").option("-
|
|
|
464
464
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
465
465
|
if (res.error) process.exit(1);
|
|
466
466
|
});
|
|
467
|
-
plansCmd.command("update <slug> <id>").description("Update a plan").option("--title <title>", "New title").option("--description <description>", "New description").option("--status <status>", "Plan status (active|
|
|
467
|
+
plansCmd.command("update <slug> <id>").description("Update a plan").option("--title <title>", "New title").option("--description <description>", "New description").option("--status <status>", "Plan status (active|done|archived)").option("--bet-id <uuid>", "Link plan to a bet").option("--task-id <uuid>", "Link plan to a task").option("--clear-bet", "Clear the bet link").option("--clear-task", "Clear the task link").action(async (slug, id, opts) => {
|
|
468
|
+
if (opts.betId && opts.clearBet) {
|
|
469
|
+
process.stderr.write("Cannot combine --bet-id with --clear-bet\n");
|
|
470
|
+
process.exit(1);
|
|
471
|
+
}
|
|
472
|
+
if (opts.taskId && opts.clearTask) {
|
|
473
|
+
process.stderr.write("Cannot combine --task-id with --clear-task\n");
|
|
474
|
+
process.exit(1);
|
|
475
|
+
}
|
|
468
476
|
const body = {};
|
|
469
477
|
if (opts.title) body.title = opts.title;
|
|
470
478
|
if (opts.description) body.description = opts.description;
|
|
471
479
|
if (opts.status) body.status = opts.status;
|
|
480
|
+
if (opts.betId) body.bet_id = opts.betId;
|
|
481
|
+
else if (opts.clearBet) body.bet_id = null;
|
|
482
|
+
if (opts.taskId) body.task_id = opts.taskId;
|
|
483
|
+
else if (opts.clearTask) body.task_id = null;
|
|
472
484
|
const res = await apiRequest(`/pebbles/${slug}/plans/${id}`, {
|
|
473
485
|
method: "PUT",
|
|
474
486
|
body
|
|
@@ -495,7 +507,7 @@ plansCmd.command("add-phase <slug> <planId> <title>").description("Add a phase t
|
|
|
495
507
|
process.stdout.write(JSON.stringify(res) + "\n");
|
|
496
508
|
if (res.error) process.exit(1);
|
|
497
509
|
});
|
|
498
|
-
plansCmd.command("update-phase <slug> <planId> <phaseId>").description("Update a phase").option("--title <title>", "Phase title").option("--status <status>", "Phase status (pending|in_progress|
|
|
510
|
+
plansCmd.command("update-phase <slug> <planId> <phaseId>").description("Update a phase").option("--title <title>", "Phase title").option("--status <status>", "Phase status (pending|in_progress|done|skipped)").option("--notes <notes>", "Phase notes").option("--description <description>", "Phase description").action(async (slug, planId, phaseId, opts) => {
|
|
499
511
|
const body = {};
|
|
500
512
|
if (opts.title) body.title = opts.title;
|
|
501
513
|
if (opts.status) body.status = opts.status;
|
|
@@ -865,12 +877,286 @@ blueprintsCmd.command("assets <id>").description("List assets for a blueprint").
|
|
|
865
877
|
if (res.error) process.exit(1);
|
|
866
878
|
});
|
|
867
879
|
|
|
868
|
-
// src/
|
|
880
|
+
// src/commands/bets.ts
|
|
881
|
+
import { Command as Command14 } from "commander";
|
|
869
882
|
import { readFileSync as readFileSync10 } from "fs";
|
|
883
|
+
|
|
884
|
+
// src/commands/bet-dependencies.ts
|
|
885
|
+
import { Command as Command13 } from "commander";
|
|
886
|
+
var depsCmd = new Command13("deps").description("Manage bet dependencies (blocked-by graph)");
|
|
887
|
+
depsCmd.command("list <slug> <bet-id>").description("List dependencies for a bet (blocked_by + blocking)").action(async (slug, betId) => {
|
|
888
|
+
const res = await apiRequest(
|
|
889
|
+
`/pebbles/${slug}/bets/${betId}/dependencies`
|
|
890
|
+
);
|
|
891
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
892
|
+
if (res.error) process.exit(1);
|
|
893
|
+
});
|
|
894
|
+
depsCmd.command("add <slug> <bet-id>").description("Add a blocked-by dependency").requiredOption("--blocked-by <id>", "Bet ID that blocks this bet").action(async (slug, betId, opts) => {
|
|
895
|
+
const res = await apiRequest(
|
|
896
|
+
`/pebbles/${slug}/bets/${betId}/dependencies`,
|
|
897
|
+
{
|
|
898
|
+
method: "POST",
|
|
899
|
+
body: { blocked_by_bet_id: opts.blockedBy }
|
|
900
|
+
}
|
|
901
|
+
);
|
|
902
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
903
|
+
if (res.error) process.exit(1);
|
|
904
|
+
});
|
|
905
|
+
depsCmd.command("remove <slug> <bet-id>").description("Remove a blocked-by dependency").requiredOption("--blocked-by <id>", "Bet ID to unlink").action(async (slug, betId, opts) => {
|
|
906
|
+
const res = await apiRequest(
|
|
907
|
+
`/pebbles/${slug}/bets/${betId}/dependencies/${opts.blockedBy}`,
|
|
908
|
+
{ method: "DELETE" }
|
|
909
|
+
);
|
|
910
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
911
|
+
if (res.error) process.exit(1);
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
// src/commands/bets.ts
|
|
915
|
+
var betsCmd = new Command14("bets").description("Manage bets");
|
|
916
|
+
betsCmd.command("list <slug>").description("List bets for a pebble").option("--status <status>", "Filter by status").action(async (slug, opts) => {
|
|
917
|
+
const params = {};
|
|
918
|
+
if (opts.status) params.status = opts.status;
|
|
919
|
+
const res = await apiRequest(`/pebbles/${slug}/bets`, { params });
|
|
920
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
921
|
+
if (res.error) process.exit(1);
|
|
922
|
+
});
|
|
923
|
+
betsCmd.command("get <slug> <id>").description("Get a bet by ID").action(async (slug, id) => {
|
|
924
|
+
const res = await apiRequest(`/pebbles/${slug}/bets/${id}`);
|
|
925
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
926
|
+
if (res.error) process.exit(1);
|
|
927
|
+
});
|
|
928
|
+
betsCmd.command("create <slug> <title>").description("Create a bet").option("--source <source>", "Source agent", "claude-code").option("--content <content>", "Bet content").option("--file <path>", "Read content from file").option("--status <status>", "Bet status").option("--priority <priority>", "Bet priority").option("--appetite <appetite>", "Bet appetite").action(async (slug, title, opts) => {
|
|
929
|
+
const content = opts.file ? readFileSync10(opts.file, "utf-8") : opts.content ?? "";
|
|
930
|
+
const res = await apiRequest(`/pebbles/${slug}/bets`, {
|
|
931
|
+
method: "POST",
|
|
932
|
+
body: { title, source: opts.source, content, status: opts.status, priority: opts.priority, appetite: opts.appetite }
|
|
933
|
+
});
|
|
934
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
935
|
+
if (res.error) process.exit(1);
|
|
936
|
+
});
|
|
937
|
+
betsCmd.command("update <slug> <id>").description("Update a bet").option("--title <title>", "New title").option("--content <content>", "New content").option("--file <path>", "Read content from file").option("--status <status>", "New status").option("--priority <priority>", "New priority").option("--appetite <appetite>", "New appetite").action(async (slug, id, opts) => {
|
|
938
|
+
const body = {};
|
|
939
|
+
if (opts.title) body.title = opts.title;
|
|
940
|
+
if (opts.file) body.content = readFileSync10(opts.file, "utf-8");
|
|
941
|
+
else if (opts.content) body.content = opts.content;
|
|
942
|
+
if (opts.status) body.status = opts.status;
|
|
943
|
+
if (opts.priority) body.priority = opts.priority;
|
|
944
|
+
if (opts.appetite) body.appetite = opts.appetite;
|
|
945
|
+
const res = await apiRequest(`/pebbles/${slug}/bets/${id}`, {
|
|
946
|
+
method: "PUT",
|
|
947
|
+
body
|
|
948
|
+
});
|
|
949
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
950
|
+
if (res.error) process.exit(1);
|
|
951
|
+
});
|
|
952
|
+
betsCmd.command("delete <slug> <id>").description("Delete a bet").action(async (slug, id) => {
|
|
953
|
+
const res = await apiRequest(`/pebbles/${slug}/bets/${id}`, {
|
|
954
|
+
method: "DELETE"
|
|
955
|
+
});
|
|
956
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
957
|
+
if (res.error) process.exit(1);
|
|
958
|
+
});
|
|
959
|
+
betsCmd.addCommand(depsCmd);
|
|
960
|
+
|
|
961
|
+
// src/commands/tasks.ts
|
|
962
|
+
import { Command as Command15 } from "commander";
|
|
963
|
+
var tasksCmd = new Command15("tasks").description("Manage tasks");
|
|
964
|
+
tasksCmd.command("list <slug>").description("List tasks for a pebble").option("--status <status>", "Filter by status").option("--bet <bet-id>", "Filter by bet ID").action(async (slug, opts) => {
|
|
965
|
+
const params = {};
|
|
966
|
+
if (opts.status) params.status = opts.status;
|
|
967
|
+
if (opts.bet) params.bet_id = opts.bet;
|
|
968
|
+
const res = await apiRequest(`/pebbles/${slug}/tasks`, { params });
|
|
969
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
970
|
+
if (res.error) process.exit(1);
|
|
971
|
+
});
|
|
972
|
+
tasksCmd.command("get <slug> <id>").description("Get a task by ID").action(async (slug, id) => {
|
|
973
|
+
const res = await apiRequest(`/pebbles/${slug}/tasks/${id}`);
|
|
974
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
975
|
+
if (res.error) process.exit(1);
|
|
976
|
+
});
|
|
977
|
+
tasksCmd.command("create <slug> <title>").description("Create a task").option("--source <source>", "Source agent", "claude-code").option("--description <description>", "Task description").option("--bet <bet-id>", "Parent bet ID").option("--status <status>", "Task status").option("--priority <priority>", "Task priority").action(async (slug, title, opts) => {
|
|
978
|
+
const res = await apiRequest(`/pebbles/${slug}/tasks`, {
|
|
979
|
+
method: "POST",
|
|
980
|
+
body: { title, source: opts.source, description: opts.description, bet_id: opts.bet, status: opts.status, priority: opts.priority }
|
|
981
|
+
});
|
|
982
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
983
|
+
if (res.error) process.exit(1);
|
|
984
|
+
});
|
|
985
|
+
tasksCmd.command("update <slug> <id>").description("Update a task").option("--title <title>", "New title").option("--description <description>", "New description").option("--status <status>", "New status").option("--priority <priority>", "New priority").option("--bet <bet-id>", "New parent bet ID").action(async (slug, id, opts) => {
|
|
986
|
+
const body = {};
|
|
987
|
+
if (opts.title) body.title = opts.title;
|
|
988
|
+
if (opts.description) body.description = opts.description;
|
|
989
|
+
if (opts.status) body.status = opts.status;
|
|
990
|
+
if (opts.priority) body.priority = opts.priority;
|
|
991
|
+
if (opts.bet) body.bet_id = opts.bet;
|
|
992
|
+
const res = await apiRequest(`/pebbles/${slug}/tasks/${id}`, {
|
|
993
|
+
method: "PUT",
|
|
994
|
+
body
|
|
995
|
+
});
|
|
996
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
997
|
+
if (res.error) process.exit(1);
|
|
998
|
+
});
|
|
999
|
+
tasksCmd.command("delete <slug> <id>").description("Delete a task").action(async (slug, id) => {
|
|
1000
|
+
const res = await apiRequest(`/pebbles/${slug}/tasks/${id}`, {
|
|
1001
|
+
method: "DELETE"
|
|
1002
|
+
});
|
|
1003
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1004
|
+
if (res.error) process.exit(1);
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
// src/commands/roadmaps.ts
|
|
1008
|
+
import { Command as Command16 } from "commander";
|
|
1009
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
1010
|
+
var roadmapsCmd = new Command16("roadmaps").description("Manage roadmaps");
|
|
1011
|
+
roadmapsCmd.command("list <slug>").description("List roadmaps for a pebble").option("--status <status>", "Filter by status").action(async (slug, opts) => {
|
|
1012
|
+
const params = {};
|
|
1013
|
+
if (opts.status) params.status = opts.status;
|
|
1014
|
+
const res = await apiRequest(`/pebbles/${slug}/roadmaps`, { params });
|
|
1015
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1016
|
+
if (res.error) process.exit(1);
|
|
1017
|
+
});
|
|
1018
|
+
roadmapsCmd.command("get <slug> <id>").description("Get a roadmap by ID (includes bets)").action(async (slug, id) => {
|
|
1019
|
+
const res = await apiRequest(`/pebbles/${slug}/roadmaps/${id}`);
|
|
1020
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1021
|
+
if (res.error) process.exit(1);
|
|
1022
|
+
});
|
|
1023
|
+
roadmapsCmd.command("create <slug> <title>").description("Create a roadmap").option("--source <source>", "Source agent", "claude-code").option("--content <content>", "Roadmap content").option("--file <path>", "Read content from file").option("--status <status>", "Roadmap status").action(async (slug, title, opts) => {
|
|
1024
|
+
const content = opts.file ? readFileSync11(opts.file, "utf-8") : opts.content ?? "";
|
|
1025
|
+
const res = await apiRequest(`/pebbles/${slug}/roadmaps`, {
|
|
1026
|
+
method: "POST",
|
|
1027
|
+
body: { title, source: opts.source, content, status: opts.status }
|
|
1028
|
+
});
|
|
1029
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1030
|
+
if (res.error) process.exit(1);
|
|
1031
|
+
});
|
|
1032
|
+
roadmapsCmd.command("update <slug> <id>").description("Update a roadmap").option("--title <title>", "New title").option("--content <content>", "New content").option("--file <path>", "Read content from file").option("--status <status>", "New status").action(async (slug, id, opts) => {
|
|
1033
|
+
const body = {};
|
|
1034
|
+
if (opts.title) body.title = opts.title;
|
|
1035
|
+
if (opts.file) body.content = readFileSync11(opts.file, "utf-8");
|
|
1036
|
+
else if (opts.content) body.content = opts.content;
|
|
1037
|
+
if (opts.status) body.status = opts.status;
|
|
1038
|
+
const res = await apiRequest(`/pebbles/${slug}/roadmaps/${id}`, {
|
|
1039
|
+
method: "PUT",
|
|
1040
|
+
body
|
|
1041
|
+
});
|
|
1042
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1043
|
+
if (res.error) process.exit(1);
|
|
1044
|
+
});
|
|
1045
|
+
roadmapsCmd.command("delete <slug> <id>").description("Delete a roadmap").action(async (slug, id) => {
|
|
1046
|
+
const res = await apiRequest(`/pebbles/${slug}/roadmaps/${id}`, {
|
|
1047
|
+
method: "DELETE"
|
|
1048
|
+
});
|
|
1049
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1050
|
+
if (res.error) process.exit(1);
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
// src/commands/persona-runs.ts
|
|
1054
|
+
import { Command as Command17 } from "commander";
|
|
1055
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
1056
|
+
import { join as join2 } from "path";
|
|
1057
|
+
import { homedir as homedir2 } from "os";
|
|
1058
|
+
var personaRunsCmd = new Command17("persona-runs").description(
|
|
1059
|
+
"Manage per-persona per-session token usage rows"
|
|
1060
|
+
);
|
|
1061
|
+
personaRunsCmd.command("list <slug>").description("List persona runs for a pebble").option("--bet-id <id>", "Filter by bet_id").option("--plan-id <id>", "Filter by plan_id").option("--persona <name>", "Filter by persona name").option("--limit <n>", "Max rows", "50").action(async (slug, opts) => {
|
|
1062
|
+
const params = {};
|
|
1063
|
+
if (opts.betId) params.bet_id = opts.betId;
|
|
1064
|
+
if (opts.planId) params.plan_id = opts.planId;
|
|
1065
|
+
if (opts.persona) params.persona = opts.persona;
|
|
1066
|
+
if (opts.limit) params.limit = String(opts.limit);
|
|
1067
|
+
const res = await apiRequest(
|
|
1068
|
+
`/pebbles/${slug}/persona-runs`,
|
|
1069
|
+
{ params }
|
|
1070
|
+
);
|
|
1071
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1072
|
+
if (res.error) process.exit(1);
|
|
1073
|
+
});
|
|
1074
|
+
personaRunsCmd.command("get <slug> <id>").description("Get a persona run by id").action(async (slug, id) => {
|
|
1075
|
+
const res = await apiRequest(
|
|
1076
|
+
`/pebbles/${slug}/persona-runs/${id}`
|
|
1077
|
+
);
|
|
1078
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1079
|
+
if (res.error) process.exit(1);
|
|
1080
|
+
});
|
|
1081
|
+
personaRunsCmd.command("create <slug>").description("Create/upsert a persona run from a JSON file").requiredOption("--file <path>", "JSON payload matching PersonaRunCreate").action(async (slug, opts) => {
|
|
1082
|
+
const body = JSON.parse(readFileSync12(opts.file, "utf-8"));
|
|
1083
|
+
const res = await apiRequest(`/pebbles/${slug}/persona-runs`, {
|
|
1084
|
+
method: "POST",
|
|
1085
|
+
body
|
|
1086
|
+
});
|
|
1087
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
1088
|
+
if (res.error) process.exit(1);
|
|
1089
|
+
});
|
|
1090
|
+
personaRunsCmd.command("capture").description("Read marker + transcript, compute tokens, POST to endpoint (hook path)").requiredOption("--session-id <id>", "Claude Code session id").requiredOption("--transcript <path>", "Path to transcript JSONL").option("--marker <path>", "Explicit marker path (default: ~/.claude/odin-context/<session-id>.json)").action(async (opts) => {
|
|
1091
|
+
const markerPath = opts.marker ?? join2(homedir2(), ".claude", "odin-context", `${opts.sessionId}.json`);
|
|
1092
|
+
let marker = {};
|
|
1093
|
+
try {
|
|
1094
|
+
marker = JSON.parse(readFileSync12(markerPath, "utf-8"));
|
|
1095
|
+
} catch {
|
|
1096
|
+
process.exit(0);
|
|
1097
|
+
}
|
|
1098
|
+
if (!marker.pebble_slug || !marker.persona) {
|
|
1099
|
+
process.exit(0);
|
|
1100
|
+
}
|
|
1101
|
+
let input = 0, output = 0, cacheRead = 0, cacheCreate = 0;
|
|
1102
|
+
let minTs = null, maxTs = null;
|
|
1103
|
+
try {
|
|
1104
|
+
const raw = readFileSync12(opts.transcript, "utf-8");
|
|
1105
|
+
for (const line of raw.split("\n")) {
|
|
1106
|
+
if (!line.trim()) continue;
|
|
1107
|
+
let obj;
|
|
1108
|
+
try {
|
|
1109
|
+
obj = JSON.parse(line);
|
|
1110
|
+
} catch {
|
|
1111
|
+
continue;
|
|
1112
|
+
}
|
|
1113
|
+
if (obj.type !== "assistant") continue;
|
|
1114
|
+
const u = obj.message?.usage;
|
|
1115
|
+
if (!u) continue;
|
|
1116
|
+
input += Number(u.input_tokens ?? 0);
|
|
1117
|
+
output += Number(u.output_tokens ?? 0);
|
|
1118
|
+
cacheRead += Number(u.cache_read_input_tokens ?? 0);
|
|
1119
|
+
cacheCreate += Number(u.cache_creation_input_tokens ?? 0);
|
|
1120
|
+
const ts = obj.timestamp;
|
|
1121
|
+
if (ts) {
|
|
1122
|
+
if (!minTs || ts < minTs) minTs = ts;
|
|
1123
|
+
if (!maxTs || ts > maxTs) maxTs = ts;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
} catch {
|
|
1127
|
+
process.exit(0);
|
|
1128
|
+
}
|
|
1129
|
+
const payload = {
|
|
1130
|
+
persona: marker.persona,
|
|
1131
|
+
session_id: opts.sessionId,
|
|
1132
|
+
input_tokens: input,
|
|
1133
|
+
output_tokens: output,
|
|
1134
|
+
cache_read_tokens: cacheRead,
|
|
1135
|
+
cache_creation_tokens: cacheCreate,
|
|
1136
|
+
bet_id: marker.bet_id ?? null,
|
|
1137
|
+
plan_id: marker.plan_id ?? null,
|
|
1138
|
+
phase_id: marker.phase_id ?? null,
|
|
1139
|
+
started_at: minTs,
|
|
1140
|
+
ended_at: maxTs
|
|
1141
|
+
};
|
|
1142
|
+
const res = await apiRequest(
|
|
1143
|
+
`/pebbles/${marker.pebble_slug}/persona-runs`,
|
|
1144
|
+
{ method: "POST", body: payload }
|
|
1145
|
+
);
|
|
1146
|
+
if (res.error) {
|
|
1147
|
+
process.stderr.write(`odin persona-runs capture: ${res.error}
|
|
1148
|
+
`);
|
|
1149
|
+
process.exit(1);
|
|
1150
|
+
}
|
|
1151
|
+
process.stdout.write(JSON.stringify(res.data) + "\n");
|
|
1152
|
+
});
|
|
1153
|
+
|
|
1154
|
+
// src/index.ts
|
|
1155
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
870
1156
|
import { fileURLToPath } from "url";
|
|
871
1157
|
import { dirname as dirname2, resolve } from "path";
|
|
872
1158
|
var __dirname = dirname2(fileURLToPath(import.meta.url));
|
|
873
|
-
var pkg = JSON.parse(
|
|
1159
|
+
var pkg = JSON.parse(readFileSync13(resolve(__dirname, "../package.json"), "utf-8"));
|
|
874
1160
|
var GOLD = "\x1B[33m";
|
|
875
1161
|
var DIM = "\x1B[2m";
|
|
876
1162
|
var RESET = "\x1B[0m";
|
|
@@ -888,7 +1174,7 @@ ${RESET}
|
|
|
888
1174
|
${DIM}${cwd}${RESET}
|
|
889
1175
|
`);
|
|
890
1176
|
}
|
|
891
|
-
var program = new
|
|
1177
|
+
var program = new Command18();
|
|
892
1178
|
program.name("odin").description("CLI for Odin \u2014 the knowledge backbone for Pebble House").version(VERSION);
|
|
893
1179
|
program.command("login").description("Authenticate with Odin via browser").action(async () => {
|
|
894
1180
|
printBanner();
|
|
@@ -916,6 +1202,10 @@ program.addCommand(guidelinesCmd);
|
|
|
916
1202
|
program.addCommand(rulesCmd);
|
|
917
1203
|
program.addCommand(briefsCmd);
|
|
918
1204
|
program.addCommand(blueprintsCmd);
|
|
1205
|
+
program.addCommand(betsCmd);
|
|
1206
|
+
program.addCommand(tasksCmd);
|
|
1207
|
+
program.addCommand(roadmapsCmd);
|
|
1208
|
+
program.addCommand(personaRunsCmd);
|
|
919
1209
|
process.on("exit", () => {
|
|
920
1210
|
process.stderr.write("\n\n\n\n\n");
|
|
921
1211
|
});
|