@linzumi/cli 0.0.5-beta → 0.0.7-beta

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 CHANGED
@@ -1,152 +1,264 @@
1
- # @linzumi/cli
1
+ # Linzumi CLI
2
2
 
3
- ```text
4
- ___ ___
5
- .-' '-. .-' '-.
6
- .' ' '.
7
- / _ _ \
8
- | .' '. .' '. |
9
- | / \ .-. / \ |
10
- \ \ (o o) / /
11
- '._'._ \_/ _.'_.'
12
- | | |
13
- | /|\ |
14
- |___/ | \___|
15
- \_|_/
16
- / \
17
- ```
3
+ Connect your computer to Kandan so you can run Codex locally from the browser.
4
+
5
+ Linzumi gives Kandan a secure, authenticated bridge to your own machine. You
6
+ keep the code, shells, editors, and preview servers local. Kandan gives you the
7
+ web UI, sharing controls, HTTPS editor access, forwarded previews, and Codex
8
+ session orchestration.
18
9
 
19
- Linzumi's CLI package. It installs the `linzumi` executable.
10
+ ## Copy And Paste
20
11
 
21
- The initial CLI command connects this computer to Kandan as a local Codex
22
- runner. It wraps the same local runner that was previously started with
23
- `bun run start -- ...`.
12
+ Use a Chromium-based browser such as Chrome, Edge, Arc, or Brave.
24
13
 
25
- ## Install
14
+ ```bash
15
+ npm install -g @linzumi/cli@beta && linzumi start ~/code
16
+ ```
26
17
 
27
- Install the exact beta version:
18
+ To pin this exact beta:
28
19
 
29
20
  ```bash
30
- npm install -g @linzumi/cli@0.0.5-beta
21
+ npm install -g @linzumi/cli@0.0.7-beta && linzumi start ~/code
31
22
  ```
32
23
 
33
- Or install the current beta tag:
24
+ Use a different folder if your projects live somewhere else:
34
25
 
35
26
  ```bash
36
- npm install -g @linzumi/cli@beta
27
+ npm install -g @linzumi/cli@beta && linzumi start ~/work/my-app
37
28
  ```
38
29
 
39
- This beta expects Bun and Codex to be available locally:
30
+ That command opens Kandan, walks you through signup or sign-in, connects this
31
+ computer, and lets Kandan start Codex against the folder you chose.
32
+
33
+ ## What You Can Do
34
+
35
+ After `linzumi start` is connected, try this from Kandan:
36
+
37
+ 1. Start a Codex session.
38
+ 2. Ask Codex to inspect or edit a file in the folder you allowed.
39
+ 3. Open the local editor from Kandan.
40
+ 4. Start a dev server locally, then open its forwarded preview from Kandan.
41
+ 5. Share editor or preview access with another user.
42
+
43
+ The editor and previews open on Kandan HTTPS URLs. They should not expose
44
+ `localhost` URLs to the browser.
45
+
46
+ ## What Linzumi Runs Locally
47
+
48
+ The CLI starts a local runner process on your computer. That runner:
49
+
50
+ - launches or connects to Codex locally
51
+ - downloads the Kandan-approved editor runtime when needed
52
+ - starts code-server for the allowed folder
53
+ - exposes only explicitly approved local ports through Kandan
54
+ - keeps Kandan auth cookies and bearer tokens away from local services
55
+
56
+ Kandan remains the control plane. Browser traffic terminates at Kandan first,
57
+ where auth, grants, and allowed-port policy are enforced before traffic is sent
58
+ through the runner tunnel.
59
+
60
+ In the local-service hop, `127.0.0.1` means your computer, not the Kandan
61
+ server.
62
+
63
+ ## Requirements
64
+
65
+ Install these before running the beta:
40
66
 
41
67
  ```bash
68
+ node --version
69
+ npm --version
42
70
  bun --version
43
71
  codex --version
44
- linzumi --version
45
72
  ```
46
73
 
47
- Expected CLI output:
74
+ Expected:
75
+
76
+ - Node.js 20 or newer
77
+ - npm
78
+ - Bun 1.2 or newer
79
+ - Codex CLI
80
+ - Chrome, Edge, Arc, Brave, or another Chromium-based browser
81
+
82
+ Safari is semi-supported for now. Use Chromium for the best editor and
83
+ collaboration behavior.
84
+
85
+ ## First Run
48
86
 
49
87
  ```bash
50
- linzumi 0.0.5-beta
88
+ linzumi start ~/code
89
+ ```
90
+
91
+ What happens:
92
+
93
+ 1. The CLI opens Kandan.
94
+ 2. You sign up or sign in.
95
+ 3. Kandan asks permission to connect this computer.
96
+ 4. The CLI stores a scoped local-runner token.
97
+ 5. The CLI checks Bun, Codex, and the Kandan editor runtime.
98
+ 6. Kandan shows the computer as connected.
99
+
100
+ The first editor launch can download a Kandan-approved runtime archive. Later
101
+ runs reuse the verified runtime from:
102
+
103
+ ```text
104
+ ~/.linzumi/editor-runtimes
51
105
  ```
52
106
 
53
- ## Prod Quick Start
107
+ The production path does not use a random local `code-server` install. Kandan
108
+ publishes a checksummed runtime manifest, and the CLI only advertises editor
109
+ readiness after that runtime is verified locally.
110
+
111
+ ## Good Things To Try
54
112
 
55
- For the Linzumi workspace in prod, this is the first command to try:
113
+ Start from a real project:
56
114
 
57
115
  ```bash
58
- npm install -g @linzumi/cli@0.0.5-beta
116
+ linzumi start ~/code/my-app
117
+ ```
59
118
 
60
- linzumi connect \
61
- --kandan-url wss://serve.kandanai.com \
62
- --workspace linzumi \
63
- --channel seans-playground \
64
- --codex-bin codex \
65
- --launch-tui
119
+ Then in Kandan:
120
+
121
+ ```text
122
+ Summarize this repository and tell me how to run it locally.
66
123
  ```
67
124
 
68
- The runner handles OAuth itself. If the cached Kandan token is missing or
69
- rejected, it opens the OAuth flow and saves the refreshed auth cache.
70
- By default it listens for replies from the authenticated Kandan user.
125
+ If your app starts a dev server:
71
126
 
72
- For a more explicit launch that pins the Codex model, reasoning effort, and
73
- fast service tier:
127
+ ```bash
128
+ npm run dev
129
+ ```
130
+
131
+ Open the detected forwarded port from Kandan. If a port is not auto-detected,
132
+ restart with an explicit approved port:
74
133
 
75
134
  ```bash
76
- linzumi connect \
77
- --kandan-url wss://serve.kandanai.com \
78
- --workspace linzumi \
79
- --channel seans-playground \
80
- --codex-bin codex \
81
- --model gpt-5.5 \
82
- --reasoning-effort low \
83
- --fast \
84
- --launch-tui
135
+ linzumi start ~/code/my-app --forward-port 3000
136
+ ```
137
+
138
+ For a shared editor test, invite another user, open the local editor, and edit
139
+ the same file. Chromium should show remote cursor labels and selections.
140
+
141
+ ## Hosted Kandan
142
+
143
+ For a hosted Kandan deployment, point the CLI at the hosted websocket URL:
144
+
145
+ ```bash
146
+ linzumi start ~/code/my-app --kandan-url wss://<your-kandan-host>
85
147
  ```
86
148
 
87
- ## Basic Use
149
+ For Render-hosted Kandan, public TLS should work without local certificate
150
+ flags. The CLI derives the HTTPS API origin from the websocket URL for OAuth,
151
+ runtime manifest download, and runtime archive download.
88
152
 
89
- Running `linzumi` without arguments prints the local runner guide:
153
+ For local development with a private CA:
90
154
 
91
155
  ```bash
92
- linzumi
156
+ KANDAN_TLS_CA_FILE=/path/to/ca.crt linzumi start ~/code/my-app \
157
+ --kandan-url wss://linzumi.io:4140
93
158
  ```
94
159
 
95
- Start the runner for a Kandan workspace/channel:
160
+ ## Tailscale Development
161
+
162
+ If your browser needs to reach a local Kandan server through Tailscale:
96
163
 
97
164
  ```bash
98
- linzumi connect \
99
- --kandan-url wss://serve.kandanai.com \
100
- --workspace linzumi \
101
- --channel seans-playground \
102
- --codex-bin codex \
103
- --launch-tui
165
+ linzumi start ~/code/my-app \
166
+ --kandan-url ws://100.71.192.98:4162 \
167
+ --oauth-callback-host 100.71.192.98
104
168
  ```
105
169
 
106
- Leave that terminal process running while Kandan uses the local runner.
170
+ Use your own Tailscale IP.
107
171
 
108
172
  ## Commands
109
173
 
110
- Supported commands right now:
111
-
112
174
  ```bash
113
175
  linzumi
114
176
  linzumi --help
115
177
  linzumi --version
178
+ linzumi start <folder>
116
179
  linzumi connect --help
117
180
  linzumi connect [runner options]
118
181
  linzumi auth [auth options]
119
182
  ```
120
183
 
121
- `linzumi local-codex-runner` is accepted as a compatibility alias for
122
- `linzumi connect`.
184
+ Most people should use `linzumi start`.
185
+
186
+ `linzumi connect` is the lower-level command for connecting to an explicit
187
+ workspace and channel:
188
+
189
+ ```bash
190
+ linzumi connect \
191
+ --kandan-url wss://serve.kandanai.com \
192
+ --workspace default \
193
+ --channel general \
194
+ --cwd ~/code/my-app
195
+ ```
123
196
 
124
197
  ## Useful Options
125
198
 
126
199
  ```bash
127
- --kandan-url <ws-url> Kandan websocket URL, for example wss://serve.kandanai.com
128
- --workspace <slug> Workspace slug, for example linzumi
129
- --channel <slug|w/c> Channel slug, or workspace/channel
130
- --kandan-thread-id <uuid> Resume an existing Kandan thread
131
- --listen-user <user|all> User whose replies are accepted, default authenticated user
132
- --cwd <path> Working directory for Codex
133
- --codex-bin <path> Codex executable, default codex
134
- --model <name> Codex model
135
- --reasoning-effort <value> Codex reasoning effort
136
- --fast Request the fast service tier
137
- --launch-tui Launch codex --remote against the app-server
200
+ --kandan-url <ws-url> Kandan websocket URL
138
201
  --oauth-callback-host <ip> Callback host reachable by your browser
202
+ --runner-id <id> Stable id for this computer
203
+ --codex-bin <path> Codex executable, default codex
204
+ --model <name> Codex model metadata shown in Kandan
205
+ --reasoning-effort <value> Codex reasoning metadata shown in Kandan
206
+ --fast Mark this runner as low-latency
207
+ --forward-port <ports> Comma-separated local ports Kandan may expose
208
+ --allowed-cwd <paths> Comma-separated roots Kandan may use
209
+ --log-file <path> JSONL runner event log
139
210
  ```
140
211
 
141
- Run `linzumi connect --help` for the full option list.
212
+ `--code-server-bin` exists only as a development override. It is not the
213
+ supported production editor path.
142
214
 
143
215
  ## Troubleshooting
144
216
 
145
- If `linzumi` is not found, confirm the global npm bin directory is on your
146
- `PATH`.
217
+ Check the CLI version:
218
+
219
+ ```bash
220
+ linzumi --version
221
+ ```
222
+
223
+ Expected:
224
+
225
+ ```text
226
+ linzumi 0.0.7-beta
227
+ ```
228
+
229
+ If `linzumi` is not found, your global npm bin directory is not on `PATH`.
230
+
231
+ If `bun` is not found, install Bun and rerun `linzumi start`.
232
+
233
+ If `codex` is not found, install or configure the Codex CLI, or pass
234
+ `--codex-bin`.
147
235
 
148
- If `bun` is not found, install Bun first. This beta wraps the existing Bun local
149
- runner implementation instead of a Node rewrite.
236
+ If OAuth opens but does not return to the CLI, pass an
237
+ `--oauth-callback-host` that your browser can reach.
238
+
239
+ If the editor does not become ready, do not install a local code-server package
240
+ as a workaround. The server-managed runtime must download and verify cleanly.
241
+ Rerun the CLI and check the runner log.
242
+
243
+ If collaboration behaves oddly in Safari, retry in Chromium. Safari is currently
244
+ semi-supported.
245
+
246
+ ## For Kandan Release Engineers
247
+
248
+ The production contract is:
249
+
250
+ 1. Build the server-approved editor runtime archive.
251
+ 2. Publish the manifest and archive from Kandan.
252
+ 3. Publish the CLI beta.
253
+ 4. The CLI downloads only the approved runtime archive.
254
+ 5. The CLI verifies the archive SHA before advertising editor readiness.
255
+
256
+ For local package verification:
257
+
258
+ ```bash
259
+ bun test
260
+ npm pack --dry-run
261
+ ```
150
262
 
151
- If OAuth opens but does not return to the CLI, pass `--oauth-callback-host` with
152
- an IP address that your browser can reach, such as your Tailscale IP.
263
+ The npm package must include this README, `bin/linzumi.js`, and the `src`
264
+ runtime files.
package/package.json CHANGED
@@ -1,26 +1,33 @@
1
1
  {
2
2
  "name": "@linzumi/cli",
3
- "version": "0.0.5-beta",
4
- "description": "Linzumi local Codex runner CLI.",
3
+ "version": "0.0.7-beta",
4
+ "description": "Connect your computer to Kandan for local Codex sessions, editors, and forwarded previews",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "linzumi": "bin/linzumi.js"
8
8
  },
9
9
  "files": [
10
+ "README.md",
10
11
  "bin",
11
- "src",
12
- "README.md"
12
+ "src"
13
13
  ],
14
14
  "scripts": {
15
- "start": "bun run src/index.ts",
16
- "test": "bun test"
17
- },
18
- "engines": {
19
- "bun": ">=1.1.0",
20
- "node": ">=22.0.0"
15
+ "test": "bun test",
16
+ "pack:dry-run": "npm pack --dry-run"
21
17
  },
18
+ "keywords": [
19
+ "linzumi",
20
+ "kandan",
21
+ "codex",
22
+ "local-runner"
23
+ ],
24
+ "license": "MIT",
22
25
  "publishConfig": {
23
26
  "access": "public"
24
27
  },
25
- "license": "MIT"
28
+ "engines": {
29
+ "node": ">=20",
30
+ "bun": ">=1.2.0"
31
+ },
32
+ "readme": "# Linzumi CLI\n\nConnect your computer to Kandan so you can run Codex locally from the browser.\n\nLinzumi gives Kandan a secure, authenticated bridge to your own machine. You\nkeep the code, shells, editors, and preview servers local. Kandan gives you the\nweb UI, sharing controls, HTTPS editor access, forwarded previews, and Codex\nsession orchestration.\n\n## Copy And Paste\n\nUse a Chromium-based browser such as Chrome, Edge, Arc, or Brave.\n\n```bash\nnpm install -g @linzumi/cli@beta && linzumi start ~/code\n```\n\nTo pin this exact beta:\n\n```bash\nnpm install -g @linzumi/cli@0.0.7-beta && linzumi start ~/code\n```\n\nUse a different folder if your projects live somewhere else:\n\n```bash\nnpm install -g @linzumi/cli@beta && linzumi start ~/work/my-app\n```\n\nThat command opens Kandan, walks you through signup or sign-in, connects this\ncomputer, and lets Kandan start Codex against the folder you chose.\n\n## What You Can Do\n\nAfter `linzumi start` is connected, try this from Kandan:\n\n1. Start a Codex session.\n2. Ask Codex to inspect or edit a file in the folder you allowed.\n3. Open the local editor from Kandan.\n4. Start a dev server locally, then open its forwarded preview from Kandan.\n5. Share editor or preview access with another user.\n\nThe editor and previews open on Kandan HTTPS URLs. They should not expose\n`localhost` URLs to the browser.\n\n## What Linzumi Runs Locally\n\nThe CLI starts a local runner process on your computer. That runner:\n\n- launches or connects to Codex locally\n- downloads the Kandan-approved editor runtime when needed\n- starts code-server for the allowed folder\n- exposes only explicitly approved local ports through Kandan\n- keeps Kandan auth cookies and bearer tokens away from local services\n\nKandan remains the control plane. Browser traffic terminates at Kandan first,\nwhere auth, grants, and allowed-port policy are enforced before traffic is sent\nthrough the runner tunnel.\n\nIn the local-service hop, `127.0.0.1` means your computer, not the Kandan\nserver.\n\n## Requirements\n\nInstall these before running the beta:\n\n```bash\nnode --version\nnpm --version\nbun --version\ncodex --version\n```\n\nExpected:\n\n- Node.js 20 or newer\n- npm\n- Bun 1.2 or newer\n- Codex CLI\n- Chrome, Edge, Arc, Brave, or another Chromium-based browser\n\nSafari is semi-supported for now. Use Chromium for the best editor and\ncollaboration behavior.\n\n## First Run\n\n```bash\nlinzumi start ~/code\n```\n\nWhat happens:\n\n1. The CLI opens Kandan.\n2. You sign up or sign in.\n3. Kandan asks permission to connect this computer.\n4. The CLI stores a scoped local-runner token.\n5. The CLI checks Bun, Codex, and the Kandan editor runtime.\n6. Kandan shows the computer as connected.\n\nThe first editor launch can download a Kandan-approved runtime archive. Later\nruns reuse the verified runtime from:\n\n```text\n~/.linzumi/editor-runtimes\n```\n\nThe production path does not use a random local `code-server` install. Kandan\npublishes a checksummed runtime manifest, and the CLI only advertises editor\nreadiness after that runtime is verified locally.\n\n## Good Things To Try\n\nStart from a real project:\n\n```bash\nlinzumi start ~/code/my-app\n```\n\nThen in Kandan:\n\n```text\nSummarize this repository and tell me how to run it locally.\n```\n\nIf your app starts a dev server:\n\n```bash\nnpm run dev\n```\n\nOpen the detected forwarded port from Kandan. If a port is not auto-detected,\nrestart with an explicit approved port:\n\n```bash\nlinzumi start ~/code/my-app --forward-port 3000\n```\n\nFor a shared editor test, invite another user, open the local editor, and edit\nthe same file. Chromium should show remote cursor labels and selections.\n\n## Hosted Kandan\n\nFor a hosted Kandan deployment, point the CLI at the hosted websocket URL:\n\n```bash\nlinzumi start ~/code/my-app --kandan-url wss://<your-kandan-host>\n```\n\nFor Render-hosted Kandan, public TLS should work without local certificate\nflags. The CLI derives the HTTPS API origin from the websocket URL for OAuth,\nruntime manifest download, and runtime archive download.\n\nFor local development with a private CA:\n\n```bash\nKANDAN_TLS_CA_FILE=/path/to/ca.crt linzumi start ~/code/my-app \\\n --kandan-url wss://linzumi.io:4140\n```\n\n## Tailscale Development\n\nIf your browser needs to reach a local Kandan server through Tailscale:\n\n```bash\nlinzumi start ~/code/my-app \\\n --kandan-url ws://100.71.192.98:4162 \\\n --oauth-callback-host 100.71.192.98\n```\n\nUse your own Tailscale IP.\n\n## Commands\n\n```bash\nlinzumi\nlinzumi --help\nlinzumi --version\nlinzumi start <folder>\nlinzumi connect --help\nlinzumi connect [runner options]\nlinzumi auth [auth options]\n```\n\nMost people should use `linzumi start`.\n\n`linzumi connect` is the lower-level command for connecting to an explicit\nworkspace and channel:\n\n```bash\nlinzumi connect \\\n --kandan-url wss://serve.kandanai.com \\\n --workspace default \\\n --channel general \\\n --cwd ~/code/my-app\n```\n\n## Useful Options\n\n```bash\n--kandan-url <ws-url> Kandan websocket URL\n--oauth-callback-host <ip> Callback host reachable by your browser\n--runner-id <id> Stable id for this computer\n--codex-bin <path> Codex executable, default codex\n--model <name> Codex model metadata shown in Kandan\n--reasoning-effort <value> Codex reasoning metadata shown in Kandan\n--fast Mark this runner as low-latency\n--forward-port <ports> Comma-separated local ports Kandan may expose\n--allowed-cwd <paths> Comma-separated roots Kandan may use\n--log-file <path> JSONL runner event log\n```\n\n`--code-server-bin` exists only as a development override. It is not the\nsupported production editor path.\n\n## Troubleshooting\n\nCheck the CLI version:\n\n```bash\nlinzumi --version\n```\n\nExpected:\n\n```text\nlinzumi 0.0.7-beta\n```\n\nIf `linzumi` is not found, your global npm bin directory is not on `PATH`.\n\nIf `bun` is not found, install Bun and rerun `linzumi start`.\n\nIf `codex` is not found, install or configure the Codex CLI, or pass\n`--codex-bin`.\n\nIf OAuth opens but does not return to the CLI, pass an\n`--oauth-callback-host` that your browser can reach.\n\nIf the editor does not become ready, do not install a local code-server package\nas a workaround. The server-managed runtime must download and verify cleanly.\nRerun the CLI and check the runner log.\n\nIf collaboration behaves oddly in Safari, retry in Chromium. Safari is currently\nsemi-supported.\n\n## For Kandan Release Engineers\n\nThe production contract is:\n\n1. Build the server-approved editor runtime archive.\n2. Publish the manifest and archive from Kandan.\n3. Publish the CLI beta.\n4. The CLI downloads only the approved runtime archive.\n5. The CLI verifies the archive SHA before advertising editor readiness.\n\nFor local package verification:\n\n```bash\nbun test\nnpm pack --dry-run\n```\n\nThe npm package must include this README, `bin/linzumi.js`, and the `src`\nruntime files."
26
33
  }
@@ -13,6 +13,7 @@ export type LocalRunnerTokenResolutionArgs = {
13
13
  readonly explicitToken?: string | undefined;
14
14
  readonly workspaceSlug?: string | undefined;
15
15
  readonly channelSlug?: string | undefined;
16
+ readonly onboarding?: "start" | undefined;
16
17
  readonly authFilePath?: string | undefined;
17
18
  readonly callbackHost?: string | undefined;
18
19
  readonly reportRejectedCachedToken?: (() => void) | undefined;
@@ -61,6 +62,7 @@ async function acquireAndCacheToken(args: LocalRunnerTokenResolutionArgs): Promi
61
62
  kandanUrl: args.kandanUrl,
62
63
  workspaceSlug: args.workspaceSlug,
63
64
  channelSlug: args.channelSlug,
65
+ onboarding: args.onboarding,
64
66
  callbackHost: args.callbackHost,
65
67
  });
66
68
 
@@ -0,0 +1,57 @@
1
+ /*
2
+ - Date: 2026-04-26
3
+ Spec: kandan/server_v2/plans/2026-04-26-local-codex-driver-worldclass-spec.md
4
+ Relationship: Provides bounded in-memory registries for local Codex runner
5
+ state so long turns keep O(1) keyed lookup while retaining deterministic
6
+ eviction order for transcript reconciliation.
7
+ */
8
+
9
+ export type BoundedCache<TValue> = {
10
+ readonly limit: number;
11
+ readonly values: Map<string, TValue>;
12
+ };
13
+
14
+ export function createBoundedCache<TValue>(limit: number): BoundedCache<TValue> {
15
+ if (!Number.isInteger(limit) || limit <= 0) {
16
+ throw new Error(`invalid bounded cache limit: ${limit}`);
17
+ }
18
+
19
+ return {
20
+ limit,
21
+ values: new Map(),
22
+ };
23
+ }
24
+
25
+ export function getBoundedCacheValue<TValue>(
26
+ cache: BoundedCache<TValue>,
27
+ key: string,
28
+ ): TValue | undefined {
29
+ return cache.values.get(key);
30
+ }
31
+
32
+ export function rememberBoundedCacheValue<TValue>(
33
+ cache: BoundedCache<TValue>,
34
+ key: string,
35
+ value: TValue,
36
+ ): void {
37
+ cache.values.set(key, value);
38
+
39
+ while (cache.values.size > cache.limit) {
40
+ const evicted = cache.values.keys().next().value;
41
+
42
+ if (evicted !== undefined) {
43
+ cache.values.delete(evicted);
44
+ }
45
+ }
46
+ }
47
+
48
+ export function forgetBoundedCacheValue<TValue>(
49
+ cache: BoundedCache<TValue>,
50
+ key: string,
51
+ ): void {
52
+ cache.values.delete(key);
53
+ }
54
+
55
+ export function boundedCacheValues<TValue>(cache: BoundedCache<TValue>): TValue[] {
56
+ return [...cache.values.values()];
57
+ }