@skrr-ai/cli 0.1.8 → 0.1.10

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 (170) hide show
  1. package/dist/base-command.d.ts +27 -0
  2. package/dist/base-command.js +83 -11
  3. package/dist/commands/agent/message/send.js +1 -1
  4. package/dist/commands/agents/chat.d.ts +1 -1
  5. package/dist/commands/agents/chat.js +1 -1
  6. package/dist/commands/browser/install.d.ts +1 -1
  7. package/dist/commands/browser/install.js +10 -2
  8. package/dist/commands/browser/mcp-config.js +3 -1
  9. package/dist/commands/browser/skill/show.js +1 -1
  10. package/dist/commands/browser/status.js +4 -1
  11. package/dist/commands/browser/uninstall.d.ts +1 -1
  12. package/dist/commands/browser/uninstall.js +10 -2
  13. package/dist/commands/browser.d.ts +1 -1
  14. package/dist/commands/browser.js +3 -3
  15. package/dist/commands/code/index.js +6 -3
  16. package/dist/commands/code/install.d.ts +61 -0
  17. package/dist/commands/code/install.js +247 -0
  18. package/dist/commands/code/oversky-agent.d.ts +2 -1
  19. package/dist/commands/code/oversky-agent.js +12 -8
  20. package/dist/commands/commands.js +1 -1
  21. package/dist/commands/context.js +1 -1
  22. package/dist/commands/create-token.js +1 -1
  23. package/dist/commands/daemon/byok.d.ts +1 -0
  24. package/dist/commands/daemon/byok.js +14 -1
  25. package/dist/commands/daemon/index.js +18 -7
  26. package/dist/commands/daemon/install.d.ts +1 -0
  27. package/dist/commands/daemon/install.js +22 -3
  28. package/dist/commands/daemon/logs.d.ts +1 -0
  29. package/dist/commands/daemon/logs.js +4 -0
  30. package/dist/commands/daemon/start.d.ts +1 -0
  31. package/dist/commands/daemon/start.js +15 -2
  32. package/dist/commands/daemon/status.d.ts +1 -0
  33. package/dist/commands/daemon/status.js +14 -1
  34. package/dist/commands/daemon/stop.d.ts +1 -0
  35. package/dist/commands/daemon/stop.js +14 -1
  36. package/dist/commands/daemon/uninstall.d.ts +1 -0
  37. package/dist/commands/daemon/uninstall.js +15 -2
  38. package/dist/commands/daemon/usage.d.ts +1 -0
  39. package/dist/commands/daemon/usage.js +5 -1
  40. package/dist/commands/doctor.js +2 -2
  41. package/dist/commands/github/allow-tools.d.ts +1 -0
  42. package/dist/commands/github/app/install.d.ts +1 -0
  43. package/dist/commands/github/app/status.d.ts +1 -0
  44. package/dist/commands/github/connect.d.ts +1 -0
  45. package/dist/commands/github/connections.d.ts +1 -0
  46. package/dist/commands/github/disconnect.d.ts +1 -0
  47. package/dist/commands/github/finalize.d.ts +1 -0
  48. package/dist/commands/github/reconnect.d.ts +1 -0
  49. package/dist/commands/github/run.d.ts +1 -0
  50. package/dist/commands/github/tools.d.ts +1 -0
  51. package/dist/commands/goals/create.js +2 -2
  52. package/dist/commands/goals/show.js +5 -0
  53. package/dist/commands/harnesses/list.js +14 -3
  54. package/dist/commands/harnesses/show.js +14 -0
  55. package/dist/commands/instructions/activate.js +1 -1
  56. package/dist/commands/instructions/archive-version.js +1 -1
  57. package/dist/commands/instructions/delete.js +1 -1
  58. package/dist/commands/instructions/diff.js +1 -1
  59. package/dist/commands/instructions/install.js +7 -1
  60. package/dist/commands/instructions/restore.js +1 -1
  61. package/dist/commands/instructions/show.js +17 -1
  62. package/dist/commands/instructions/update.js +1 -1
  63. package/dist/commands/integrations/connections/connect.d.ts +1 -0
  64. package/dist/commands/integrations/connections/disconnect.d.ts +1 -0
  65. package/dist/commands/integrations/connections/finalize.d.ts +1 -0
  66. package/dist/commands/integrations/connections/list.d.ts +1 -0
  67. package/dist/commands/integrations/connections/reconnect.d.ts +1 -0
  68. package/dist/commands/integrations/execute.d.ts +1 -0
  69. package/dist/commands/integrations/search.d.ts +1 -0
  70. package/dist/commands/integrations/toolkits.d.ts +1 -0
  71. package/dist/commands/integrations/tools/allow.d.ts +1 -0
  72. package/dist/commands/integrations/tools/list.d.ts +1 -0
  73. package/dist/commands/list-daemons.d.ts +2 -7
  74. package/dist/commands/list-daemons.js +13 -13
  75. package/dist/commands/login.js +78 -33
  76. package/dist/commands/logout.js +52 -1
  77. package/dist/commands/machines/hosted/start.js +1 -1
  78. package/dist/commands/pair.js +2 -2
  79. package/dist/commands/projects/create.js +6 -1
  80. package/dist/commands/projects/tasks.js +6 -1
  81. package/dist/commands/revoke-daemon.js +6 -2
  82. package/dist/commands/set-capabilities.js +6 -2
  83. package/dist/commands/skills/install.js +1 -1
  84. package/dist/commands/skills/library.js +2 -2
  85. package/dist/commands/spaces/create.js +6 -2
  86. package/dist/commands/tasks/complete.d.ts +1 -1
  87. package/dist/commands/tasks/complete.js +21 -8
  88. package/dist/commands/tasks/create.js +4 -1
  89. package/dist/commands/tasks/current.js +1 -1
  90. package/dist/commands/tasks/delete.d.ts +1 -0
  91. package/dist/commands/tasks/delete.js +9 -0
  92. package/dist/commands/tasks/export.js +5 -1
  93. package/dist/commands/tasks/follow-up.js +2 -1
  94. package/dist/commands/tasks/list.js +5 -1
  95. package/dist/commands/tasks/pr.js +1 -1
  96. package/dist/commands/tasks/show.js +10 -1
  97. package/dist/commands/tasks/triage.js +2 -1
  98. package/dist/commands/tasks/update.js +4 -1
  99. package/dist/commands/tasks/upsert.js +4 -1
  100. package/dist/commands/usage.js +1 -1
  101. package/dist/commands/whoami.js +4 -1
  102. package/dist/lib/agentic-stream.js +21 -1
  103. package/dist/lib/api-fetch.d.ts +1 -1
  104. package/dist/lib/api-fetch.js +1 -1
  105. package/dist/lib/auth-core-init.js +23 -3
  106. package/dist/lib/auth-storage.d.ts +0 -12
  107. package/dist/lib/auth-storage.js +37 -2
  108. package/dist/lib/config.d.ts +43 -3
  109. package/dist/lib/config.js +391 -31
  110. package/dist/lib/created-line.d.ts +22 -0
  111. package/dist/lib/created-line.js +25 -0
  112. package/dist/lib/daemon-binding.d.ts +29 -0
  113. package/dist/lib/daemon-binding.js +63 -0
  114. package/dist/lib/daemon-ref.d.ts +31 -0
  115. package/dist/lib/daemon-ref.js +47 -0
  116. package/dist/lib/daemonBroker.js +1 -1
  117. package/dist/lib/delegated-cli.js +3 -3
  118. package/dist/lib/exec-oversky.d.ts +18 -1
  119. package/dist/lib/exec-oversky.js +21 -4
  120. package/dist/lib/html-text.d.ts +15 -0
  121. package/dist/lib/html-text.js +40 -0
  122. package/dist/lib/keychain.d.ts +43 -0
  123. package/dist/lib/keychain.js +145 -4
  124. package/dist/lib/login.js +3 -3
  125. package/dist/lib/node-adapter.js +1 -1
  126. package/dist/lib/oauthLogin.js +17 -6
  127. package/dist/lib/sky-code-agent.d.ts +1 -1
  128. package/dist/lib/sky-code-agent.js +8 -8
  129. package/dist/lib/sky-code-broker.js +18 -2
  130. package/dist/lib/sky-code-doctor.js +120 -4
  131. package/dist/lib/sky-code-managed.d.ts +12 -0
  132. package/dist/lib/sky-code-managed.js +21 -7
  133. package/dist/lib/sky-code.d.ts +16 -1
  134. package/dist/lib/sky-code.js +110 -7
  135. package/dist/lib/task-execution.js +4 -11
  136. package/dist/lib/tasks.d.ts +1 -0
  137. package/dist/lib/tasks.js +9 -6
  138. package/dist/lib/update-check.js +1 -1
  139. package/dist/lib/usage-discovery.js +1 -1
  140. package/dist/lib/web-url.js +12 -1
  141. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.d.ts +1 -1
  142. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/credentialResolver.js +2 -2
  143. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +1 -0
  144. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +13 -1
  145. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/kek/linux.js +16 -3
  146. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.d.ts +0 -9
  147. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/legacyStatePreflight.js +18 -1
  148. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/loginLocalhost.js +3 -3
  149. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/messages.js +3 -3
  150. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/runtime.d.ts +7 -3
  151. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.d.ts +96 -0
  152. package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/skyCodeChannels.js +115 -0
  153. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.d.ts +1 -1
  154. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/credentialResolver.js +2 -2
  155. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +1 -0
  156. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +1 -0
  157. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/kek/linux.js +16 -3
  158. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.d.ts +0 -9
  159. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/legacyStatePreflight.js +18 -1
  160. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/loginLocalhost.js +3 -3
  161. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/messages.js +3 -3
  162. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/runtime.d.ts +7 -3
  163. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.d.ts +96 -0
  164. package/dist/node_modules/@skrr-ai/auth-core/dist/esm/skyCodeChannels.js +107 -0
  165. package/dist/node_modules/@skrr-ai/auth-core/package.json +1 -1
  166. package/dist/node_modules/@skrr-ai/data-provider/index.js +4206 -4191
  167. package/dist/node_modules/@skrr-ai/inference-broker/dist/cjs/managed-inference-broker.js +2 -2
  168. package/dist/node_modules/@skrr-ai/inference-broker/dist/esm/managed-inference-broker.js +2 -2
  169. package/oclif.manifest.json +7969 -1397
  170. package/package.json +22 -19
@@ -7,6 +7,7 @@ const session_task_endpoints_1 = require("../../lib/session-task-endpoints");
7
7
  const base_command_1 = require("../../base-command");
8
8
  const task_resolver_1 = require("../../lib/task-resolver");
9
9
  const web_url_1 = require("../../lib/web-url");
10
+ const html_text_1 = require("../../lib/html-text");
10
11
  class TasksShow extends base_command_1.BaseCommand {
11
12
  static description = 'Show details for a single task (enriched)';
12
13
  static examples = [
@@ -115,6 +116,10 @@ class TasksShow extends base_command_1.BaseCommand {
115
116
  this.log(`Priority: ${t.priority ?? '-'}`);
116
117
  this.log(`Parent: ${t.parentId ?? '-'}`);
117
118
  this.log(`Space: ${t.spaceId ?? '-'}`);
119
+ // Printed beside Space and Goal because `--project` is accepted on create
120
+ // and update, and this was the only place to confirm it landed — there
121
+ // was no way to tell an ignored flag from an honoured one.
122
+ this.log(`Project: ${t.projectId ?? '-'}`);
118
123
  this.log(`Goal: ${t.goalId ?? '-'}`);
119
124
  this.log(`Author: ${t.author ?? '-'}`);
120
125
  const dri = t.dri;
@@ -199,7 +204,11 @@ class TasksShow extends base_command_1.BaseCommand {
199
204
  if (t.description) {
200
205
  this.log('');
201
206
  this.log('Description:');
202
- this.log(` ${t.description}`);
207
+ // Descriptions are stored as HTML, so printing the field verbatim showed
208
+ // the user `<p>` and `<code>` wrapped around the markdown they wrote.
209
+ for (const line of (0, html_text_1.htmlToDisplayText)(String(t.description)).split('\n')) {
210
+ this.log(` ${line}`);
211
+ }
203
212
  }
204
213
  const ref = String(t.id ?? t._id ?? taskIdentity.id);
205
214
  this.log('');
@@ -4,6 +4,7 @@ const core_1 = require("@oclif/core");
4
4
  const data_provider_1 = require("@skrr-ai/data-provider");
5
5
  const base_command_1 = require("../../base-command");
6
6
  const task_resolver_1 = require("../../lib/task-resolver");
7
+ const tasks_1 = require("../../lib/tasks");
7
8
  /**
8
9
  * A deliberately thin decision façade. Triage has no state machine of its own:
9
10
  * accepting and declining are ordinary TYPE-resolved moves, duplicate is the
@@ -29,7 +30,7 @@ class TasksTriage extends base_command_1.BaseCommand {
29
30
  static flags = {
30
31
  reason: core_1.Flags.string({ description: 'Reason returned to the task source when declining' }),
31
32
  priority: core_1.Flags.string({
32
- options: ['low', 'medium', 'high', 'critical'],
33
+ options: [...tasks_1.TASK_PRIORITIES],
33
34
  description: 'Priority to set before accepting',
34
35
  }),
35
36
  of: core_1.Flags.string({ description: 'Canonical task for the duplicate decision' }),
@@ -45,7 +45,10 @@ class TasksUpdate extends base_command_1.BaseCommand {
45
45
  description: 'Input format for --description or from-json description',
46
46
  options: ['html', 'markdown', 'plain'],
47
47
  }),
48
- priority: core_1.Flags.string({ description: 'New priority' }),
48
+ priority: core_1.Flags.string({
49
+ description: 'New priority',
50
+ options: [...tasks_1.TASK_PRIORITIES],
51
+ }),
49
52
  'start-date': core_1.Flags.string({ description: 'New planned start date (ISO string)' }),
50
53
  'due-date': core_1.Flags.string({ description: 'New due date (ISO string)' }),
51
54
  estimate: core_1.Flags.integer({ description: 'New estimate value from the Space estimate scale' }),
@@ -31,7 +31,10 @@ class TasksUpsert extends base_command_1.BaseCommand {
31
31
  description: 'Input format for --description or from-json description',
32
32
  options: ['html', 'markdown', 'plain'],
33
33
  }),
34
- priority: core_1.Flags.string({ description: 'Task priority' }),
34
+ priority: core_1.Flags.string({
35
+ description: 'Task priority',
36
+ options: [...tasks_1.TASK_PRIORITIES],
37
+ }),
35
38
  parent: core_1.Flags.string({ description: 'Parent task ID' }),
36
39
  space: core_1.Flags.string({ description: 'Space ID' }),
37
40
  goal: core_1.Flags.string({ description: 'Goal ID' }),
@@ -5,7 +5,7 @@ const base_command_1 = require("../base-command");
5
5
  const command_manifest_1 = require("../lib/command-manifest");
6
6
  const usage_discovery_1 = require("../lib/usage-discovery");
7
7
  class Usage extends base_command_1.BaseCommand {
8
- static description = 'Progressively discover Sky commands from the manifest, one token-budgeted domain at a time.';
8
+ static description = 'Progressively discover skrr commands from the manifest, one token-budgeted domain at a time.';
9
9
  static examples = [
10
10
  '<%= config.bin %> usage',
11
11
  '<%= config.bin %> usage tasks',
@@ -130,7 +130,10 @@ class Whoami extends base_command_1.BaseCommand {
130
130
  : '-';
131
131
  this.log(`Workspace: ${workspaceLabel}`);
132
132
  this.log(`Daemon ID: ${daemonId ?? '-'}`);
133
- this.log(`Server: ${this.cliConfig.baseURL}`);
133
+ // Named, not just spelled: `oversky.dev` and `skrr.ai` do not read as a
134
+ // dev/prod pair to anyone who has not seen the constants, and `whoami` is
135
+ // where the login message sends you to find out where you are (OSK-301).
136
+ this.log(`Server: ${(0, config_1.describeDeployment)(this.cliConfig.baseURL)}`);
134
137
  this.log(`Profile: ${(0, keychain_1.getActiveProfile)()}`);
135
138
  if (this.cliConfig.cliId) {
136
139
  this.log(`CLI ID: ${this.cliConfig.cliId}`);
@@ -8,6 +8,8 @@ exports.toWebSocketOrigin = toWebSocketOrigin;
8
8
  const node_readline_1 = require("node:readline");
9
9
  const socket_io_client_1 = require("socket.io-client");
10
10
  const data_provider_1 = require("@skrr-ai/data-provider");
11
+ const config_1 = require("./config");
12
+ const publicEndpoints_generated_1 = require("./publicEndpoints.generated");
11
13
  /**
12
14
  * Small Node-side adapter for the existing Agentic Socket.IO contract.
13
15
  * It deliberately normalizes only lifecycle/text/tool events; the server's
@@ -458,9 +460,27 @@ class AgenticStreamClient {
458
460
  }
459
461
  }
460
462
  exports.AgenticStreamClient = AgenticStreamClient;
463
+ /**
464
+ * Web apexes whose realtime traffic lives on their `api.` subdomain.
465
+ *
466
+ * Derived from the endpoint contract rather than written out, because the two
467
+ * hostnames used to be literals here and the domain cutover moved one of them:
468
+ * a CLI logged into the new prod apex fell through to `wss://<apex>`, which
469
+ * CloudFront cannot upgrade. Nothing errors at the call site — the socket just
470
+ * never connects, which reads as a network problem rather than a stale list.
471
+ *
472
+ * The retired prod apex stays, for the reverse reason: a config file written
473
+ * before the cutover still names it, and dropping it would strand exactly the
474
+ * sessions the entry exists to carry.
475
+ */
476
+ const REALTIME_APEXES = new Set([
477
+ new URL(publicEndpoints_generated_1.OVERSKY_ENVIRONMENT_ENDPOINTS.prod.appUrl).hostname,
478
+ new URL(publicEndpoints_generated_1.OVERSKY_ENVIRONMENT_ENDPOINTS.dev.appUrl).hostname,
479
+ new URL(config_1.LEGACY_PROD_BASE_URL).hostname,
480
+ ]);
461
481
  function toWebSocketOrigin(baseURL) {
462
482
  const url = new URL(baseURL);
463
- if (url.hostname === 'oversky.dev' || url.hostname === 'oversky.ai') {
483
+ if (REALTIME_APEXES.has(url.hostname)) {
464
484
  url.hostname = `api.${url.hostname}`;
465
485
  }
466
486
  url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
@@ -32,7 +32,7 @@ export declare class ApiFetchError extends Error {
32
32
  constructor(message: string, status: number, body?: string, code?: string);
33
33
  }
34
34
  /**
35
- * Call an skrr API endpoint with the current credential. Throws
35
+ * Call a skrr API endpoint with the current credential. Throws
36
36
  * `ApiFetchError` on any non-2xx status so callers can branch on
37
37
  * `err.status` / `err.code`.
38
38
  */
@@ -56,7 +56,7 @@ class ApiFetchError extends Error {
56
56
  }
57
57
  exports.ApiFetchError = ApiFetchError;
58
58
  /**
59
- * Call an skrr API endpoint with the current credential. Throws
59
+ * Call a skrr API endpoint with the current credential. Throws
60
60
  * `ApiFetchError` on any non-2xx status so callers can branch on
61
61
  * `err.status` / `err.code`.
62
62
  */
@@ -85,6 +85,26 @@ function ensureAuthCoreConfigured() {
85
85
  // Phase D: share the daemon's config root so auth.lock and the
86
86
  // needs-reauth flag are coordinated across binaries.
87
87
  configDir: () => node_path_1.default.join(node_os_1.default.homedir(), '.skrr'),
88
+ /**
89
+ * The machine root, PINNED — never the active profile's directory.
90
+ *
91
+ * `machineConfigDir` defaults to `configDir()`, and while the CLI's
92
+ * `configDir` was unconditionally `~/.skrr` that default was correct and
93
+ * this line would have been noise. It stops being correct the moment
94
+ * `configDir` becomes profile-aware: machine identity would start drifting
95
+ * per profile, and the server binds `cliId` into the JWT `did` claim and
96
+ * REFUSES a rotation presented against a different one. A second profile
97
+ * would not degrade — it would fail to stay logged in.
98
+ *
99
+ * The daemon already learned this the expensive way. OSK-1478: pinning the
100
+ * machine UUID to a profile-scoped `configDir` silently killed the
101
+ * `legacyDaemonUuids()` fold safety net, because it scanned
102
+ * `<profileDir>/profiles/*`, which never exists.
103
+ *
104
+ * Wired ahead of the profile work rather than with it, so the landmine is
105
+ * gone before anything can step on it.
106
+ */
107
+ machineConfigDir: () => node_path_1.default.join(node_os_1.default.homedir(), '.skrr'),
88
108
  logger: cliLogger,
89
109
  killSwitches: {
90
110
  // CLI shares the same kill-switch surface as the daemon for ops parity.
@@ -139,13 +159,13 @@ async function settlesWithin(promise, timeoutMs, keepTimerRef = false) {
139
159
  function encryptedCredentialInitError(timedOut, cause) {
140
160
  const state = (0, cred_envelope_1.describeCredEnvelopeState)();
141
161
  if (timedOut) {
142
- return new CliCredentialInitializationError('Stored Sky credentials are encrypted, but the local credential store did not ' +
162
+ return new CliCredentialInitializationError('Stored skrr credentials are encrypted, but the local credential store did not ' +
143
163
  `initialize within ${ENCRYPTED_CREDENTIAL_INIT_TIMEOUT_MS / 1000} seconds. ` +
144
- 'The credential remains protected; wait for other Sky processes to finish and retry.');
164
+ 'The credential remains protected; wait for other skrr processes to finish and retry.');
145
165
  }
146
166
  const detail = state.kind === 'disabled' && state.reason ? `${state.kind} (${state.reason})` : state.kind;
147
167
  const causeMessage = cause instanceof Error ? cause.message.trim().slice(0, 200) : '';
148
- return new CliCredentialInitializationError(`Stored Sky credentials are encrypted, but the local credential store is ${detail}. ` +
168
+ return new CliCredentialInitializationError(`Stored skrr credentials are encrypted, but the local credential store is ${detail}. ` +
149
169
  (causeMessage ? `Initialization failed: ${causeMessage}. ` : '') +
150
170
  'The credential remains protected; unlock or repair the OS credential store and retry.');
151
171
  }
@@ -33,18 +33,6 @@ export interface WriteOptions {
33
33
  * function returns whatever is persisted.
34
34
  */
35
35
  export declare function readFromBackend(expectedServerOrigin?: string): ReadResult;
36
- /**
37
- * Persist a token bundle to the preferred backend.
38
- *
39
- * Writes to keychain when available, file otherwise. If keychain writes
40
- * fail mid-flight (e.g., user canceled the unlock prompt), we fall back
41
- * to the file backend so the CLI remains functional.
42
- *
43
- * Returns the backend that actually accepted the write. Callers wanting
44
- * a specific backend (bare mode, store-mode overrides) should call the
45
- * lower-level write helpers directly — not exported here to keep the
46
- * default path honest.
47
- */
48
36
  export declare function writeToBackend(bundle: AuthBundle, options?: WriteOptions): AuthBackend;
49
37
  /**
50
38
  * Clear both backends. Called on `skrr logout` (and internally during
@@ -357,6 +357,37 @@ function readFromBackend(expectedServerOrigin) {
357
357
  * lower-level write helpers directly — not exported here to keep the
358
358
  * default path honest.
359
359
  */
360
+ /**
361
+ * Clear the DAEMON's needs-reauth latch as well as the CLI's own.
362
+ *
363
+ * `clearReauthState()` resolves `getAuthConfigDir()`, and the two binaries wire
364
+ * that differently: the CLI points auth-core at the machine root (`~/.skrr`),
365
+ * the daemon at its PROFILE dir (`~/.skrr/profiles/<profile>`). So the daemon
366
+ * latched at one path while `skrr login` cleared another — a file that on most
367
+ * machines does not exist at all, which made the clear a silent no-op.
368
+ *
369
+ * The visible cost was a loop with no exit: `skrr daemon status` reported
370
+ * "Cause: TOKEN_INVALID · Remedy: run `skrr login`", the login succeeded, and
371
+ * the flag never moved, so the daemon's realtime channel stayed down and it
372
+ * could not execute tasks. `auth-core-init.ts` states the intent — "share the
373
+ * daemon's config root so auth.lock and the needs-reauth flag are coordinated
374
+ * across binaries" — which stopped being true when the daemon became
375
+ * profile-scoped.
376
+ *
377
+ * The ACTIVE profile only, deliberately: a per-profile latch is correct because
378
+ * different profiles can hold different credentials, and a login re-authorises
379
+ * exactly the one it just wrote.
380
+ */
381
+ function clearDaemonProfileReauthState() {
382
+ try {
383
+ const target = path.join(os.homedir(), '.skrr', 'profiles', keychain.getActiveProfile(), 'needs-reauth.json');
384
+ fs.rmSync(target, { force: true });
385
+ }
386
+ catch {
387
+ // Best effort: the CLI's own latch is already cleared, and failing to
388
+ // remove the daemon's must not fail a login that otherwise succeeded.
389
+ }
390
+ }
360
391
  function writeToBackend(bundle, options = {}) {
361
392
  const requestedOrigin = options.serverOrigin ?? bundle.serverOrigin;
362
393
  let persistedBundle = bundle;
@@ -373,8 +404,10 @@ function writeToBackend(bundle, options = {}) {
373
404
  // Remove any stale file copy so we don't have two sources of truth.
374
405
  deleteFileBackend();
375
406
  backend = 'keychain';
376
- if (options.clearReauth)
407
+ if (options.clearReauth) {
377
408
  (0, auth_core_1.clearReauthState)();
409
+ clearDaemonProfileReauthState();
410
+ }
378
411
  return backend;
379
412
  }
380
413
  // Keychain failed — fall through to the file backend rather than
@@ -386,8 +419,10 @@ function writeToBackend(bundle, options = {}) {
386
419
  }
387
420
  writeToFile(persistedBundle);
388
421
  backend = 'file';
389
- if (options.clearReauth)
422
+ if (options.clearReauth) {
390
423
  (0, auth_core_1.clearReauthState)();
424
+ clearDaemonProfileReauthState();
425
+ }
391
426
  return backend;
392
427
  }
393
428
  /**
@@ -119,6 +119,19 @@ export declare function environmentForBaseURL(value: string): 'dev' | 'prod' | '
119
119
  * display and not harmless for routing, because two spellings of prod are two
120
120
  * different keys to anything comparing base URLs.
121
121
  */
122
+ /**
123
+ * A deployment, written so a human can tell which one it is.
124
+ *
125
+ * A published `npm i -g @skrr-ai/cli` defaults to the DEV deployment, and nothing
126
+ * in the login flow said so — you got "Signed in via browser" and no indication
127
+ * of which backend now holds your account (OSK-301). Naming the environment as
128
+ * well as the URL matters because `oversky.dev` and `skrr.ai` do not look like a
129
+ * dev/prod pair to anyone who has not read this file.
130
+ *
131
+ * Falls back to the bare URL for a deployment we do not recognise — a
132
+ * self-hosted or local server is legitimate, and labelling it would be a guess.
133
+ */
134
+ export declare function describeDeployment(baseURL: string): string;
122
135
  export declare function canonicalizeKnownBaseURL(value: string): string;
123
136
  /**
124
137
  * True when any auth-carrying env var is set. In this mode credentials are
@@ -128,9 +141,36 @@ export declare function canonicalizeKnownBaseURL(value: string): string;
128
141
  */
129
142
  export declare function isEnvAuthOverride(): boolean;
130
143
  /**
131
- * Read the config file. Returns defaults if missing. Throws on corrupt
132
- * JSON. Performs a one-shot legacy → new copy when only the legacy file
133
- * exists, so existing users don't have to re-login.
144
+ * Storage layout (Phase H+).
145
+ *
146
+ * Canonical: ~/.skrr/cli-config.json (metadata only)
147
+ * ~/.skrr/cli-auth.json (file-backend auth storage)
148
+ * Keychain (darwin-preferred auth storage)
149
+ * Legacy: ~/.sky/config.json (read-only fallback, copied forward once)
150
+ *
151
+ * The CLI shares the daemon's config root so `auth.lock` and
152
+ * `needs-reauth.json` are coordinated across binaries.
153
+ */
154
+ /**
155
+ * The skrr root for this process — the ONE place every root-derived path comes
156
+ * from.
157
+ *
158
+ * It is exported and takes `env` because the alternative is what this replaced:
159
+ * two functions each deriving the root themselves, one honouring the override
160
+ * and one not, disagreeing only when someone relocated their root (OSK-300).
161
+ * Fixing that by teaching the second function the same two variable names would
162
+ * have re-created the split the moment a third name appeared — and did, briefly,
163
+ * when `SKRR_CONFIG_DIR` was added to one side only.
164
+ *
165
+ * `SKRR_CONFIG_DIR` is the spelling for anything new (root CLAUDE.md) and wins
166
+ * when both are set. `OVERSKY_CONFIG_DIR` keeps working: the daemon, the engine
167
+ * resolver and every existing install read it.
168
+ */
169
+ export declare function configRoot(env?: NodeJS.ProcessEnv): string;
170
+ /**
171
+ * Read the config file. Returns defaults if missing. Throws on corrupt JSON.
172
+ * Performs a one-shot legacy → new copy when only the legacy file exists, so
173
+ * existing users don't have to re-login.
134
174
  */
135
175
  export declare function loadConfig(): CliConfig;
136
176
  /** Write the config file with mode 0600 inside a 0700 directory. */