@tryglen/cli 0.2.0 → 0.4.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 (77) hide show
  1. package/README.md +80 -0
  2. package/dist/_utils/agent-adapter.d.ts +19 -0
  3. package/dist/_utils/agent-adapter.js +50 -0
  4. package/dist/_utils/agent-adapter.js.map +1 -0
  5. package/dist/_utils/build-turn-body.d.ts +2 -1
  6. package/dist/_utils/build-turn-body.js +3 -0
  7. package/dist/_utils/build-turn-body.js.map +1 -1
  8. package/dist/_utils/config.d.ts +2 -2
  9. package/dist/_utils/config.js +2 -2
  10. package/dist/_utils/config.js.map +1 -1
  11. package/dist/_utils/git-context.d.ts +10 -0
  12. package/dist/_utils/git-context.js +32 -0
  13. package/dist/_utils/git-context.js.map +1 -0
  14. package/dist/_utils/glen-headers.d.ts +8 -0
  15. package/dist/_utils/glen-headers.js +8 -0
  16. package/dist/_utils/glen-headers.js.map +1 -0
  17. package/dist/_utils/http.d.ts +1 -0
  18. package/dist/_utils/http.js +1 -0
  19. package/dist/_utils/http.js.map +1 -1
  20. package/dist/_utils/idempotency-key.d.ts +1 -1
  21. package/dist/_utils/idempotency-key.js +6 -2
  22. package/dist/_utils/idempotency-key.js.map +1 -1
  23. package/dist/_utils/state-line.d.ts +3 -0
  24. package/dist/_utils/state-line.js +10 -0
  25. package/dist/_utils/state-line.js.map +1 -0
  26. package/dist/_utils/state.d.ts +13 -0
  27. package/dist/_utils/state.js +41 -0
  28. package/dist/_utils/state.js.map +1 -0
  29. package/dist/_utils/update.d.ts +11 -0
  30. package/dist/_utils/update.js +122 -0
  31. package/dist/_utils/update.js.map +1 -0
  32. package/dist/_utils/version.d.ts +2 -0
  33. package/dist/_utils/version.js +10 -0
  34. package/dist/_utils/version.js.map +1 -0
  35. package/dist/_utils/which.d.ts +6 -0
  36. package/dist/_utils/which.js +16 -0
  37. package/dist/_utils/which.js.map +1 -0
  38. package/dist/bin.js +116 -16
  39. package/dist/bin.js.map +1 -1
  40. package/dist/commands/doctor.d.ts +13 -0
  41. package/dist/commands/doctor.js +91 -0
  42. package/dist/commands/doctor.js.map +1 -0
  43. package/dist/commands/incognito.d.ts +3 -0
  44. package/dist/commands/incognito.js +19 -0
  45. package/dist/commands/incognito.js.map +1 -0
  46. package/dist/commands/ingest.d.ts +1 -1
  47. package/dist/commands/ingest.js +59 -9
  48. package/dist/commands/ingest.js.map +1 -1
  49. package/dist/commands/install.js +146 -27
  50. package/dist/commands/install.js.map +1 -1
  51. package/dist/commands/login.js +26 -1
  52. package/dist/commands/login.js.map +1 -1
  53. package/dist/commands/logout.js +2 -0
  54. package/dist/commands/logout.js.map +1 -1
  55. package/dist/commands/onboard.d.ts +3 -0
  56. package/dist/commands/onboard.js +20 -0
  57. package/dist/commands/onboard.js.map +1 -0
  58. package/dist/commands/org.d.ts +4 -0
  59. package/dist/commands/org.js +80 -0
  60. package/dist/commands/org.js.map +1 -0
  61. package/dist/commands/search.js +29 -5
  62. package/dist/commands/search.js.map +1 -1
  63. package/dist/commands/session-start.d.ts +19 -0
  64. package/dist/commands/session-start.js +57 -0
  65. package/dist/commands/session-start.js.map +1 -0
  66. package/dist/commands/status.js +24 -5
  67. package/dist/commands/status.js.map +1 -1
  68. package/dist/commands/statusline.d.ts +13 -0
  69. package/dist/commands/statusline.js +38 -0
  70. package/dist/commands/statusline.js.map +1 -0
  71. package/dist/commands/update.d.ts +7 -0
  72. package/dist/commands/update.js +35 -0
  73. package/dist/commands/update.js.map +1 -0
  74. package/package.json +1 -1
  75. package/dist/commands/private.d.ts +0 -6
  76. package/dist/commands/private.js +0 -40
  77. package/dist/commands/private.js.map +0 -1
@@ -1,36 +1,151 @@
1
1
  import { execFileSync } from "node:child_process";
2
+ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import { dirname, join } from "node:path";
2
5
  import prompts from "prompts";
3
- import { err, ok } from "../_utils/result.js";
6
+ import { readCredentials } from "../_utils/credentials.js";
7
+ import { err, fromPromise, ok } from "../_utils/result.js";
8
+ import { isInstalled } from "../_utils/which.js";
9
+ import { login } from "./login.js";
10
+ // ---------------------------------------------------------------------------
11
+ // Settings path (GLEN_CLAUDE_SETTINGS_PATH env var is for test overrides only)
12
+ // ---------------------------------------------------------------------------
13
+ const claudeSettingsPath = () => process.env.GLEN_CLAUDE_SETTINGS_PATH ??
14
+ join(homedir(), ".claude", "settings.json");
4
15
  const AGENTS = [
5
16
  {
6
17
  name: "Claude Code",
7
18
  bin: "claude",
8
- installArgs: ["plugin", "install", "tryglen/glen-claude-code-plugin"],
19
+ steps: [
20
+ ["plugin", "marketplace", "add", "Glen-Web-App/glen-claude-code-plugin"],
21
+ ["plugin", "install", "glen@glen"],
22
+ ],
23
+ postInstall: "claude",
9
24
  },
10
25
  {
11
26
  name: "Codex",
12
27
  bin: "codex",
13
- installArgs: ["plugin", "install", "tryglen/glen-codex-plugin"],
28
+ steps: [
29
+ ["plugin", "marketplace", "add", "Glen-Web-App/glen-codex-plugin"],
30
+ ["plugin", "add", "glen"],
31
+ ],
32
+ postInstall: "codex",
14
33
  },
15
34
  ];
16
- const isInstalled = (bin) => {
17
- const r = (() => {
18
- try {
19
- execFileSync("which", [bin], { stdio: "ignore" });
20
- return true;
35
+ // ---------------------------------------------------------------------------
36
+ // Step label: last two args make a readable name ("marketplace add", "install glen@glen")
37
+ // ---------------------------------------------------------------------------
38
+ const stepLabel = (step) => step.slice(1).join(" ");
39
+ // ---------------------------------------------------------------------------
40
+ // Statusline opt-in for Claude Code
41
+ // ---------------------------------------------------------------------------
42
+ const handleClaudeStatusline = async () => {
43
+ const response = await prompts({
44
+ type: "confirm",
45
+ name: "statusline",
46
+ message: "Show glen in your Claude Code status line?",
47
+ initial: true,
48
+ });
49
+ if (!response.statusline)
50
+ return;
51
+ const filePath = claudeSettingsPath();
52
+ // Read the existing settings file; missing → treat as {}
53
+ const rawResult = await fromPromise(readFile(filePath, "utf-8"));
54
+ let existingSettings = {};
55
+ let parseFailed = false;
56
+ if (rawResult.ok) {
57
+ const parseResult = await fromPromise(new Promise((resolve) => resolve(JSON.parse(rawResult.value))));
58
+ if (parseResult.ok &&
59
+ parseResult.value &&
60
+ typeof parseResult.value === "object") {
61
+ existingSettings = parseResult.value;
21
62
  }
22
- catch {
23
- return false;
63
+ else {
64
+ // Parse failure — treat as existing-with-statusline (don't touch)
65
+ parseFailed = true;
24
66
  }
25
- })();
26
- return r;
67
+ }
68
+ // If statusLine already exists, print snippet + merge note; do NOT touch
69
+ if (parseFailed || "statusLine" in existingSettings) {
70
+ process.stdout.write(" ℹ statusLine already configured. To add glen, merge this into your existing command:\n");
71
+ process.stdout.write(` "statusLine": { "type": "command", "command": "glen statusline" }\n`);
72
+ process.stdout.write(` (manual merge required — glen won't overwrite your existing statusLine)\n`);
73
+ return;
74
+ }
75
+ // Write back with statusLine key added — atomic tmp+rename
76
+ const updated = {
77
+ ...existingSettings,
78
+ statusLine: { type: "command", command: "glen statusline" },
79
+ };
80
+ const mk = await fromPromise(mkdir(dirname(filePath), { recursive: true }));
81
+ if (!mk.ok) {
82
+ process.stdout.write(" ✗ Could not create .claude directory.\n");
83
+ return;
84
+ }
85
+ const tmp = `${filePath}.tmp`;
86
+ const w = await fromPromise(writeFile(tmp, JSON.stringify(updated, null, 2)));
87
+ if (!w.ok) {
88
+ process.stdout.write(" ✗ Could not write settings file.\n");
89
+ return;
90
+ }
91
+ const mv = await fromPromise(rename(tmp, filePath));
92
+ if (!mv.ok) {
93
+ process.stdout.write(" ✗ Could not finalize settings file.\n");
94
+ return;
95
+ }
96
+ process.stdout.write(" ✓ statusline configured\n");
27
97
  };
98
+ // ---------------------------------------------------------------------------
99
+ // Post-install actions per agent
100
+ // ---------------------------------------------------------------------------
101
+ const handlePostInstall = async (agent) => {
102
+ if (agent.postInstall === "codex") {
103
+ process.stdout.write("\n ⚠ One-time step: open Codex, run /hooks, and trust the glen hooks\n" +
104
+ " (Codex skips untrusted hooks silently — glen won't work until you do).\n");
105
+ }
106
+ else if (agent.postInstall === "claude") {
107
+ await handleClaudeStatusline();
108
+ process.stdout.write("\n Tip: enable auto-update for the glen marketplace in /plugin → Marketplaces.\n");
109
+ }
110
+ };
111
+ // ---------------------------------------------------------------------------
112
+ // Connect prompt — both install paths end here so a fresh user always gets
113
+ // nudged into `glen login`. Never prompts when non-interactive or logged in.
114
+ // ---------------------------------------------------------------------------
115
+ const promptConnect = async () => {
116
+ const creds = await readCredentials();
117
+ if (creds)
118
+ return;
119
+ if (!process.stdout.isTTY) {
120
+ process.stdout.write(" Run `glen login` to connect your account.\n\n");
121
+ return;
122
+ }
123
+ const response = await prompts({
124
+ type: "confirm",
125
+ name: "connect",
126
+ message: "Connect your glen account now?",
127
+ initial: true,
128
+ });
129
+ if (!response.connect) {
130
+ process.stdout.write(" Run `glen login` when you're ready.\n\n");
131
+ return;
132
+ }
133
+ const result = await login();
134
+ if (!result.ok) {
135
+ process.stdout.write(` ✗ login failed: ${result.error}\n`);
136
+ process.stdout.write(" Run `glen login` to try again.\n\n");
137
+ }
138
+ };
139
+ // ---------------------------------------------------------------------------
140
+ // Main install command
141
+ // ---------------------------------------------------------------------------
28
142
  const install = async () => {
29
- process.stdout.write("\n 🌿 glen — install agent plugins\n\n");
143
+ process.stdout.write("\n 🏔️ glen — install agent plugins\n\n");
30
144
  const detected = AGENTS.filter((a) => isInstalled(a.bin));
31
145
  if (detected.length === 0) {
32
146
  process.stdout.write(" ⚠ Could not find Claude Code or Codex installed.\n");
33
147
  process.stdout.write(" See https://tryglen.com/docs/plugins for manual install instructions.\n\n");
148
+ await promptConnect();
34
149
  return err("no agents detected");
35
150
  }
36
151
  process.stdout.write(" Detected coding agents:\n");
@@ -53,25 +168,29 @@ const install = async () => {
53
168
  const selected = (response.plugins ?? []);
54
169
  if (selected.length === 0) {
55
170
  process.stdout.write(" No plugins selected.\n");
171
+ await promptConnect();
56
172
  return ok(undefined);
57
173
  }
58
174
  for (const agent of selected) {
59
- process.stdout.write(` Installing ${agent.name} plugin... `);
60
- const installResult = (() => {
61
- try {
62
- execFileSync(agent.bin, agent.installArgs, {
63
- stdio: "ignore",
64
- });
65
- return true;
66
- }
67
- catch {
68
- return false;
69
- }
70
- })();
71
- process.stdout.write(installResult ? "✓\n" : "✗ (failed)\n");
175
+ process.stdout.write(`\n Installing ${agent.name} plugin:\n`);
176
+ for (const step of agent.steps) {
177
+ const label = stepLabel(step);
178
+ process.stdout.write(` ${label}... `);
179
+ const stepOk = (() => {
180
+ try {
181
+ execFileSync(agent.bin, step, { stdio: "ignore" });
182
+ return true;
183
+ }
184
+ catch {
185
+ return false;
186
+ }
187
+ })();
188
+ process.stdout.write(stepOk ? "✓\n" : "✗ (failed — continuing)\n");
189
+ }
190
+ await handlePostInstall(agent);
72
191
  }
73
192
  process.stdout.write("\n Done! Start a conversation in either agent — glen memory is active.\n");
74
- process.stdout.write(" Run `glen login` if you haven't connected yet.\n\n");
193
+ await promptConnect();
75
194
  return ok(undefined);
76
195
  };
77
196
  export { install };
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,7 @@ import { acquireLoginLock, releaseLoginLock } from "../_utils/login-lock.js";
7
7
  import { startLoopbackServer } from "../_utils/loopback-server.js";
8
8
  import { openBrowser } from "../_utils/open-browser.js";
9
9
  import { err, ok } from "../_utils/result.js";
10
+ import { writeState } from "../_utils/state.js";
10
11
  const WAIT_MS = 10 * 60_000;
11
12
  const login = async () => {
12
13
  const lockAcquired = await acquireLoginLock();
@@ -54,7 +55,31 @@ const login = async () => {
54
55
  });
55
56
  if (!writeResult.ok)
56
57
  return err("failed to write credentials");
57
- process.stdout.write("✓ Connected to glen. Memory is now active.\n");
58
+ // Defensively parse the org from the exchange payload.
59
+ // All three fields must be strings; anything else is treated as null.
60
+ const rawOrg = payload.org ?? null;
61
+ const org = rawOrg !== null &&
62
+ typeof rawOrg === "object" &&
63
+ typeof rawOrg.id === "string" &&
64
+ typeof rawOrg.slug === "string" &&
65
+ typeof rawOrg.name === "string"
66
+ ? rawOrg
67
+ : null;
68
+ if (org) {
69
+ const stateResult = await writeState({
70
+ activeOrgId: org.id,
71
+ activeOrgSlug: org.slug,
72
+ activeOrgName: org.name,
73
+ incognito: false,
74
+ });
75
+ if (stateResult.ok) {
76
+ process.stdout.write(`🏔️ Connected to glen — active org: ${org.name}. Memory is now active.\n`);
77
+ return ok(undefined);
78
+ }
79
+ // writeState failed — credentials already saved, so login succeeded.
80
+ // Fall through to the org-switch hint below.
81
+ }
82
+ process.stdout.write("🏔️ Connected to glen. Run `glen org switch` to pick an organization.\n");
58
83
  return ok(undefined);
59
84
  };
60
85
  export { login };
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import { clearCredentials } from "../_utils/credentials.js";
2
2
  import { releaseLoginLock } from "../_utils/login-lock.js";
3
3
  import { ok } from "../_utils/result.js";
4
+ import { clearState } from "../_utils/state.js";
4
5
  const logout = async () => {
5
6
  await clearCredentials();
7
+ await clearState();
6
8
  await releaseLoginLock();
7
9
  process.stdout.write("✓ Signed out of glen (credentials removed).\n");
8
10
  return ok(undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAe,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAEtD,MAAM,MAAM,GAAG,KAAK,IAAmC,EAAE;IACvD,MAAM,gBAAgB,EAAE,CAAC;IACzB,MAAM,gBAAgB,EAAE,CAAC;IACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACtE,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAe,EAAE,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,MAAM,GAAG,KAAK,IAAmC,EAAE;IACvD,MAAM,gBAAgB,EAAE,CAAC;IACzB,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,gBAAgB,EAAE,CAAC;IACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACtE,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Result } from "../_utils/result.js";
2
+ declare const maybeOnboard: () => Promise<Result<"ran" | "skip", string>>;
3
+ export { maybeOnboard };
@@ -0,0 +1,20 @@
1
+ import { readCredentials } from "../_utils/credentials.js";
2
+ import { ok } from "../_utils/result.js";
3
+ import { install } from "./install.js";
4
+ // First-run onboarding for bare `glen`. Fires only on a fresh interactive
5
+ // setup (no credentials + TTY); everything else returns "skip" so bin.ts
6
+ // falls through to help. The connect/login prompt chains inside install().
7
+ const maybeOnboard = async () => {
8
+ const creds = await readCredentials();
9
+ if (creds || !process.stdout.isTTY)
10
+ return ok("skip");
11
+ process.stdout.write("\n 🏔️ glen — let's get you set up\n");
12
+ // install() prints its own guidance for every outcome (including "no
13
+ // agents detected", an err) — onboarding continues to the summary regardless.
14
+ await install();
15
+ process.stdout.write("\n That's it! Open Claude Code or Codex — glen runs automatically.\n" +
16
+ " Anytime: `glen status` · `glen org switch` · `glen --help`\n\n");
17
+ return ok("ran");
18
+ };
19
+ export { maybeOnboard };
20
+ //# sourceMappingURL=onboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onboard.js","sourceRoot":"","sources":["../../src/commands/onboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAe,EAAE,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,MAAM,YAAY,GAAG,KAAK,IAA6C,EAAE;IACvE,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,IAAI,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IAEtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAE9D,qEAAqE;IACrE,8EAA8E;IAC9E,MAAM,OAAO,EAAE,CAAC;IAEhB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uEAAuE;QACrE,kEAAkE,CACrE,CAAC;IACF,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;AACnB,CAAC,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type Result } from "../_utils/result.js";
2
+ declare const orgList: () => Promise<Result<void, string>>;
3
+ declare const orgSwitch: (slug?: string) => Promise<Result<void, string>>;
4
+ export { orgList, orgSwitch };
@@ -0,0 +1,80 @@
1
+ import prompts from "prompts";
2
+ import { config } from "../_utils/config.js";
3
+ import { readCredentials } from "../_utils/credentials.js";
4
+ import { buildGlenHeaders } from "../_utils/glen-headers.js";
5
+ import { httpJson } from "../_utils/http.js";
6
+ import { err, ok } from "../_utils/result.js";
7
+ import { readState, writeState } from "../_utils/state.js";
8
+ import { cliVersion } from "../_utils/version.js";
9
+ const fetchOrgs = async () => {
10
+ const creds = await readCredentials();
11
+ if (!creds)
12
+ return err("Not connected. Run `glen login` first.");
13
+ const state = await readState();
14
+ const res = await httpJson(config.listOrgsUrl, {
15
+ method: "POST",
16
+ headers: {
17
+ "content-type": "application/json",
18
+ ...buildGlenHeaders({ key: creds.key, state, version: cliVersion }),
19
+ },
20
+ body: JSON.stringify({}),
21
+ timeoutMs: config.listOrgsTimeoutMs,
22
+ });
23
+ if (!res.ok)
24
+ return err("Could not reach glen (network error).");
25
+ if (res.value.status === 401 || res.value.status === 403)
26
+ return err("Your session lost its organization. Run `glen login` to reconnect.");
27
+ if (!res.value.isOk)
28
+ return err(`glen returned HTTP ${res.value.status}.`);
29
+ const orgs = res.value.json?.orgs;
30
+ if (!orgs)
31
+ return err("Unexpected response from glen.");
32
+ return ok(orgs);
33
+ };
34
+ const applySwitch = async (target) => {
35
+ const current = await readState();
36
+ const w = await writeState({
37
+ activeOrgId: target.orgId,
38
+ activeOrgSlug: target.slug,
39
+ activeOrgName: target.name,
40
+ incognito: current?.incognito ?? false,
41
+ });
42
+ if (!w.ok)
43
+ return err("Failed to write state file.");
44
+ process.stdout.write(`🏔️ Active organization is now ${target.name} (${target.slug}).\n`);
45
+ return ok(undefined);
46
+ };
47
+ const orgList = async () => {
48
+ const orgs = await fetchOrgs();
49
+ if (!orgs.ok)
50
+ return orgs;
51
+ for (const o of orgs.value)
52
+ process.stdout.write(`${o.active ? "✓" : " "} ${o.slug} ${o.name}\n`);
53
+ return ok(undefined);
54
+ };
55
+ const orgSwitch = async (slug) => {
56
+ const orgs = await fetchOrgs();
57
+ if (!orgs.ok)
58
+ return orgs;
59
+ if (slug) {
60
+ const target = orgs.value.find((o) => o.slug === slug || o.orgId === slug);
61
+ if (!target)
62
+ return err(`No organization "${slug}". Available: ${orgs.value.map((o) => o.slug).join(", ")}`);
63
+ return applySwitch(target);
64
+ }
65
+ const response = await prompts({
66
+ type: "select",
67
+ name: "org",
68
+ message: "Select an organization",
69
+ choices: orgs.value.map((o) => ({
70
+ title: `${o.name} (${o.slug})`,
71
+ value: o,
72
+ })),
73
+ initial: Math.max(0, orgs.value.findIndex((o) => o.active)),
74
+ });
75
+ if (!response.org)
76
+ return ok(undefined);
77
+ return applySwitch(response.org);
78
+ };
79
+ export { orgList, orgSwitch };
80
+ //# sourceMappingURL=org.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"org.js","sourceRoot":"","sources":["../../src/commands/org.ts"],"names":[],"mappings":"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"}
@@ -1,25 +1,49 @@
1
1
  import { config } from "../_utils/config.js";
2
- import { resolveAuthHeader } from "../_utils/credentials.js";
2
+ import { readCredentials } from "../_utils/credentials.js";
3
+ import { gitContext } from "../_utils/git-context.js";
4
+ import { buildGlenHeaders } from "../_utils/glen-headers.js";
3
5
  import { httpJson } from "../_utils/http.js";
4
6
  import { err, ok } from "../_utils/result.js";
7
+ import { readState } from "../_utils/state.js";
8
+ import { handle426AndReexec, maybeSpawnBackgroundUpdate, } from "../_utils/update.js";
9
+ import { cliVersion } from "../_utils/version.js";
5
10
  const search = async (query) => {
11
+ void maybeSpawnBackgroundUpdate();
6
12
  if (!query.trim())
7
13
  return err({ code: 2, message: 'usage: glen search "<query>"' });
8
- const header = await resolveAuthHeader();
9
- if (!header)
14
+ const creds = await readCredentials();
15
+ if (!creds)
10
16
  return err({ code: 1, message: "glen: not connected — run `glen login`." });
17
+ const state = await readState();
18
+ // Assemble additionalContext for search. Apply the empty-context rule: only
19
+ // include when we have at least one non-empty group.
20
+ const workspaceCtx = gitContext(process.cwd());
21
+ const additionalContext = Object.keys(workspaceCtx).length > 0
22
+ ? { workspace: workspaceCtx }
23
+ : undefined;
24
+ const body = { query };
25
+ if (additionalContext !== undefined)
26
+ body.additionalContext = additionalContext;
11
27
  const res = await httpJson(config.searchUrl, {
12
28
  method: "POST",
13
29
  headers: {
14
30
  "content-type": "application/json",
15
- [header.headerName]: header.headerValue,
31
+ ...buildGlenHeaders({ key: creds.key, state, version: cliVersion }),
16
32
  },
17
- body: JSON.stringify({ query }),
33
+ body: JSON.stringify(body),
18
34
  timeoutMs: config.searchTimeoutMs,
19
35
  });
20
36
  if (!res.ok)
21
37
  return err({ code: 2, message: "glen search failed (network error)." });
38
+ if (res.value.status === 426)
39
+ handle426AndReexec(process.argv.slice(2));
22
40
  if (res.value.status === 401 || res.value.status === 403) {
41
+ if (res.value.rawText.includes("no active organization")) {
42
+ return err({
43
+ code: 1,
44
+ message: "No active organization. Run `glen org switch`.",
45
+ });
46
+ }
23
47
  // Don't clear credentials — a concurrent `glen login` may have just saved a fresh key.
24
48
  return err({
25
49
  code: 1,
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAe,GAAG,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,MAAM,GAAG,KAAK,EAClB,KAAa,EAC6C,EAAE;IAC5D,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QACf,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC,CAAC;IAEnE,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM;QACT,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;IAE9E,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE;QAC3C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,WAAW;SACxC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC;QAC/B,SAAS,EAAE,MAAM,CAAC,eAAe;KAClC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE;QACT,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC,CAAC;IAE1E,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACzD,uFAAuF;QACvF,OAAO,GAAG,CAAC;YACT,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,gEAAgE;SAC1E,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI;QACjB,OAAO,GAAG,CAAC;YACT,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,4BAA4B,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI;SAC1D,CAAC,CAAC;IAEL,MAAM,OAAO,GAAI,GAAG,CAAC,KAAK,CAAC,IAAuC,EAAE,OAAO,CAAC;IAC5E,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;QAC3C,CAAC,CAAC,GAAG,OAAO,IAAI;QAChB,CAAC,CAAC,kDAAkD,CACvD,CAAC;IACF,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAe,GAAG,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,MAAM,GAAG,KAAK,EAClB,KAAa,EAC6C,EAAE;IAC5D,KAAK,0BAA0B,EAAE,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QACf,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,8BAA8B,EAAE,CAAC,CAAC;IAEnE,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IACtC,IAAI,CAAC,KAAK;QACR,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;IAE9E,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAEhC,4EAA4E;IAC5E,qDAAqD;IACrD,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GACrB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC;QAClC,CAAC,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE;QAC7B,CAAC,CAAC,SAAS,CAAC;IAEhB,MAAM,IAAI,GAA4B,EAAE,KAAK,EAAE,CAAC;IAChD,IAAI,iBAAiB,KAAK,SAAS;QACjC,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IAE7C,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE;QAC3C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,GAAG,gBAAgB,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;SACpE;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;QAC1B,SAAS,EAAE,MAAM,CAAC,eAAe;KAClC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE;QACT,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC,CAAC;IAE1E,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG;QAAE,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAExE,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACzD,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,CAAC;YACzD,OAAO,GAAG,CAAC;gBACT,IAAI,EAAE,CAAC;gBACP,OAAO,EAAE,gDAAgD;aAC1D,CAAC,CAAC;QACL,CAAC;QACD,uFAAuF;QACvF,OAAO,GAAG,CAAC;YACT,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,gEAAgE;SAC1E,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI;QACjB,OAAO,GAAG,CAAC;YACT,IAAI,EAAE,CAAC;YACP,OAAO,EAAE,4BAA4B,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI;SAC1D,CAAC,CAAC;IAEL,MAAM,OAAO,GAAI,GAAG,CAAC,KAAK,CAAC,IAAuC,EAAE,OAAO,CAAC;IAC5E,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;QAC3C,CAAC,CAAC,GAAG,OAAO,IAAI;QAChB,CAAC,CAAC,kDAAkD,CACvD,CAAC;IACF,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;AACvB,CAAC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `glen session-start [--agent <agent>]` — called by the agent's SessionStart hook.
3
+ *
4
+ * The `--agent` option is accepted and currently unused; it keeps hook lines uniform
5
+ * across agent types so hooks.json can call `glen session-start --agent <agent>` now
6
+ * and we can make use of it later without updating hook configs.
7
+ *
8
+ * Behavior:
9
+ * 1. Fire `void maybeSpawnBackgroundUpdate()` (background TTL check; never blocks).
10
+ * 2. Read stdin (SessionStart event JSON, parsed defensively — tolerate garbage).
11
+ * 3. Read local session state.
12
+ * 4. Write ONE JSON object to stdout:
13
+ * - state exists → hookSpecificOutput.additionalContext = formatStateLine(state)
14
+ * + systemMessage at top level when incognito is ON
15
+ * - no state → hookSpecificOutput.additionalContext = "[glen] not connected — run `glen login`"
16
+ * 5. Always exit 0 — this hook must never block a session.
17
+ */
18
+ declare const sessionStart: () => Promise<void>;
19
+ export { sessionStart };
@@ -0,0 +1,57 @@
1
+ import { formatStateLine } from "../_utils/state-line.js";
2
+ import { readState } from "../_utils/state.js";
3
+ import { maybeSpawnBackgroundUpdate } from "../_utils/update.js";
4
+ // Reads stdin defensively (SessionStart hook event — parse lenient; may be empty
5
+ // or invalid and we must still work).
6
+ const readStdin = async () => {
7
+ const chunks = [];
8
+ for await (const chunk of process.stdin)
9
+ chunks.push(chunk);
10
+ return Buffer.concat(chunks).toString("utf8");
11
+ };
12
+ /**
13
+ * `glen session-start [--agent <agent>]` — called by the agent's SessionStart hook.
14
+ *
15
+ * The `--agent` option is accepted and currently unused; it keeps hook lines uniform
16
+ * across agent types so hooks.json can call `glen session-start --agent <agent>` now
17
+ * and we can make use of it later without updating hook configs.
18
+ *
19
+ * Behavior:
20
+ * 1. Fire `void maybeSpawnBackgroundUpdate()` (background TTL check; never blocks).
21
+ * 2. Read stdin (SessionStart event JSON, parsed defensively — tolerate garbage).
22
+ * 3. Read local session state.
23
+ * 4. Write ONE JSON object to stdout:
24
+ * - state exists → hookSpecificOutput.additionalContext = formatStateLine(state)
25
+ * + systemMessage at top level when incognito is ON
26
+ * - no state → hookSpecificOutput.additionalContext = "[glen] not connected — run `glen login`"
27
+ * 5. Always exit 0 — this hook must never block a session.
28
+ */
29
+ const sessionStart = async () => {
30
+ // Fire background update check — detached, never awaited so it doesn't block.
31
+ void maybeSpawnBackgroundUpdate();
32
+ // Drain stdin before state read (best-effort; ignore errors).
33
+ try {
34
+ await readStdin();
35
+ }
36
+ catch {
37
+ // Tolerate stdin errors — the hook must always produce output.
38
+ }
39
+ const state = await readState();
40
+ const additionalContext = state
41
+ ? (formatStateLine(state) ?? "[glen] not connected — run `glen login`")
42
+ : "[glen] not connected — run `glen login`";
43
+ const output = {
44
+ hookSpecificOutput: {
45
+ hookEventName: "SessionStart",
46
+ additionalContext,
47
+ },
48
+ ...(state?.incognito
49
+ ? {
50
+ systemMessage: "glen: incognito is ON — nothing will be recorded. Run `glen incognito off` to resume.",
51
+ }
52
+ : {}),
53
+ };
54
+ process.stdout.write(JSON.stringify(output));
55
+ };
56
+ export { sessionStart };
57
+ //# sourceMappingURL=session-start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-start.js","sourceRoot":"","sources":["../../src/commands/session-start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEjE,iFAAiF;AACjF,sCAAsC;AACtC,MAAM,SAAS,GAAG,KAAK,IAAqB,EAAE;IAC5C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK;QAAE,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,YAAY,GAAG,KAAK,IAAmB,EAAE;IAC7C,8EAA8E;IAC9E,KAAK,0BAA0B,EAAE,CAAC;IAElC,8DAA8D;IAC9D,IAAI,CAAC;QACH,MAAM,SAAS,EAAE,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;IACjE,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAEhC,MAAM,iBAAiB,GAAG,KAAK;QAC7B,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,yCAAyC,CAAC;QACvE,CAAC,CAAC,yCAAyC,CAAC;IAU9C,MAAM,MAAM,GAAuB;QACjC,kBAAkB,EAAE;YAClB,aAAa,EAAE,cAAc;YAC7B,iBAAiB;SAClB;QACD,GAAG,CAAC,KAAK,EAAE,SAAS;YAClB,CAAC,CAAC;gBACE,aAAa,EACX,uFAAuF;aAC1F;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;IAEF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -1,14 +1,33 @@
1
1
  import { config } from "../_utils/config.js";
2
2
  import { readCredentials } from "../_utils/credentials.js";
3
- import { err, ok } from "../_utils/result.js";
3
+ import { ok } from "../_utils/result.js";
4
+ import { readState } from "../_utils/state.js";
5
+ import { cliVersion } from "../_utils/version.js";
4
6
  const status = async () => {
5
- const creds = await readCredentials();
7
+ const [creds, state] = await Promise.all([readCredentials(), readState()]);
8
+ process.stdout.write(`🏔️ glen ${cliVersion}\n`);
6
9
  if (creds?.type === "apikey" && creds.key) {
7
- process.stdout.write(`glen: connected with an API key. Base: ${config.baseUrl}\n`);
10
+ process.stdout.write(` connected with an API key. Base: ${config.baseUrl}\n`);
11
+ }
12
+ else {
13
+ process.stdout.write(` not connected. Run \`glen login\` to connect. Base: ${config.baseUrl}\n`);
14
+ if (state) {
15
+ process.stdout.write(` org: ${state.activeOrgSlug ?? state.activeOrgId}${state.activeOrgName ? ` (${state.activeOrgName})` : ""}\n`);
16
+ process.stdout.write(` incognito: ${state.incognito ? "ON" : "off"}\n`);
17
+ }
18
+ else {
19
+ process.stdout.write(" org: none — run `glen org switch`\n");
20
+ }
8
21
  return ok(undefined);
9
22
  }
10
- process.stdout.write("glen: not connected. Run `glen login` to connect.\n");
11
- return err("not connected");
23
+ if (state) {
24
+ process.stdout.write(` org: ${state.activeOrgSlug ?? state.activeOrgId}${state.activeOrgName ? ` (${state.activeOrgName})` : ""}\n`);
25
+ process.stdout.write(` incognito: ${state.incognito ? "ON" : "off"}\n`);
26
+ }
27
+ else {
28
+ process.stdout.write(" org: none — run `glen org switch`\n");
29
+ }
30
+ return ok(undefined);
12
31
  };
13
32
  export { status };
14
33
  //# sourceMappingURL=status.js.map