@skrr-ai/cli 0.1.94 → 0.1.95
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/README.md +153 -165
- package/bin/run.js +32 -0
- package/bin/update-npm-runner.cjs +33 -0
- package/bin/update-session.cjs +194 -0
- package/bin/update-worker.cjs +208 -0
- package/dist/base-command.js +0 -15
- package/dist/commands/code/doctor.d.ts +1 -0
- package/dist/commands/code/doctor.js +6 -0
- package/dist/commands/code/index.js +4 -0
- package/dist/commands/code/install.d.ts +5 -62
- package/dist/commands/code/install.js +86 -279
- package/dist/commands/code/rollback.d.ts +8 -0
- package/dist/commands/code/rollback.js +20 -0
- package/dist/commands/code/update.d.ts +8 -37
- package/dist/commands/code/update.js +134 -213
- package/dist/commands/daemon/install.js +4 -0
- package/dist/commands/generate-recovery-code.d.ts +13 -1
- package/dist/commands/generate-recovery-code.js +146 -13
- package/dist/commands/instructions/guide.d.ts +20 -0
- package/dist/commands/instructions/guide.js +84 -0
- package/dist/commands/instructions/install.js +57 -33
- package/dist/commands/instructions/setup.d.ts +14 -0
- package/dist/commands/instructions/setup.js +72 -0
- package/dist/commands/integrations/execute.js +1 -1
- package/dist/commands/login.d.ts +5 -6
- package/dist/commands/login.js +27 -11
- package/dist/commands/logout.js +7 -7
- package/dist/commands/security/overview.d.ts +11 -0
- package/dist/commands/security/overview.js +158 -0
- package/dist/commands/spaces/claim.d.ts +12 -0
- package/dist/commands/spaces/claim.js +42 -0
- package/dist/commands/spaces/ownership.d.ts +12 -0
- package/dist/commands/spaces/ownership.js +46 -0
- package/dist/commands/tasks/cancel-cascade.js +1 -1
- package/dist/commands/tasks/create-tree.d.ts +5 -1
- package/dist/commands/tasks/create-tree.js +35 -7
- package/dist/commands/tasks/interrupt.js +2 -2
- package/dist/commands/tasks/pause-schedule.js +1 -1
- package/dist/commands/token/list.d.ts +3 -5
- package/dist/commands/token/list.js +99 -57
- package/dist/commands/update.d.ts +14 -0
- package/dist/commands/update.js +61 -0
- package/dist/generated/managed-instruction-guides.json +9 -0
- package/dist/hooks/init.d.ts +5 -0
- package/dist/hooks/init.js +27 -0
- package/dist/lib/commitments.d.ts +0 -8
- package/dist/lib/commitments.js +0 -52
- package/dist/lib/daemon-installer.d.ts +2 -0
- package/dist/lib/daemon-installer.js +100 -24
- package/dist/lib/first-party-harness-doctor.js +31 -1
- package/dist/lib/first-party-harness-remote-install.d.ts +71 -0
- package/dist/lib/first-party-harness-remote-install.js +310 -0
- package/dist/lib/first-party-harness-remote-update.d.ts +46 -0
- package/dist/lib/first-party-harness-remote-update.js +242 -0
- package/dist/lib/first-party-harness-startup-update.d.ts +26 -0
- package/dist/lib/first-party-harness-startup-update.js +166 -0
- package/dist/lib/first-party-harness-update.d.ts +46 -0
- package/dist/lib/first-party-harness-update.js +289 -0
- package/dist/lib/first-party-harness.js +7 -4
- package/dist/lib/managed-instruction-local.d.ts +12 -0
- package/dist/lib/managed-instruction-local.js +58 -0
- package/dist/lib/managed-instruction-setup.d.ts +35 -0
- package/dist/lib/managed-instruction-setup.js +306 -0
- package/dist/lib/memory-sync.d.ts +1 -0
- package/dist/lib/memory-sync.js +279 -68
- package/dist/lib/platform-update-local.d.ts +2 -0
- package/dist/lib/platform-update-local.js +113 -0
- package/dist/lib/platform-update.d.ts +39 -0
- package/dist/lib/platform-update.js +84 -0
- package/dist/lib/profile-machine-identity-guard.d.ts +2 -0
- package/dist/lib/profile-machine-identity-guard.js +13 -0
- package/dist/lib/prompt.d.ts +1 -0
- package/dist/lib/prompt.js +4 -3
- package/dist/lib/task-batch.d.ts +9 -0
- package/dist/lib/task-batch.js +94 -17
- package/dist/lib/task-instruction-offer.d.ts +1 -4
- package/dist/lib/task-instruction-offer.js +3 -129
- package/dist/lib/update-check.d.ts +61 -53
- package/dist/lib/update-check.js +453 -314
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.d.ts +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessChannels.js +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.d.ts +82 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessReleaseKeys.js +105 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.d.ts +110 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/firstPartyHarnessUpdater.js +945 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/harnessPermissionControls.js +62 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/index.js +4 -1
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/machineUuid.js +35 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.d.ts +63 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releasePolicy.js +169 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/cjs/releaseVersions.js +44 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.d.ts +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessChannels.js +3 -4
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.d.ts +82 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessReleaseKeys.js +102 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.d.ts +110 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/firstPartyHarnessUpdater.js +923 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.d.ts +32 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/harnessPermissionControls.js +59 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/index.js +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/machineUuid.js +35 -5
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.d.ts +63 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releasePolicy.js +163 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.d.ts +2 -0
- package/dist/node_modules/@skrr-ai/auth-core/dist/esm/releaseVersions.js +41 -0
- package/dist/node_modules/@skrr-ai/auth-core/package.json +31 -1
- package/dist/node_modules/@skrr-ai/data-provider/index.js +6584 -6567
- package/docs/v1/README.md +28 -0
- package/docs/v1/api.md +55 -0
- package/docs/v1/changelog.md +16 -0
- package/docs/v1/check-examples.mjs +178 -0
- package/docs/v1/examples/api-readonly.mjs +144 -0
- package/docs/v1/operations.md +87 -0
- package/docs/v1/quickstart.md +71 -0
- package/oclif.manifest.json +46007 -45462
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -2,6 +2,83 @@
|
|
|
2
2
|
|
|
3
3
|
Command-line interface for OverSky, wrapping the `@skrr-ai/data-provider` client.
|
|
4
4
|
|
|
5
|
+
|
|
6
|
+
## Start here
|
|
7
|
+
|
|
8
|
+
The supported executable is `skrr`. These [versioned developer guides](docs/v1/README.md) are included with the npm package; they do not require access to the private source repository. This guide set was checked against CLI **0.1.95** source on **2026-10-10**. Run `skrr --version` to identify your installed artifact; source availability is not evidence of a published release.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install -g @skrr-ai/cli
|
|
12
|
+
skrr --version
|
|
13
|
+
skrr login --base-url https://skrr.ai
|
|
14
|
+
skrr whoami
|
|
15
|
+
skrr spaces list --json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`login` first tries a signed-in local daemon, then browser PKCE, then a device code when the callback cannot run. With SSH or no local browser, use `skrr login --device-code`; approve it in a browser on another device. Password, MFA, passkey and configured federation challenges remain on the web sign-in page. The CLI has no password flag.
|
|
19
|
+
|
|
20
|
+
To create your first Task in an existing Space, copy its ID from `spaces list` and run:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
skrr tasks create --space <space-id> --title "My first CLI task" --execution-mode human --external-key onboarding/first-task --json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This creates a Task; it does not start an agent run. Use a Space whose automation is disabled if you are exploring. See the [quickstart](docs/v1/quickstart.md) for scope selection and safe retries, the [public API guide](docs/v1/api.md) for a read-only first API call, and [operations and recovery](docs/v1/operations.md) for credentials, errors, request IDs, quotas and upgrades. `skrr code` runs a coding agent in the current repository and can incur model/compute usage; run it only after choosing that execution context.
|
|
27
|
+
|
|
28
|
+
After installing the CLI, run `skrr login`. On an interactive sign-in, skrr can help set up
|
|
29
|
+
removable managed instructions for the coding agents on your computer. You select each
|
|
30
|
+
provider and choose automatic updates or a fixed current version; installing the CLI alone
|
|
31
|
+
does not change agent instruction files.
|
|
32
|
+
|
|
33
|
+
Run `skrr instructions setup` at any time to revisit provider choices. The setup verifies
|
|
34
|
+
the local daemon's account, server and profile, then previews the real file paths and checks
|
|
35
|
+
whether the agent can read them. Use `--provider codex --review` to inspect the exact content
|
|
36
|
+
without installing. To choose a different machine explicitly, pass `--daemon <id>`.
|
|
37
|
+
|
|
38
|
+
Automation never prompts. For an explicit installation, use
|
|
39
|
+
`skrr instructions setup --provider codex --update-policy latest --yes --json`.
|
|
40
|
+
Use `--update-policy pinned` to keep the current version, or `--review --json` to get a
|
|
41
|
+
read-only preflight. `skrr instructions status` confirms application by the daemon.
|
|
42
|
+
`skrr instructions guide task-management` loads the detailed workflow on demand.
|
|
43
|
+
It works offline and without sign-in, using a canonical guide generated into the CLI release.
|
|
44
|
+
|
|
45
|
+
## Local updates
|
|
46
|
+
|
|
47
|
+
These commands work without a cloud login or connected daemon:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
skrr update --check # CLI, Code and daemon offered versions
|
|
51
|
+
skrr update --status --json # local versions and recorded results; no network
|
|
52
|
+
skrr update # update installed components through their owners
|
|
53
|
+
skrr update --component daemon --restart
|
|
54
|
+
skrr code install # install the signed local Code engine
|
|
55
|
+
skrr code update # update it; existing sessions keep their release
|
|
56
|
+
skrr code update --check
|
|
57
|
+
skrr code rollback # restore the previous verified release
|
|
58
|
+
skrr code update --startup-checks off
|
|
59
|
+
skrr code update --startup-checks on
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Interactive `skrr code` sessions offer **Update and start**, **Skip once**,
|
|
63
|
+
**Skip this version** and **Disable startup checks** when a newer signed release is available. ACP, scripts,
|
|
64
|
+
JSON output, help and noninteractive launches do not display that prompt.
|
|
65
|
+
`SKRR_CODE_UPDATE_CHECK=0` disables startup checks; explicit update commands remain
|
|
66
|
+
available. Use `--daemon <id>` with `code install` or `code update` to target a
|
|
67
|
+
remote machine instead; that path uses account authentication.
|
|
68
|
+
|
|
69
|
+
The CLI automatically queues updates for private, writable, user-owned npm global
|
|
70
|
+
installations and waits for active CLI invocations to finish. Set
|
|
71
|
+
`OVERSKY_CLI_AUTO_UPDATE=0` to keep discovery while disabling automatic application.
|
|
72
|
+
Shared prefixes, Windows npm installations, project dependencies, source checkouts,
|
|
73
|
+
app bundles and runtime images show their owner's update command. Daemon automatic
|
|
74
|
+
updates require an eligible supervised installation with its update monitor enabled;
|
|
75
|
+
the unified status reports the live daemon's recorded posture.
|
|
76
|
+
|
|
77
|
+
Code and daemon rollback obey retained signed minimum versions. Unsigned or tampered
|
|
78
|
+
rollback artifacts cannot be used as verified releases. See the
|
|
79
|
+
[update lifecycle design](../docs/architecture/component-update-lifecycle-2026-10-10.md)
|
|
80
|
+
and the [release runbook](../docs/runbooks/cli-daemon-release.md) for storage and rollout.
|
|
81
|
+
|
|
5
82
|
## Status
|
|
6
83
|
|
|
7
84
|
**Comprehensive CRUD + workflow surface across the OverSky public API.**
|
|
@@ -38,7 +115,7 @@ observability), and shared links.
|
|
|
38
115
|
| **spaces widgets** | `list`, `add`, `remove` |
|
|
39
116
|
| **spaces skills** | `list`, `add`, `remove`, `pin` |
|
|
40
117
|
| **spaces labels** | `list`, `add`, `remove` (attach/detach; filter with `spaces list --label`) |
|
|
41
|
-
| **labels** | `list`, `palette`, `create`, `update`, `archive`, `restore`, `delete`, `reorder` (unified labels across `user` and `workspace` scopes)
|
|
118
|
+
| **labels** | `list`, `palette`, `create`, `update`, `archive`, `restore`, `delete`, `reorder` (unified labels across `user` and `workspace` scopes) |
|
|
42
119
|
| **chats triggers** | `show`, `set` |
|
|
43
120
|
| **dm** | `list`, `show`, `messages`, `threads`, `thread show/messages/follow/mute/share`, `send` (agent 1:1 main chat and Slack-style Thread controls) |
|
|
44
121
|
| **diagnostics** | `context`, `doctor`, `usage`, `commands` (agent-friendly runtime identity, readiness, progressive token-budgeted discovery, and complete machine-readable schemas) |
|
|
@@ -53,7 +130,7 @@ observability), and shared links.
|
|
|
53
130
|
| **tasks result** | `submit`, `show` (immutable Result versions and exact Review state) |
|
|
54
131
|
| **tasks resource** | `add`, `list` (versioned inputs, references, evidence, attachments, and Deliverables) |
|
|
55
132
|
| **tasks deliverable** | `add`, `list`, `confirm` (the user-facing produced-Resource workflow) |
|
|
56
|
-
| **tasks labels** | `list`, `create`, `delete`, `attach`, `detach`, `suggest` (label vocabulary + per-task attachment; `suggest` asks the model to pick from the declared vocabulary, advisory only)
|
|
133
|
+
| **tasks labels** | `list`, `create`, `delete`, `attach`, `detach`, `suggest` (label vocabulary + per-task attachment; `suggest` asks the model to pick from the declared vocabulary, advisory only) |
|
|
57
134
|
| **tasks approvals** | `list`, `create`, `delete`, `resolve` |
|
|
58
135
|
| **tasks attachments** | `list`, `delete`, `upload`, `download` |
|
|
59
136
|
| **integrations** | `toolkits`, `search`, `execute`, `tools list`, `tools allow`, `connections connect`, `connections list`, `connections finalize`, `connections disconnect`, `connections reconnect` |
|
|
@@ -66,27 +143,27 @@ observability), and shared links.
|
|
|
66
143
|
Recent conversations, optionally scoped to one agent, then the transcript:
|
|
67
144
|
|
|
68
145
|
```bash
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
146
|
+
skrr convos list --limit 10 # id, title, agent, updated
|
|
147
|
+
skrr convos list --agent <agent-id> # server-side agent scope
|
|
148
|
+
skrr convos list --search "login bug" --json # Meilisearch-backed
|
|
149
|
+
skrr messages list -c <convo-id> --limit 20 # newest 20 (default: whole transcript)
|
|
150
|
+
skrr messages show <convo-id> <message-id> # one message, full body
|
|
74
151
|
```
|
|
75
152
|
|
|
76
153
|
Tasks, and what the agent actually produced:
|
|
77
154
|
|
|
78
155
|
```bash
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
156
|
+
skrr tasks list --assignee-agent <agent-id> # what this agent is working on
|
|
157
|
+
skrr tasks show <task-id> # includes the Convo: pointer
|
|
158
|
+
skrr tasks result show <task-id> # current Result + exact Review
|
|
159
|
+
skrr tasks transcript <task-id> --assistant-only # full agent transcript, no prompt
|
|
160
|
+
skrr tasks comments list <task-id> # raw comment thread
|
|
84
161
|
```
|
|
85
162
|
|
|
86
163
|
One agent's recent work across all three surfaces:
|
|
87
164
|
|
|
88
165
|
```bash
|
|
89
|
-
|
|
166
|
+
skrr agents activity <agent-id> --limit 10 # merged DM + conversations + tasks feed
|
|
90
167
|
```
|
|
91
168
|
|
|
92
169
|
`--agent` / `agents activity` need a server that implements `?agentId=` on
|
|
@@ -96,7 +173,7 @@ conversations, and `agents activity` filters locally with a printed caveat.
|
|
|
96
173
|
|
|
97
174
|
### Production CLI Contract
|
|
98
175
|
|
|
99
|
-
|
|
176
|
+
skrr CLI is designed for both humans and daemon agents. New commands should
|
|
100
177
|
preserve these contracts:
|
|
101
178
|
|
|
102
179
|
- Positional args never read from stdin implicitly. Every `Args.string` must
|
|
@@ -107,21 +184,21 @@ preserve these contracts:
|
|
|
107
184
|
in JSON mode.
|
|
108
185
|
- Commands that accept `--from-json` also expose `--json`; typed flags override
|
|
109
186
|
JSON fields on conflict.
|
|
110
|
-
- Agent runtime scripts start with `
|
|
187
|
+
- Agent runtime scripts start with `skrr context --json`, then `skrr usage --json`.
|
|
111
188
|
It is the recommended command-discovery bootstrap: the overview is generated
|
|
112
189
|
from the oclif manifest and stays within a small token budget. Read exactly
|
|
113
|
-
the relevant reference next with `
|
|
114
|
-
`
|
|
190
|
+
the relevant reference next with `skrr usage tasks --json` (or the convenient
|
|
191
|
+
`skrr tasks usage --json` form), then use `skrr commands --schema "tasks list"`
|
|
115
192
|
only when the selected command needs its complete flag contract. Use
|
|
116
|
-
`
|
|
193
|
+
`skrr doctor --json` for auth/build readiness and `skrr commands --audit --json`
|
|
117
194
|
for command-surface hygiene.
|
|
118
195
|
- Side-effecting commands use explicit idempotency keys only when the caller
|
|
119
196
|
owns retry coordination. Daemon session commands derive stable defaults when
|
|
120
|
-
possible, such as `
|
|
197
|
+
possible, such as `skrr agent message send --text "..."`.
|
|
121
198
|
|
|
122
199
|
### Agent-initiated app voice calls
|
|
123
200
|
|
|
124
|
-
`
|
|
201
|
+
`skrr agent call` is a session-only consent flow, not a phone dialer. It reads
|
|
125
202
|
the Agent identity and owner target from `OVERSKY_SESSION_TOKEN`,
|
|
126
203
|
`OVERSKY_SESSION_ID`, and `OVERSKY_SESSION_AGENT_ID`; no flag or JSON field can
|
|
127
204
|
select another person. The user receives an in-app/push invitation and must
|
|
@@ -129,14 +206,14 @@ accept it before the normal LiveKit call is created.
|
|
|
129
206
|
|
|
130
207
|
```bash
|
|
131
208
|
# From an autonomous daemon session
|
|
132
|
-
|
|
209
|
+
skrr agent call request \
|
|
133
210
|
--reason "The production rollback decision needs you." \
|
|
134
211
|
--conversation <conversation-id> \
|
|
135
212
|
--expires-in 120 \
|
|
136
213
|
--json
|
|
137
214
|
|
|
138
|
-
|
|
139
|
-
|
|
215
|
+
skrr agent call show <call-id> --json
|
|
216
|
+
skrr agent call cancel <call-id> --json
|
|
140
217
|
```
|
|
141
218
|
|
|
142
219
|
The request is idempotent. With no explicit `--idempotency-key`, Sky derives a
|
|
@@ -152,12 +229,12 @@ default Sky CLI capability.
|
|
|
152
229
|
Run the hygiene audit before publishing CLI changes:
|
|
153
230
|
|
|
154
231
|
```bash
|
|
155
|
-
|
|
232
|
+
skrr commands --audit --json
|
|
156
233
|
```
|
|
157
234
|
|
|
158
235
|
### PSTN phone calls (Phase 2)
|
|
159
236
|
|
|
160
|
-
`
|
|
237
|
+
`skrr agent phone-call request --purpose "…"` is an explicit, autonomous-
|
|
161
238
|
session-only command. It does not accept a phone number, carrier setting,
|
|
162
239
|
caller ID, or recording option; the server derives the owner and agent and
|
|
163
240
|
uses only that owner's verified endpoint plus active, renewable consent.
|
|
@@ -179,9 +256,8 @@ or intentionally not exposed as request/response APIs:
|
|
|
179
256
|
has no SSE/WebSocket adapter — the node-adapter is pure request/response.
|
|
180
257
|
Chat streaming would need a separate client layer (Socket.io client + event
|
|
181
258
|
plumbing). This does not include persistent main-chat DM sends; use
|
|
182
|
-
`
|
|
183
|
-
- **
|
|
184
|
-
`twoFAPending`. The server supports these; the CLI does not.
|
|
259
|
+
`skrr agent message send --text "..." --json` for that agent-facing path.
|
|
260
|
+
- **Authentication**: browser/device-code sign-in delegates configured MFA, passkey and federation to the web sign-in page. There is no CLI password flow. See [authentication and revocation](docs/v1/operations.md#authentication-and-revocation).
|
|
185
261
|
- **Message delete**: `DELETE /api/messages/:convoId/:messageId` — server
|
|
186
262
|
only.
|
|
187
263
|
- **Tests**: the CLI has focused Jest coverage, but broader command/API
|
|
@@ -193,13 +269,15 @@ or intentionally not exposed as request/response APIs:
|
|
|
193
269
|
## Prerequisites
|
|
194
270
|
|
|
195
271
|
- Node.js 20+
|
|
196
|
-
-
|
|
272
|
+
- An account on your deployment (default: `https://skrr.ai`; `--env local` selects the configured local API)
|
|
197
273
|
- `@skrr-ai/data-provider` must be built — it's a workspace dep and the CLI
|
|
198
274
|
imports from its `dist/`
|
|
199
275
|
|
|
200
276
|
## Install
|
|
201
277
|
|
|
202
|
-
|
|
278
|
+
For end users: `npm install -g @skrr-ai/cli`. The package vendors its private workspace dependencies.
|
|
279
|
+
|
|
280
|
+
For contributors with a checkout, build from the repository root:
|
|
203
281
|
|
|
204
282
|
```bash
|
|
205
283
|
# 1. Install workspace deps (picks up cli/ because it was added to the root
|
|
@@ -228,8 +306,8 @@ From `cli/`:
|
|
|
228
306
|
Or globally, after `npm link` from `cli/`:
|
|
229
307
|
|
|
230
308
|
```bash
|
|
231
|
-
|
|
232
|
-
|
|
309
|
+
skrr login
|
|
310
|
+
skrr convos list --json
|
|
233
311
|
```
|
|
234
312
|
|
|
235
313
|
## GitHub tools from local runtimes
|
|
@@ -348,142 +426,48 @@ to `dist/` and the next invocation picks up the change.
|
|
|
348
426
|
|
|
349
427
|
## Commands
|
|
350
428
|
|
|
351
|
-
### `
|
|
352
|
-
|
|
353
|
-
Sign in to an OverSky instance.
|
|
354
|
-
|
|
355
|
-
**You probably don't need to run this at all.** If the local `oversky`
|
|
356
|
-
daemon is authenticated, every `sky` command silently auto-brokers a
|
|
357
|
-
sibling cli-scope token on first use — no `sky login`, no browser, no
|
|
358
|
-
device code, no user interaction whatsoever. See
|
|
359
|
-
[Auto-broker on first use](#auto-broker-on-first-use) below.
|
|
360
|
-
|
|
361
|
-
**When `sky login` is still useful:**
|
|
429
|
+
### `skrr login`
|
|
362
430
|
|
|
363
|
-
|
|
364
|
-
- You want to log in to a DIFFERENT server (`--base-url <url>`)
|
|
365
|
-
- The daemon isn't installed / isn't running, and you want sky alone
|
|
366
|
-
- You want to force a re-authentication (e.g. revoked refresh family)
|
|
367
|
-
|
|
368
|
-
**Behavior when invoked explicitly:**
|
|
369
|
-
|
|
370
|
-
- If the daemon is authed for the same server, `sky login` brokers the
|
|
371
|
-
handoff (still no browser).
|
|
372
|
-
- If the daemon is not running or not authed, the CLI runs its own
|
|
373
|
-
PKCE-localhost OAuth flow (popping your browser); device-code is the
|
|
374
|
-
secondary fallback (SSH, port-bind failure, `--device-code`).
|
|
431
|
+
Sign in to a deployment and profile. The order is a local daemon broker, browser PKCE with a localhost callback, then device code when the browser callback cannot run. `--device-code` skips both the broker and callback. A declined sign-in is not automatically retried through a different flow.
|
|
375
432
|
|
|
376
433
|
```bash
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
434
|
+
skrr login --base-url https://skrr.ai
|
|
435
|
+
skrr login --device-code
|
|
436
|
+
skrr login --profile reviewer --env dev
|
|
380
437
|
```
|
|
381
438
|
|
|
382
|
-
|
|
383
|
-
`~/.sky/config.json` and reused until you override it again.
|
|
384
|
-
|
|
385
|
-
Flags:
|
|
439
|
+
Configuration lives in `~/.skrr/cli-config.json`, or `~/.skrr/profiles/<name>/cli-config.json`. `SKRR_CONFIG_DIR` / `OVERSKY_CONFIG_DIR` can set a different root. Credentials live in the macOS Keychain or `cli-auth.json` (0600), not the legacy `~/.sky/config.json`; that path is read only for migration. Sessions are bound to their issuing server.
|
|
386
440
|
|
|
387
|
-
-
|
|
388
|
-
- `--device-code` — force the device-code flow (also skips the
|
|
389
|
-
daemon broker pre-flight)
|
|
390
|
-
- `--port <n>` — pin the localhost callback port (PKCE flow)
|
|
391
|
-
- `--scope <cli|daemon>` — token scope (default `cli`)
|
|
392
|
-
- `--recovery-code <code>` — non-interactive sign-in with a printable
|
|
393
|
-
recovery code
|
|
441
|
+
The web sign-in page handles password, two-factor, passkey and configured federation. The CLI never receives the password. `--recovery-code` redeems a printable recovery code; it can still require a confirmation step and is not an unattended CI credential. For a saved refresh family use `OVERSKY_REFRESH_TOKEN` with its matching `OVERSKY_CLI_ID`; a successful restore rotates the token, so do not reuse a bundle across machines or jobs.
|
|
394
442
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
- `OVERSKY_SKIP_DAEMON_BROKER=1` — disable the broker pre-flight
|
|
398
|
-
- `OVERSKY_FORCE_DEVICE_CODE=1` — same as `--device-code`
|
|
399
|
-
- `OVERSKY_REFRESH_TOKEN=...` + `OVERSKY_CLI_ID=...` — non-interactive
|
|
400
|
-
restore from a backed-up refresh token
|
|
401
|
-
|
|
402
|
-
2FA, OAuth, SAML, and LDAP are not yet supported via the interactive
|
|
403
|
-
PKCE / device-code flows. (The recovery-code path is unaffected.)
|
|
443
|
+
`OVERSKY_SKIP_DAEMON_BROKER=1` skips the broker. `SKRR_SKIP_DAEMON_HANDOFF=1` skips the optional post-login daemon setup. They control different steps. Login does not require installing the daemon for workspace/API management.
|
|
404
444
|
|
|
405
445
|
### Auto-broker on first use
|
|
406
446
|
|
|
407
|
-
|
|
408
|
-
`generate-recovery-code`) runs the daemon-broker handoff transparently
|
|
409
|
-
when no token is in the keychain. So:
|
|
410
|
-
|
|
411
|
-
```bash
|
|
412
|
-
oversky login # authenticate the daemon, once
|
|
413
|
-
sky tasks list # silently auto-brokers, persists, runs
|
|
414
|
-
sky tasks list --json # uses the persisted token, no broker call
|
|
415
|
-
sky whoami # confirms identity from the persisted token
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
There is no opt-in flag. The mechanism is the long-term default.
|
|
419
|
-
|
|
420
|
-
**Skip rules** — auto-broker does NOT fire when any of these hold:
|
|
447
|
+
A human command with no stored session may adopt a durable CLI family through a signed-in daemon on the same deployment. It is stored and renews independently, so a daemon restart does not sign out the CLI. Revoking that daemon also revokes the families delegated through it. If durable adoption is unavailable, the command can borrow a short-lived token for that invocation.
|
|
421
448
|
|
|
422
|
-
|
|
423
|
-
- `OVERSKY_TOKEN` or `OVERSKY_REFRESH_TOKEN` env vars are set (operator
|
|
424
|
-
controls auth out-of-band — CI runners, ephemeral containers)
|
|
425
|
-
- `OVERSKY_SKIP_DAEMON_BROKER=1` (explicit escape hatch for debugging
|
|
426
|
-
or testing the PKCE flow itself)
|
|
427
|
-
- The command is one of `login`, `logout`,
|
|
428
|
-
`generate-recovery-code` — these manage their own auth lifecycle
|
|
449
|
+
`--bare`, injected `OVERSKY_TOKEN` / `SKRR_TOKEN` / `OVERSKY_REFRESH_TOKEN`, and `OVERSKY_SKIP_DAEMON_BROKER=1` disable automatic brokering. `SKRR_NO_CLI_SESSION_ADOPTION=1` disables durable adoption. Agent/tool children only borrow and never read or persist the person's session. Their login/logout commands are refused.
|
|
429
450
|
|
|
430
|
-
|
|
431
|
-
its bootstrap file, or the daemon isn't authenticated, the auto-broker
|
|
432
|
-
fails quietly and the command's normal `requireAuth()` produces the
|
|
433
|
-
familiar "Not signed in. Run `sky login` first." error. The one case
|
|
434
|
-
that gets a louder hint is baseURL mismatch, since the fix is precise:
|
|
435
|
-
|
|
436
|
-
```
|
|
437
|
-
[sky] Local oversky daemon is logged in to http://localhost:3080, but sky
|
|
438
|
-
is configured for https://oversky.ai. Run `sky login --base-url http://localhost:3080`
|
|
439
|
-
to use the daemon.
|
|
440
|
-
Not signed in. Run `sky login` first.
|
|
441
|
-
```
|
|
451
|
+
After `skrr logout`, durable adoption remains off until explicit login, although the daemon can still lend a short-lived token. On a Dedicated Runtime, the platform-managed hand-off can continue providing access after the person's own local credential is cleared.
|
|
442
452
|
|
|
443
|
-
###
|
|
444
|
-
|
|
445
|
-
Mechanism for "logged-in daemon implies logged-in sky":
|
|
446
|
-
|
|
447
|
-
1. `sky login` reads the daemon's bootstrap file:
|
|
448
|
-
- macOS: `~/Library/Application Support/OverSky/daemon-island.<profile>.json`
|
|
449
|
-
- Linux/Windows: `~/.oversky/profiles/<profile>/daemon-island.json`
|
|
450
|
-
(pre-Phase-K fallback: `~/.oversky/daemon-island.json`)
|
|
451
|
-
2. CLI POSTs to `http://127.0.0.1:<port>/v1/auth/cli-handoff` with the
|
|
452
|
-
bootstrap secret as `Authorization: Bearer ...` and the requested
|
|
453
|
-
cliId in the body.
|
|
454
|
-
3. Daemon's loopback handler (`daemon/src/auth/cliHandoff.ts`) forwards
|
|
455
|
-
to the server's `POST /api/daemons/cli-handoff` using the daemon's
|
|
456
|
-
own bearer as proof of "this user is already authenticated here".
|
|
457
|
-
4. Server mints a **fresh cli-scope refresh family** (independent
|
|
458
|
-
rotation, distinct revocation, blast-radius isolated from the
|
|
459
|
-
daemon) bound to the supplied cliId.
|
|
460
|
-
5. CLI persists via the canonical `writeToBackend()` — Keychain on
|
|
461
|
-
macOS, `cli-auth.json` elsewhere.
|
|
462
|
-
|
|
463
|
-
Trust model is the same same-UID loopback fence the Socket.IO server
|
|
464
|
-
uses: any attacker who can read the 0600 bootstrap file can already
|
|
465
|
-
read the daemon's keychain. CI tokens are refused at the server
|
|
466
|
-
(daemon bootstrapped from `osk_ci_*` cannot auto-elevate to CLI).
|
|
467
|
-
|
|
468
|
-
### `sky logout`
|
|
469
|
-
|
|
470
|
-
Sign out and clear the saved token. The `baseURL` is preserved so the next
|
|
471
|
-
`sky login` defaults to the same host.
|
|
453
|
+
### `skrr logout`
|
|
472
454
|
|
|
473
455
|
```bash
|
|
474
|
-
|
|
456
|
+
skrr logout
|
|
457
|
+
skrr logout --all-devices
|
|
475
458
|
```
|
|
476
459
|
|
|
477
|
-
The
|
|
478
|
-
|
|
460
|
+
The first command revokes this CLI refresh family best-effort and clears its local Keychain/file credential. It keeps the server, CLI identity and daemon's separate sign-in. The second also enumerates and revokes registered daemon resources, including their delegated CLI families. Independent CLI families created by browser/device code on other machines, and personal access tokens, require their own session/token revocation controls; this flag does not promise account-wide revocation of every credential type. If remote revocation fails, local cleanup still runs and the CLI reports the incomplete sweep.
|
|
461
|
+
|
|
462
|
+
For CI, use expiring `osk_pat_*` personal access tokens through `SKRR_TOKEN`. `osk_ci_*` tokens only bootstrap a daemon. Space-scoped `osk_live_*` / `osk_test_*` keys authenticate the public `/v1` API, a different API from the workspace CLI's `/api` routes. See [operations and recovery](docs/v1/operations.md).
|
|
479
463
|
|
|
480
|
-
### `
|
|
464
|
+
### `skrr whoami`
|
|
481
465
|
|
|
482
466
|
Show the currently signed-in user.
|
|
483
467
|
|
|
484
468
|
```bash
|
|
485
|
-
|
|
486
|
-
|
|
469
|
+
skrr whoami
|
|
470
|
+
skrr whoami --json
|
|
487
471
|
```
|
|
488
472
|
|
|
489
473
|
### `sky convos list`
|
|
@@ -892,6 +876,17 @@ sky spaces unarchive <space-id>
|
|
|
892
876
|
sky spaces archive <space-id> --json
|
|
893
877
|
```
|
|
894
878
|
|
|
879
|
+
### `sky spaces claim <id>`
|
|
880
|
+
|
|
881
|
+
An eligible editor can claim an ownerless Space. The longest-standing editor
|
|
882
|
+
can claim immediately; any editor can claim after seven days. The server
|
|
883
|
+
enforces eligibility at claim time.
|
|
884
|
+
|
|
885
|
+
```bash
|
|
886
|
+
sky spaces claim <space-id>
|
|
887
|
+
sky spaces claim OSK-S-12 --json
|
|
888
|
+
```
|
|
889
|
+
|
|
895
890
|
### `sky spaces` — subspaces (parent / child hierarchy)
|
|
896
891
|
|
|
897
892
|
Spaces form a tree. Each space tracks `parentSpaceId`, the materialized
|
|
@@ -1908,25 +1903,20 @@ delete commands refuse to prompt and exit with code 7 unless `--yes` is
|
|
|
1908
1903
|
passed. This prevents the CLI from hanging forever waiting on input that
|
|
1909
1904
|
will never arrive.
|
|
1910
1905
|
|
|
1911
|
-
##
|
|
1906
|
+
## Configuration and credentials
|
|
1912
1907
|
|
|
1913
|
-
|
|
1914
|
-
created with mode `0700` and the file with mode `0600`, so it's readable only
|
|
1915
|
-
by your user account.
|
|
1908
|
+
The active config root is `~/.skrr`, with `cli-config.json` for the default profile and `profiles/<name>/cli-config.json` for a named profile. `SKRR_CONFIG_DIR` (preferred) / `OVERSKY_CONFIG_DIR` can override it. The legacy `~/.sky/config.json` is read only as a migration input.
|
|
1916
1909
|
|
|
1917
|
-
| Field
|
|
1918
|
-
|
|
|
1919
|
-
| `baseURL`
|
|
1920
|
-
| `
|
|
1921
|
-
| `
|
|
1922
|
-
| `
|
|
1923
|
-
| `email` | Signed-in user email, cached for display |
|
|
1910
|
+
| Field | Description |
|
|
1911
|
+
| --- | --- |
|
|
1912
|
+
| `baseURL` | Issuing deployment, e.g. `https://skrr.ai` |
|
|
1913
|
+
| `cliId` / `profileCliId` | Machine/profile identity used to bind refresh sessions |
|
|
1914
|
+
| `credentials.store` | Credential backend posture, such as automatic Keychain/file or env-only |
|
|
1915
|
+
| `adoptDaemonSession` | Whether human commands may durably adopt a session through the daemon |
|
|
1924
1916
|
|
|
1925
|
-
|
|
1917
|
+
Session secrets live in the macOS Keychain or profile-local `cli-auth.json` (0600), not normal config fields. Environment/flag/helper credentials outrank stored sessions and do not refresh. Agent children never read the person's stored session. Use `skrr whoami` to inspect the actual source.
|
|
1926
1918
|
|
|
1927
|
-
|
|
1928
|
-
rm ~/.sky/config.json
|
|
1929
|
-
```
|
|
1919
|
+
Use `skrr logout` to revoke and clear the local CLI session, and explicit session/token management for broader revocation. Deleting a legacy config file does not clear Keychain credentials, revoke a remote family, or stop daemon-provided access. See [authentication and revocation](docs/v1/operations.md#authentication-and-revocation).
|
|
1930
1920
|
|
|
1931
1921
|
## Architecture notes
|
|
1932
1922
|
|
|
@@ -1935,11 +1925,9 @@ code is a Node-native HttpAdapter that satisfies the `HttpAdapter` interface
|
|
|
1935
1925
|
the data-provider exposes for non-browser consumers.
|
|
1936
1926
|
|
|
1937
1927
|
- **`src/base-command.ts`** — every command extends `BaseCommand`, which in
|
|
1938
|
-
`init()` loads
|
|
1939
|
-
`setHttpAdapter()` on the data-provider, and exposes `requireAuth()` and
|
|
1940
|
-
`handleApiError()` for subclasses.
|
|
1928
|
+
`init()` loads profile configuration, resolves the effective credential, calls `setBaseURL()` and `setHttpAdapter()` on the data-provider, and exposes `requireAuth()` and `handleApiError()` for subclasses.
|
|
1941
1929
|
- **`src/lib/node-adapter.ts`** — implements `HttpAdapter` using Node 20's
|
|
1942
|
-
global `fetch`. Injects the
|
|
1930
|
+
global `fetch`. Injects the resolved credential on every request,
|
|
1943
1931
|
transparently handles 401 → refresh → retry (mirroring the browser
|
|
1944
1932
|
interceptor minus the `window.location` redirect), and surfaces server
|
|
1945
1933
|
errors as `Error` instances with `status` and `body` properties.
|
package/bin/run.js
CHANGED
|
@@ -13,6 +13,38 @@ try {
|
|
|
13
13
|
|
|
14
14
|
const path = require('node:path');
|
|
15
15
|
const { spawnSync } = require('node:child_process');
|
|
16
|
+
|
|
17
|
+
// Enter the installation's session gate before loading any package modules.
|
|
18
|
+
// The copy outside node_modules remains available while npm replaces files.
|
|
19
|
+
// npm still owns the executable itself; its one-time initial migration and
|
|
20
|
+
// clients from older releases cannot participate in this cooperative gate.
|
|
21
|
+
try {
|
|
22
|
+
const fs = require('node:fs');
|
|
23
|
+
const os = require('node:os');
|
|
24
|
+
const crypto = require('node:crypto');
|
|
25
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
26
|
+
const key = crypto.createHash('sha256').update(packageRoot).digest('hex').slice(0, 24);
|
|
27
|
+
const runtimeDirectory = path.join(os.homedir(), '.skrr', 'cli-update-runtime', key);
|
|
28
|
+
const bootstrap = path.join(runtimeDirectory, 'bootstrap-v1.cjs');
|
|
29
|
+
if (!fs.existsSync(bootstrap)) {
|
|
30
|
+
fs.mkdirSync(runtimeDirectory, { recursive: true, mode: 0o700 });
|
|
31
|
+
const temporary = `${bootstrap}.${process.pid}.tmp`;
|
|
32
|
+
fs.copyFileSync(path.join(__dirname, 'update-session.cjs'), temporary);
|
|
33
|
+
fs.chmodSync(temporary, 0o600);
|
|
34
|
+
fs.renameSync(temporary, bootstrap);
|
|
35
|
+
}
|
|
36
|
+
require(bootstrap).registerSession(packageRoot);
|
|
37
|
+
process.env.SKRR_CLI_UPDATE_SESSION_REGISTERED = String(process.pid);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (error && error.code === 'CLI_UPDATE_BUSY') {
|
|
40
|
+
console.error(`[skrr] ${error.message}`);
|
|
41
|
+
process.exit(75);
|
|
42
|
+
}
|
|
43
|
+
// Failure to record a session disables the automatic updater in this
|
|
44
|
+
// invocation. A read-only home must not break ordinary CLI commands.
|
|
45
|
+
process.env.SKRR_CLI_UPDATE_SESSION_UNAVAILABLE = '1';
|
|
46
|
+
}
|
|
47
|
+
|
|
16
48
|
const { findAlternateCli, missingLocalCommandBuild } = require('./dev-fallback');
|
|
17
49
|
|
|
18
50
|
/**
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Park before npm executes. The parent publishes this process group's durable
|
|
4
|
+
// mutation ownership before authorizing execution, closing its crash window.
|
|
5
|
+
const fs = require('node:fs');
|
|
6
|
+
const { spawn } = require('node:child_process');
|
|
7
|
+
const requestFile = process.argv[2];
|
|
8
|
+
const request = JSON.parse(fs.readFileSync(requestFile, 'utf8'));
|
|
9
|
+
const deadline = Date.now() + 30000;
|
|
10
|
+
const timer = setInterval(() => {
|
|
11
|
+
let authorization;
|
|
12
|
+
try {
|
|
13
|
+
authorization = JSON.parse(fs.readFileSync(`${requestFile}.go`, 'utf8'));
|
|
14
|
+
} catch {
|
|
15
|
+
/* still parked */
|
|
16
|
+
}
|
|
17
|
+
if (authorization?.pid === process.pid && authorization?.token === request.token) {
|
|
18
|
+
clearInterval(timer);
|
|
19
|
+
const child = spawn(request.npmPath, ['install', '-g', `@skrr-ai/cli@${request.version}`], {
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
shell: process.platform === 'win32',
|
|
22
|
+
});
|
|
23
|
+
child.once('error', () => {
|
|
24
|
+
process.exitCode = 1;
|
|
25
|
+
});
|
|
26
|
+
child.once('exit', (code) => {
|
|
27
|
+
process.exitCode = code ?? 1;
|
|
28
|
+
});
|
|
29
|
+
} else if (Date.now() >= deadline) {
|
|
30
|
+
clearInterval(timer);
|
|
31
|
+
process.exitCode = 1;
|
|
32
|
+
}
|
|
33
|
+
}, 20);
|