@skein-code/cli 0.3.28 → 0.3.30
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 +79 -27
- package/dist/cli.js +1062 -268
- package/dist/cli.js.map +1 -1
- package/docs/MULTI_MODEL_TEAMS.md +93 -19
- package/docs/NEXT_STEPS.md +53 -26
- package/package.json +14 -1
|
@@ -152,16 +152,17 @@ The shortest setup path is the interactive user-level wizard:
|
|
|
152
152
|
skein agents setup
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
It asks for a connection name,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
useful for provisioning:
|
|
155
|
+
It asks for a connection name, explicit relay transport, inference endpoint,
|
|
156
|
+
optional model-catalog endpoint, `env` or `none` authentication, and default
|
|
157
|
+
model. The wizard writes only the environment-variable name and saves shared
|
|
158
|
+
settings under the user Skein namespace, so the same connection is available
|
|
159
|
+
in every workspace. The non-interactive equivalent is useful for provisioning:
|
|
160
160
|
|
|
161
161
|
```bash
|
|
162
162
|
skein agents setup --yes \
|
|
163
163
|
--name team-relay \
|
|
164
164
|
--provider compatible \
|
|
165
|
+
--protocol openai-responses \
|
|
165
166
|
--base-url https://relay.example/v1 \
|
|
166
167
|
--api-key-env TEAM_RELAY_API_KEY \
|
|
167
168
|
--model openai/coding-model
|
|
@@ -172,25 +173,86 @@ the same next action without placing a secret in the session transcript.
|
|
|
172
173
|
|
|
173
174
|
### Authentication paths
|
|
174
175
|
|
|
175
|
-
Skein keeps
|
|
176
|
-
different ownership and billing semantics:
|
|
176
|
+
Skein keeps primary relay routing and delegated CLI login separate because they
|
|
177
|
+
have different ownership and billing semantics:
|
|
177
178
|
|
|
178
179
|
- Subscription users authenticate once in each installed official CLI. Codex
|
|
179
180
|
supports ChatGPT subscription login, Claude Code supports Claude.ai/Teams
|
|
180
181
|
login, and Gemini CLI supports Google account login. A Skein route with
|
|
181
182
|
`runtime: "codex"`, `"claude"`, or `"grok"` reuses that CLI's local login;
|
|
182
183
|
Skein does not read, copy, or persist its tokens.
|
|
183
|
-
-
|
|
184
|
-
|
|
184
|
+
- Existing direct API routes remain readable for backward compatibility; they
|
|
185
|
+
are not the evolution path for new primary connections.
|
|
185
186
|
- Relay/gateway users define one named `connection` and reuse it across model
|
|
186
|
-
routes. This matches gateways such as OpenRouter
|
|
187
|
-
|
|
187
|
+
routes. This matches gateways such as OpenRouter, LiteLLM, and Vercel AI
|
|
188
|
+
Gateway that expose Responses, Chat Completions, and/or Anthropic Messages
|
|
189
|
+
behind one relay credential.
|
|
190
|
+
|
|
191
|
+
### Primary model connection selection
|
|
192
|
+
|
|
193
|
+
The primary agent and team routes share the same connection catalog. User
|
|
194
|
+
configuration under `agents.connections` is merged with strict named
|
|
195
|
+
environment profiles:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
export SKEIN_CONNECTIONS=work,local
|
|
199
|
+
export SKEIN_CONNECTION_WORK_PROVIDER=compatible
|
|
200
|
+
export SKEIN_CONNECTION_WORK_PROTOCOL=openai-responses
|
|
201
|
+
export SKEIN_CONNECTION_WORK_BASE_URL=https://relay.example/v1
|
|
202
|
+
export SKEIN_CONNECTION_WORK_API_KEY_ENV=WORK_RELAY_KEY
|
|
203
|
+
export SKEIN_CONNECTION_WORK_MODEL=coder
|
|
204
|
+
export SKEIN_CONNECTION_LOCAL_PROVIDER=compatible
|
|
205
|
+
export SKEIN_CONNECTION_LOCAL_PROTOCOL=openai-chat
|
|
206
|
+
export SKEIN_CONNECTION_LOCAL_BASE_URL=http://127.0.0.1:11434/v1
|
|
207
|
+
export SKEIN_CONNECTION_LOCAL_AUTH=none
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
IDs are lowercase shell-safe names. IDs that collide after environment
|
|
211
|
+
normalization (for example `team-a` and `team_a`) are rejected. Endpoint and
|
|
212
|
+
credential fields never cross profile boundaries. Selection precedence is an
|
|
213
|
+
explicit `--connection`, the configured default, then automatic selection only
|
|
214
|
+
when exactly one complete profile exists. Multiple complete profiles open a
|
|
215
|
+
TTY selector; headless runs fail with `Pass --connection <name>`.
|
|
216
|
+
|
|
217
|
+
New named connections are relay-only: `provider` is `compatible`, authentication
|
|
218
|
+
is exactly `env` or `none`, and the transport is `openai-responses`,
|
|
219
|
+
`openai-chat`, or `anthropic-messages`. OAuth, keychain, command helpers, and
|
|
220
|
+
official account login are not connection schema variants. Custom legacy native
|
|
221
|
+
provider endpoints do not inherit the provider's official API key.
|
|
222
|
+
|
|
223
|
+
Responses is the default because OpenAI recommends it for new projects. Skein
|
|
224
|
+
sets `store: false` and replays the complete returned output items plus tool
|
|
225
|
+
outputs on the next request, which also works with stateless relay
|
|
226
|
+
implementations. Protocol failures never trigger an automatic request through a
|
|
227
|
+
different transport, avoiding duplicate inference and billing.
|
|
228
|
+
|
|
229
|
+
Some relays publish two SDK base URLs for the same account. The OpenAI base
|
|
230
|
+
usually includes `/v1`; the Anthropic base may be a root or provider prefix and
|
|
231
|
+
expects the client to append `/v1/messages`. This is why inference `baseUrl` and
|
|
232
|
+
OpenAI-style `modelsBaseUrl` are distinct. An Anthropic transport must configure
|
|
233
|
+
`modelsBaseUrl` explicitly:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"provider": "compatible",
|
|
238
|
+
"protocol": "anthropic-messages",
|
|
239
|
+
"baseUrl": "https://relay.example/anthropic",
|
|
240
|
+
"modelsBaseUrl": "https://relay.example/v1",
|
|
241
|
+
"defaultModel": "anthropic/coding-model",
|
|
242
|
+
"auth": {"type": "env", "name": "TEAM_RELAY_API_KEY"}
|
|
243
|
+
}
|
|
244
|
+
```
|
|
188
245
|
|
|
189
246
|
Official authentication references: [Codex](https://developers.openai.com/codex/auth),
|
|
190
247
|
[Claude Code](https://code.claude.com/docs/en/authentication), and
|
|
191
248
|
[Gemini CLI](https://geminicli.com/docs/get-started/authentication/). Unified
|
|
192
249
|
gateway examples: [OpenRouter](https://openrouter.ai/docs/quickstart) and
|
|
193
250
|
[LiteLLM](https://docs.litellm.ai/docs/learn/gateway_quickstart).
|
|
251
|
+
Transport references: [OpenAI Responses migration](https://developers.openai.com/api/docs/guides/migrate-to-responses),
|
|
252
|
+
[OpenRouter Responses](https://openrouter.ai/docs/api/reference/responses/overview),
|
|
253
|
+
[OpenRouter Anthropic Messages](https://openrouter.ai/docs/api/api-reference/anthropic-messages/create-a-message),
|
|
254
|
+
[LiteLLM supported endpoints](https://docs.litellm.ai/docs/supported_endpoints),
|
|
255
|
+
and [Vercel AI Gateway APIs](https://vercel.com/docs/ai-gateway/sdks-and-apis).
|
|
194
256
|
|
|
195
257
|
```json
|
|
196
258
|
{
|
|
@@ -247,8 +309,10 @@ role. Add a profile entry only when that role needs a different model:
|
|
|
247
309
|
"connections": {
|
|
248
310
|
"team-relay": {
|
|
249
311
|
"provider": "compatible",
|
|
312
|
+
"protocol": "openai-responses",
|
|
250
313
|
"baseUrl": "https://relay.example/v1",
|
|
251
|
-
"
|
|
314
|
+
"defaultModel": "openai/coding-model",
|
|
315
|
+
"auth": {"type": "env", "name": "TEAM_RELAY_API_KEY"}
|
|
252
316
|
}
|
|
253
317
|
},
|
|
254
318
|
"routes": {
|
|
@@ -268,8 +332,9 @@ need different connections:
|
|
|
268
332
|
"connections": {
|
|
269
333
|
"team-relay": {
|
|
270
334
|
"provider": "compatible",
|
|
335
|
+
"protocol": "openai-responses",
|
|
271
336
|
"baseUrl": "https://relay.example/v1",
|
|
272
|
-
"
|
|
337
|
+
"auth": {"type": "env", "name": "TEAM_RELAY_API_KEY"}
|
|
273
338
|
}
|
|
274
339
|
},
|
|
275
340
|
"routes": {
|
|
@@ -295,16 +360,25 @@ need different connections:
|
|
|
295
360
|
```
|
|
296
361
|
|
|
297
362
|
Run `skein agents connections` or `/connections` to inspect the resolved
|
|
298
|
-
endpoint, environment-variable reference,
|
|
299
|
-
the key.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
363
|
+
inference endpoint, model-catalog endpoint, environment-variable reference,
|
|
364
|
+
and route count without revealing the key. Run `skein agents models
|
|
365
|
+
team-relay` to inspect the relay's OpenAI-style `/models` catalog before
|
|
366
|
+
choosing route IDs. Discovery is read-only and does not rewrite config. Its
|
|
367
|
+
process-local cache is bounded to 32 endpoint/auth fingerprints with a 15-minute
|
|
368
|
+
TTL and ETag revalidation; secret values are hashed into the in-memory
|
|
369
|
+
fingerprint and never cached. `401`/`403` invalidates the entry and never returns
|
|
370
|
+
stale models as an authentication success. Named connections are best kept in
|
|
371
|
+
user-level configuration. A
|
|
304
372
|
repository-owned connection or route remains disabled until the project config
|
|
305
373
|
is explicitly trusted, preventing a cloned repository from redirecting a
|
|
306
374
|
developer's key and source context to an attacker-controlled endpoint.
|
|
307
375
|
|
|
376
|
+
External CLI runtimes remain separate from native connections. Skein launches
|
|
377
|
+
them with a minimal environment containing only the safe executable path,
|
|
378
|
+
home/temporary/locale facts, and that runtime's own config directory. Provider
|
|
379
|
+
keys, `SKEIN_*` credentials, unrelated connection keys, and `NODE_OPTIONS` are
|
|
380
|
+
not inherited by the child process.
|
|
381
|
+
|
|
308
382
|
Routing precedence is explicit and predictable: a profile route overrides team
|
|
309
383
|
defaults; a route that specifies `provider` without `connection` bypasses the
|
|
310
384
|
default connection; otherwise the current parent model is used when no team
|
package/docs/NEXT_STEPS.md
CHANGED
|
@@ -9,7 +9,7 @@ one of the milestones below.
|
|
|
9
9
|
|
|
10
10
|
- Product name: `Skein`; primary executable: `skein`.
|
|
11
11
|
- Compatibility executables: `mosaic` and `mosaic-code`.
|
|
12
|
-
- Current repository version: `0.3.
|
|
12
|
+
- Current repository version: `0.3.30`.
|
|
13
13
|
- Runtime requirement: Node.js `>=22.16.0` (the runtime uses unflagged
|
|
14
14
|
`node:sqlite` with FTS5, and current CLI/build dependencies require this
|
|
15
15
|
Node 22 baseline).
|
|
@@ -24,7 +24,8 @@ one of the milestones below.
|
|
|
24
24
|
all sizes support prompt
|
|
25
25
|
history, `@file` completion, command completion, multiline editing, queued
|
|
26
26
|
follow-ups, live context inspection, permission approval, themes, ASCII mode,
|
|
27
|
-
`NO_COLOR`,
|
|
27
|
+
`NO_COLOR`, `TERM=dumb`, screen-reader output, reduced motion, and
|
|
28
|
+
narrow-height degradation.
|
|
28
29
|
- Storage: sessions, checkpoints, local index, and project configuration still
|
|
29
30
|
use `.mosaic/` paths for compatibility. `SKEIN_*` environment variables are
|
|
30
31
|
preferred, while `MOSAIC_*` aliases remain supported.
|
|
@@ -41,16 +42,19 @@ npm audit --omit=dev
|
|
|
41
42
|
npm run release:verify -- --output-dir artifacts/package
|
|
42
43
|
```
|
|
43
44
|
|
|
44
|
-
The latest verified package is `skein-code-cli-0.3.
|
|
45
|
-
its SHA-256 to `artifacts/package/skein-code-cli-0.3.
|
|
45
|
+
The latest verified package is `skein-code-cli-0.3.30.tgz`. The verifier writes
|
|
46
|
+
its SHA-256 to `artifacts/package/skein-code-cli-0.3.30.tgz.sha256`, and CI
|
|
46
47
|
retains the checksum beside the package metadata. The checksum is deliberately
|
|
47
48
|
not copied into this packaged document because doing so would change the
|
|
48
49
|
archive it describes.
|
|
49
50
|
|
|
50
|
-
The final verification
|
|
51
|
-
aliases. PTY coverage
|
|
52
|
-
short-height case
|
|
53
|
-
|
|
51
|
+
The final verification includes a fresh install for all three executable
|
|
52
|
+
aliases. PTY coverage includes 20, 24 ASCII/`NO_COLOR`, 40, 80, and 120 columns;
|
|
53
|
+
a 40x10 short-height case; 40-column `TERM=dumb`; and 80-column screen-reader
|
|
54
|
+
interaction. Raw output is replayed through a headless terminal so the gate
|
|
55
|
+
checks the final visible screen rather than only accumulated logs. The current
|
|
56
|
+
full-suite count is recorded from the latest `npm run check` in the release
|
|
57
|
+
evidence.
|
|
54
58
|
|
|
55
59
|
## Recommended Order
|
|
56
60
|
|
|
@@ -366,25 +370,43 @@ Implementation progress:
|
|
|
366
370
|
stopped attempt in telemetry, and feeds only the fresh result into the
|
|
367
371
|
caller's aggregation. Completed attempts remain immutable until the next
|
|
368
372
|
report-inspection increment.
|
|
369
|
-
- Named `agents.connections`
|
|
370
|
-
and
|
|
371
|
-
|
|
372
|
-
|
|
373
|
+
- Named `agents.connections` and `SKEIN_CONNECTION_*` profiles now let the
|
|
374
|
+
primary agent and API routes share one provider, protocol, base URL, default
|
|
375
|
+
model, and typed authentication reference. One complete connection is
|
|
376
|
+
selected automatically; multiple candidates require a TTY choice or
|
|
377
|
+
`--connection` in headless mode. New connections are relay-only and accept
|
|
378
|
+
only `env` or `none`; subscription-backed official CLIs remain isolated
|
|
379
|
+
delegated runtimes rather than primary connections.
|
|
373
380
|
- `skein agents connections` and `/connections` expose redacted connection
|
|
374
381
|
status and route counts. Repository-owned connections are stripped until
|
|
375
382
|
project config is trusted, just like direct model routes.
|
|
376
|
-
- `skein agents models <connection>`
|
|
377
|
-
|
|
378
|
-
|
|
383
|
+
- `skein agents models <connection>` queries the relay's independent
|
|
384
|
+
OpenAI-style `/models` endpoint. A 32-entry process-local cache uses a
|
|
385
|
+
15-minute TTL, ETag revalidation, endpoint/credential fingerprint isolation,
|
|
386
|
+
and hard invalidation on `401`/`403`; it never stores credential values or
|
|
387
|
+
treats stale data as an authentication success.
|
|
379
388
|
- Team routing now supports `agents.defaultConnection` and optional
|
|
380
389
|
`agents.defaultModel`. Most users configure one shared gateway once; profile
|
|
381
390
|
routes only contain model or provider overrides when needed. CLI and TUI
|
|
382
391
|
surfaces label inherited versus overridden routes, and unknown defaults fail
|
|
383
392
|
validation before any agent starts.
|
|
384
393
|
- `skein agents setup` now provides a guided user-level setup for a shared
|
|
385
|
-
connection and default model, with
|
|
386
|
-
|
|
387
|
-
|
|
394
|
+
connection and default model, with explicit Responses, Chat Completions, and
|
|
395
|
+
Anthropic Messages transports plus separate inference/model-catalog bases.
|
|
396
|
+
The first-run TUI uses the same relay-only model and stores only credential
|
|
397
|
+
environment-variable names while preserving other user configuration.
|
|
398
|
+
- The Responses transport uses `POST /responses`, `store: false`, typed SSE,
|
|
399
|
+
normalized text/function/usage events, and exact output-item replay for
|
|
400
|
+
stateless tool and reasoning continuation. It never retries a failed request
|
|
401
|
+
through a different protocol. Anthropic relay transport accepts SDK-style
|
|
402
|
+
root bases, appends `/v1/messages` when needed, and uses relay bearer auth.
|
|
403
|
+
- `skein doctor` reports unsupported `SEKIN_API`/`SKEIN_BASEURL` spellings and
|
|
404
|
+
connection readiness without reading or printing their values. Custom native
|
|
405
|
+
endpoints cannot inherit official provider keys, and external CLI runtimes
|
|
406
|
+
receive a minimal environment allowlist instead of the parent secret set.
|
|
407
|
+
- This relay-only connection catalog, Responses transport, independent model
|
|
408
|
+
directory, redacted status, and delegated-runtime isolation slice is complete
|
|
409
|
+
and release-verified in `0.3.30`.
|
|
388
410
|
- Team budgets default to `observe`: telemetry is retained, but configured
|
|
389
411
|
thresholds do not warn or terminate work. `guard` adds non-blocking threshold
|
|
390
412
|
warnings, while `strict` is an explicit hard-stop policy for controlled jobs.
|
|
@@ -462,14 +484,19 @@ already separated short-term working memory and durable records:
|
|
|
462
484
|
Never promote model-inferred facts directly into durable memory without the
|
|
463
485
|
existing candidate/approval path.
|
|
464
486
|
|
|
465
|
-
### P2: Terminal Accessibility And Visual Regression
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
487
|
+
### P2: Terminal Accessibility And Visual Regression (complete in 0.3.29)
|
|
488
|
+
|
|
489
|
+
Version `0.3.29` adds an explicit screen-reader profile, automatic `TERM=dumb`
|
|
490
|
+
fallback, semantic Ink roles, reduced motion, and non-incremental low-capability
|
|
491
|
+
rendering. The PTY release gate now covers the contracted 20/24/40/80/120-column
|
|
492
|
+
matrix, 40x10 height constraint, CJK/emoji component fixtures, ASCII,
|
|
493
|
+
`NO_COLOR`, permission/error/ready states, history search, and file completion.
|
|
494
|
+
It replays logs through `@xterm/headless` and rejects final-frame wraps, stale
|
|
495
|
+
panels, control-probe leaks, joined announcements, or missing status. The
|
|
496
|
+
single-process benchmark enforces 25 ms input and 150 ms streaming-render p95
|
|
497
|
+
budgets while requiring the last chunk in the final frame. Future expansion may
|
|
498
|
+
sample additional widths through 160 and heights through 60 without changing
|
|
499
|
+
the shipped gate's factual scope.
|
|
473
500
|
|
|
474
501
|
### P3: Distribution
|
|
475
502
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skein-code/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.30",
|
|
4
4
|
"description": "A context-first, model-agnostic coding agent with an auditable terminal workspace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -16,6 +16,17 @@
|
|
|
16
16
|
},
|
|
17
17
|
"skein": {
|
|
18
18
|
"releaseNotes": [
|
|
19
|
+
"Named primary connections now target third-party compatible relays only, use explicit env or none authentication, and resolve one complete profile automatically while requiring an explicit choice for ambiguity",
|
|
20
|
+
"OpenAI Responses is the recommended new transport with POST /responses, store false, typed SSE, normalized tools and usage, and bounded exact output-item replay for stateless reasoning continuation",
|
|
21
|
+
"OpenAI Chat Completions and Anthropic Messages remain explicit relay transports without cross-protocol retries; inference and OpenAI-style model catalog base URLs are configured independently",
|
|
22
|
+
"Relay model discovery now uses a bounded 15-minute ETag cache isolated by endpoint and credential fingerprints, invalidates authentication failures, and never stores or echoes credential values",
|
|
23
|
+
"First-run and agents setup flows are relay-only, save only credential environment-variable names, and expose redacted connection state consistently across TUI, text, JSON, JSONL, doctor, and config output",
|
|
24
|
+
"Provider diagnostics redact secrets, authorization headers, URL credentials, and query strings while Responses replay state is capped at 128 items and 4 MiB in memory and persisted sessions",
|
|
25
|
+
"External delegated CLIs now receive a minimal runtime-owned environment instead of inheriting provider, Skein, relay, or NODE_OPTIONS secrets",
|
|
26
|
+
"TERM=dumb and screen-reader sessions now use deterministic ASCII, monochrome, reduced-motion, non-incremental rendering without losing keyboard input",
|
|
27
|
+
"SKEIN_SCREEN_READER=1 enables Ink accessibility output with semantic timeline, permission, and composer roles plus clean phase boundaries",
|
|
28
|
+
"PTY release gates now replay eight terminal scenarios through a headless emulator and reject final-frame overflow, stale panels, announcement joins, and missing status",
|
|
29
|
+
"A local terminal UI benchmark enforces 25 ms input and 150 ms streaming-render p95 budgets while retaining the final streamed chunk",
|
|
19
30
|
"MCP trust and revoke confirmation rendering now has a deterministic cross-platform release regression gate",
|
|
20
31
|
"MCP now follows a no-network search and inspect review before explicit workspace-bound manifest trust and lazy activation",
|
|
21
32
|
"Declarative capability manifests expose redacted source, version, tools, permissions, network, command, path, sensitive-field, process, and completion-evidence effects",
|
|
@@ -99,6 +110,7 @@
|
|
|
99
110
|
"benchmark:context": "tsx scripts/benchmark-local-index.ts",
|
|
100
111
|
"benchmark:duplication": "tsx scripts/benchmark-duplication.ts",
|
|
101
112
|
"benchmark:token-economy": "tsx scripts/benchmark-token-economy.ts",
|
|
113
|
+
"benchmark:terminal-ui": "tsx scripts/benchmark-terminal-ui.ts",
|
|
102
114
|
"verify:package": "node scripts/verify-package.mjs",
|
|
103
115
|
"release:verify": "npm run check && npm run verify:package --",
|
|
104
116
|
"typecheck": "tsc --noEmit",
|
|
@@ -126,6 +138,7 @@
|
|
|
126
138
|
"@types/diff": "^8.0.0",
|
|
127
139
|
"@types/node": "^22.19.7",
|
|
128
140
|
"@types/react": "^19.2.7",
|
|
141
|
+
"@xterm/headless": "^6.0.0",
|
|
129
142
|
"tsup": "^8.5.1",
|
|
130
143
|
"tsx": "^4.21.0",
|
|
131
144
|
"vitest": "^4.0.18"
|