tabctl 0.5.3 → 0.6.0-alpha.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 (51) hide show
  1. package/README.md +135 -35
  2. package/dist/extension/background.js +179 -3155
  3. package/dist/extension/lib/content.js +0 -115
  4. package/dist/extension/lib/screenshot.js +0 -93
  5. package/dist/extension/manifest.json +2 -2
  6. package/package.json +13 -5
  7. package/dist/cli/lib/args.js +0 -141
  8. package/dist/cli/lib/client.js +0 -83
  9. package/dist/cli/lib/commands/doctor.js +0 -134
  10. package/dist/cli/lib/commands/index.js +0 -51
  11. package/dist/cli/lib/commands/list.js +0 -159
  12. package/dist/cli/lib/commands/meta.js +0 -229
  13. package/dist/cli/lib/commands/params-groups.js +0 -48
  14. package/dist/cli/lib/commands/params-move.js +0 -44
  15. package/dist/cli/lib/commands/params.js +0 -314
  16. package/dist/cli/lib/commands/profile.js +0 -91
  17. package/dist/cli/lib/commands/setup.js +0 -294
  18. package/dist/cli/lib/constants.js +0 -30
  19. package/dist/cli/lib/help.js +0 -205
  20. package/dist/cli/lib/options-commands.js +0 -274
  21. package/dist/cli/lib/options-groups.js +0 -41
  22. package/dist/cli/lib/options.js +0 -125
  23. package/dist/cli/lib/output.js +0 -147
  24. package/dist/cli/lib/pagination.js +0 -55
  25. package/dist/cli/lib/policy-filter.js +0 -202
  26. package/dist/cli/lib/policy.js +0 -91
  27. package/dist/cli/lib/report.js +0 -61
  28. package/dist/cli/lib/response.js +0 -235
  29. package/dist/cli/lib/scope.js +0 -250
  30. package/dist/cli/lib/snapshot.js +0 -216
  31. package/dist/cli/lib/types.js +0 -2
  32. package/dist/cli/tabctl.js +0 -475
  33. package/dist/extension/lib/archive.js +0 -444
  34. package/dist/extension/lib/deps.js +0 -4
  35. package/dist/extension/lib/groups.js +0 -529
  36. package/dist/extension/lib/inspect.js +0 -252
  37. package/dist/extension/lib/move.js +0 -342
  38. package/dist/extension/lib/tabs.js +0 -456
  39. package/dist/extension/lib/undo-handlers.js +0 -447
  40. package/dist/host/host.bundle.js +0 -670
  41. package/dist/host/host.js +0 -143
  42. package/dist/host/host.sh +0 -5
  43. package/dist/host/launcher/go.mod +0 -3
  44. package/dist/host/launcher/main.go +0 -109
  45. package/dist/host/lib/handlers.js +0 -327
  46. package/dist/host/lib/undo.js +0 -60
  47. package/dist/shared/config.js +0 -134
  48. package/dist/shared/extension-sync.js +0 -170
  49. package/dist/shared/profiles.js +0 -78
  50. package/dist/shared/version.js +0 -8
  51. package/dist/shared/wrapper-health.js +0 -132
package/README.md CHANGED
@@ -7,13 +7,21 @@ A command-line instrument for browser tab orchestration — list, search, group,
7
7
  ## Install
8
8
 
9
9
  ```bash
10
- npm install -g tabctl
11
- tabctl setup --browser chrome
12
- # Load the extension: chrome://extensions → Developer mode → Load unpacked → paste: ~/.local/state/tabctl/extension/
10
+ mise use -g github:ekroon/tabctl # install the tabctl binary
11
+ tabctl setup --browser edge --extension-id <id> # or: --browser chrome --extension-id <id>
12
+ # Load the extension: edge://extensions → Developer mode → Load unpacked → paste: ~/.local/state/tabctl/extension/
13
13
  tabctl ping
14
14
  ```
15
15
 
16
- If it pings back, the wire is live. You're connected.
16
+ Setup writes the wrapper script, native messaging manifest, and registers the profile in one step. Works on macOS, Linux, and Windows. If it pings back, the wire is live. You're connected.
17
+
18
+ ### Alternative: build from source
19
+
20
+ ```bash
21
+ cargo install --path rust/crates/tabctl
22
+ ```
23
+
24
+ > **Legacy:** `npm install -g tabctl` still works for the Node.js-based distribution but is no longer the primary install method. No Node.js or Go is required at runtime — the single `tabctl` binary handles everything.
17
25
 
18
26
  ## Agent Skill
19
27
 
@@ -54,28 +62,44 @@ When tabctl is installed as a skill, your agent sees what you see. Just talk to
54
62
 
55
63
  ---
56
64
 
57
- `tabctl` works through a lightweight local stack: the CLI talks to a native messaging host, which proxies requests to a browser extension. The host only runs while the browser is open and the extension is connected.
65
+ `tabctl` is a single Rust binary that serves as both the CLI and the native messaging host. The CLI sends commands over a Unix socket (or named pipe on Windows) to the host, which proxies them to the browser extension via native messaging. The `tabctl host` subcommand is the native messaging entry point — invoked automatically by the browser, not manually.
58
66
 
59
67
  This repo contains:
60
- - Chrome/Edge extension (tab/group inspection + actions)
61
- - Native messaging host (Node)
62
- - CLI (`tabctl`) for on-demand workflows
68
+ - Chrome/Edge extension (`src/extension/`, the only TypeScript component)
69
+ - Rust workspace (`rust/crates/*`) — single `tabctl` binary for CLI + host + shared runtime
70
+ - Node packaging/build scripts for distribution (legacy)
63
71
 
64
72
  ## Quick Start
65
73
 
66
74
  ### 1. Build and install
67
75
 
76
+ ```bash
77
+ cargo install --path rust/crates/tabctl # puts tabctl on your PATH
78
+ ```
79
+
80
+ For development with the full build pipeline (extension + Rust):
81
+
68
82
  ```bash
69
83
  npm install
70
84
  npm run build
71
- npm link # puts tabctl on your PATH
72
85
  ```
73
86
 
74
- If you haven't run `npm link`, you can always use `node ./cli/tabctl.js` instead of `tabctl`.
87
+ Local development shortcuts are available via `Makefile`:
88
+
89
+ ```bash
90
+ make dev-up BROWSER=edge PROFILE=edge
91
+ make dev-run PROFILE=edge CMD="list --all --json"
92
+ make dev-run-release-like PROFILE=edge CMD="list --all --json"
93
+ ```
94
+
95
+ If `npm` is not on PATH in your shell, override it per command:
96
+ ```bash
97
+ make dev-build NPM=~/.local/share/mise/shims/npm
98
+ ```
75
99
 
76
100
  ### 2. Set up your browser
77
101
 
78
- Run setup it syncs the extension, tells you where to load it, and auto-derives the extension ID:
102
+ Run setup to write the manifest, wrapper script, and profile registration:
79
103
 
80
104
  <!-- test: "setup explicit --extension-id overrides auto-derived ID" -->
81
105
  ```bash
@@ -83,25 +107,32 @@ tabctl setup --browser chrome
83
107
  ```
84
108
 
85
109
  This will:
86
- 1. Copy the extension to a stable location (`~/.local/state/tabctl/extension/`)
87
- 2. Print the path (and copy it to your clipboard)
88
- 3. Ask you to load it as an unpacked extension in `chrome://extensions`
89
- 4. Auto-derive the extension ID from the installed path
110
+ 1. Write the native messaging manifest and wrapper script
111
+ 2. Register the browser profile in `profiles.json`
112
+ 3. Download the version-pinned release extension asset (`tabctl-extension.zip` + `.sha256`) into the tabctl data directory
113
+ 4. Sync the managed unpacked extension directory to the tabctl version (`~/.local/state/tabctl/extension/`)
114
+ 5. Derive the extension ID from the managed extension path (or use explicit `--extension-id`)
115
+ 6. Print the path for loading as an unpacked extension in `chrome://extensions`
116
+
117
+ For local dev builds (no GitHub download), point setup at an unpacked directory:
118
+ ```bash
119
+ tabctl setup --browser chrome --extension-dir dist/extension
120
+ ```
90
121
 
91
122
  > **Edge?** Use `--browser edge` and load from `edge://extensions` instead.
123
+ >
124
+ > **Cross-platform:** setup works on macOS, Linux, and Windows. On Windows, setup verifies connectivity after writing setup artifacts and checks the runtime extension ID reported by the browser. Connectivity failures and runtime extension ID mismatches exit non-zero and print manual recovery steps (including expected vs runtime IDs).
92
125
 
93
- If you need to override the auto-derived ID (e.g. for a custom extension path):
94
-
95
- <!-- test: "setup writes native host manifest for chrome" -->
96
- ```bash
97
- tabctl setup --browser chrome --extension-id <your-extension-id>
98
- ```
126
+ Optional setup release overrides:
127
+ - Flags: `--extension-dir`, `--release-repo`, `--release-tag` (or `--release-version`), `--release-asset`, `--skip-extension-download`
128
+ - Env vars: `TABCTL_SETUP_EXTENSION_DIR`, `TABCTL_RELEASE_REPO`, `TABCTL_RELEASE_TAG`, `TABCTL_RELEASE_ASSET`, `TABCTL_SETUP_FETCH_EXTENSION=0`
129
+ - Precedence: flags override env vars, then built-in defaults; if download fails, setup continues and includes warning details in setup output.
99
130
 
100
131
  ### 3. Verify and explore
101
132
 
102
133
  <!-- test: "ping sends ping action", "list sends list action" -->
103
134
  ```bash
104
- tabctl ping # check the connection
135
+ tabctl ping # check connection + runtime version sync
105
136
  tabctl list # see your open tabs
106
137
  ```
107
138
 
@@ -209,6 +240,46 @@ See [CLI.md](CLI.md#configuration) for full details.
209
240
  - Socket: `<dataDir>/tabctl.sock` (default: `~/.local/state/tabctl/tabctl.sock`)
210
241
  - Undo log: `<dataDir>/undo.jsonl` (default: `~/.local/state/tabctl/undo.jsonl`)
211
242
  - Profile registry: `<configDir>/profiles.json`
243
+ - WSL TCP port file: `<dataDir>/tcp-port` (written by the Windows host)
244
+
245
+ ## Windows + WSL transport
246
+
247
+ On Windows, the host exposes a dual endpoint model:
248
+ - Windows native clients use a named pipe endpoint (`\\.\pipe\tabctl-<hash>`).
249
+ - WSL/Linux clients use `tcp://127.0.0.1:<port>`, with the host writing `<dataDir>/tcp-port`.
250
+
251
+ WSL endpoint discovery (CLI):
252
+ 1. `TABCTL_SOCKET` (explicit endpoint); if this is a pipe endpoint in WSL, CLI still prefers discovered TCP.
253
+ 2. `TABCTL_TCP_PORT` (forces `127.0.0.1:<port>`).
254
+ 3. `tcp-port` file discovery from resolved data dir (and equivalent `/mnt/c/Users/*/.../tabctl/.../tcp-port` locations).
255
+ 4. Fallback: `tcp://127.0.0.1:38000`.
256
+
257
+ Relevant knobs: `TABCTL_SOCKET`, `TABCTL_TCP_PORT`, `TABCTL_PROFILE`, `TABCTL_DATA_DIR`, `TABCTL_STATE_DIR`, `TABCTL_CONFIG_DIR`.
258
+
259
+ ## Troubleshooting (setup/ping on Windows + WSL)
260
+
261
+ - `tabctl setup` fails with `Windows setup verification failed`: check `data.verification.reason` in JSON output (`ping-timeout`, `socket-not-found`, `socket-refused`, `ping-not-ok`, `extension-id-mismatch`), then follow printed manual steps.
262
+ - Runtime ID mismatch (`extension-id-mismatch`): compare expected vs runtime IDs from setup output, then rerun setup with the runtime ID shown by `edge://extensions` / `chrome://extensions`:
263
+ - `tabctl setup --browser <edge|chrome> --extension-id <runtime-id>`
264
+ - Runtime command runs can auto-sync extension files when host/extension versions drift; rerun `tabctl reload` if the browser does not pick up changes immediately.
265
+ - For local release-like testing while developing, force runtime sync behavior with `TABCTL_AUTO_SYNC_MODE=release-like`.
266
+ - Disable runtime sync entirely with `TABCTL_AUTO_SYNC_MODE=off`.
267
+ - `tabctl ping --json` is the canonical runtime version check (`versionsInSync`, `hostBaseVersion`, `baseVersion`).
268
+ - Version metadata is intentionally health-only: regular command payloads (`open`, `list`, etc.) do not include version fields.
269
+ - `tabctl ping` returns connect errors (`ENOENT`, `ECONNREFUSED`, timeout): ensure extension is loaded and active, rerun `tabctl setup`, and in WSL verify `TABCTL_TCP_PORT` or `<dataDir>/tcp-port` matches a listening localhost port.
270
+ - `tabctl doctor --fix --json` includes per-profile connectivity diagnostics in `data.profiles[].connectivity`; if ping remains unhealthy after local repairs, follow `manualSteps`.
271
+
272
+ Local release-like sync test recipe:
273
+ ```bash
274
+ # 1) Install an older extension release into managed extension path
275
+ tabctl setup --browser edge --extension-id <extension-id> --release-tag v0.5.2
276
+
277
+ # 2) Run the current binary with forced release-like auto-sync
278
+ TABCTL_AUTO_SYNC_MODE=release-like cargo run --manifest-path rust/Cargo.toml -p tabctl -- list --all
279
+
280
+ # 3) Verify host/extension base versions are back in sync
281
+ tabctl ping --json
282
+ ```
212
283
 
213
284
  ## Multi-Browser Setup
214
285
 
@@ -219,10 +290,10 @@ tabctl supports multiple browser profiles. Each profile connects to a different
219
290
  <!-- test: "setup writes native host manifest", "setup writes native host manifest for chrome", "setup --name creates custom-named profile", "profile-list with multiple profiles shows all", "profile-switch success updates default", "--profile flag overrides active profile" -->
220
291
  ```bash
221
292
  # Setup for Edge
222
- tabctl setup --browser edge
293
+ tabctl setup --browser edge --extension-id <edge-extension-id>
223
294
 
224
295
  # Setup for Chrome (with custom name)
225
- tabctl setup --browser chrome --name chrome-work
296
+ tabctl setup --browser chrome --name chrome-work --extension-id <chrome-extension-id>
226
297
 
227
298
  # List profiles
228
299
  tabctl profile-list
@@ -258,24 +329,34 @@ Policy is shared across all profiles.
258
329
  ## Security
259
330
  - The native host is locked to your extension ID.
260
331
  - All data stays local; no external API keys are used.
332
+ - TCP connections (used for WSL ↔ Windows communication) are secured with a per-session auth token. The host generates a random token on startup; the CLI reads it automatically. See [CLI.md](CLI.md) for details.
333
+ - TCP transport is available on all platforms via `TABCTL_HOST_TCP=1` (host) and `TABCTL_TRANSPORT=tcp` (CLI). All TCP connections are authenticated. See [CLI.md](CLI.md) for details.
261
334
 
262
335
  ## Development
263
336
 
264
- ### TypeScript workflow
265
- Source lives in `src/` and compiles to `build/`, then syncs to the runtime locations:
266
- - `src/extension/background.ts` -> `extension/background.js`
267
- - `src/host/host.ts` -> `host/host.js`
268
- - `src/cli/tabctl.ts` -> `cli/tabctl.js`
269
- - `src/tests/unit/*.ts` -> `tests/unit/*.js`
337
+ ### Build workflow
338
+ The single `tabctl` binary is built from the Rust workspace (`rust/`). TypeScript is limited to the browser extension boundary (`src/extension/`). No Node.js or Go is required at runtime.
270
339
 
271
- Build and test:
340
+ Build and verify:
272
341
 
273
342
  ```bash
274
- npm install
275
- npm run build
276
- npm test
343
+ cargo build --release -p tabctl # build the binary
344
+ npm install && npm run build # full pipeline (extension + Rust)
345
+ npm test # unit tests
277
346
  ```
278
347
 
348
+ Rust-only validation:
349
+ ```bash
350
+ npm run rust:verify
351
+ ```
352
+
353
+ Browser-backed integration harness (requires built dist artifacts and Chrome):
354
+ ```bash
355
+ npm run test:integration
356
+ ```
357
+
358
+ WSL CI validates the WSL->Windows invocation bridge (`test.yml` `wsl` job) with phases: `prerequisites`, `diagnostics`, `build_and_unit`, `setup_validation`, `windows_invocation`, `integration`. Runtime/build execution is delegated to Windows commands (`cmd.exe`/`powershell.exe`), so WSL-local Rust compilation is not required.
359
+
279
360
  ### Versioning
280
361
  The base version lives in `package.json` and is embedded into the CLI, host, and extension at build time.
281
362
 
@@ -284,6 +365,25 @@ Commands:
284
365
  npm run bump:patch
285
366
  npm run bump:minor
286
367
  npm run bump:major
368
+ npm run bump:alpha
369
+ npm run bump:rc
370
+ npm run bump:stable
371
+ ```
372
+
373
+ Pre-release staging flow:
374
+ - `bump:alpha` creates/increments `x.y.z-alpha.N`
375
+ - `bump:rc` promotes alpha to `x.y.z-rc.1` (or increments RC)
376
+ - `bump:stable` drops the prerelease suffix for final stable publish
377
+
378
+ Release publishing (`.github/workflows/publish.yml`) enforces:
379
+ - Git tag must match `package.json` version (`v<version>`)
380
+ - prerelease tags publish to `alpha`/`rc`; stable publishes to `latest`
381
+ - `npm run build` and `npm test` must pass before publish
382
+ - release assets include `tabctl-extension.zip` plus `tabctl-extension.zip.sha256`
383
+
384
+ Fetch the extension asset from a release with:
385
+ ```bash
386
+ tabctl extension-fetch --version 0.5.3
287
387
  ```
288
388
 
289
389
  Local builds default to a dev version when a `.git` directory is present, appending the short SHA.
@@ -309,5 +409,5 @@ Notes:
309
409
  - Selector `attr` supports `href-url`/`src-url` to return absolute http(s) URLs.
310
410
  - `screenshot --out` writes per-tab folders into the target directory.
311
411
  - `tabctl undo` accepts a positional txid, `--txid`, or `--latest`.
312
- - `tabctl history --json` returns a JSON array in `data`.
412
+ - `tabctl history --json` returns a top-level JSON array.
313
413
  - `--format` is only supported by `report` (use `--json` elsewhere).