gearbox-code 0.1.7 → 0.1.8

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,117 +1,93 @@
1
- # gearbox
1
+ # gearbox
2
2
 
3
- A beautiful, simple coding harness for the terminal. It reads, edits, and runs your code through one clean agent loop, talking to any provider (Anthropic, OpenAI, Google, DeepSeek).
3
+ ## Install
4
4
 
5
- > **What it does:** the point of Gearbox is *intelligent per-task model routing* — automatically using the right model for each task across every provider and account you pay for, cheaply and transparently. Basic routing is live: it classifies each task, filters candidates by quality bar, and picks the cheapest one that fits. The richer engine (shadow-eval, credit/limit scoring, confidence display) layers on top. See [`DESIGN.md`](./DESIGN.md).
5
+ macOS, Linux, WSL:
6
6
 
7
+ ```bash
8
+ curl -fsSL https://unpkg.com/gearbox-code@latest/install.sh | bash
7
9
  ```
8
- ⚙ gearbox
9
- coding harness · sonnet-4.6
10
- ──────────────────────────────────────────────────────────
11
-
12
- › add a --json flag to the CLI and cover it with a test
13
10
 
14
- ⏺ I'll see how args are parsed, add the flag, then test it.
15
-
16
- ✓ read_file src/cli.tsx
17
- renders the Ink app · 18 lines
18
- ✓ edit_file src/cli.tsx
19
- ✓ run_shell bun test
20
- 9 pass · 0 fail
21
-
22
- ⏺ Done — flag added with a passing test.
11
+ Windows PowerShell:
23
12
 
24
- ╭──────────────────────────────────────────────────────────╮
25
- │ › ask gearbox to build or fix something │
26
- ╰──────────────────────────────────────────────────────────╯
27
- gearbox · sonnet-4.6 · 18,432 tok · ⏎ send ctrl+c quit
13
+ ```powershell
14
+ irm https://unpkg.com/gearbox-code@latest/install.ps1 | iex
28
15
  ```
29
16
 
30
- ## Run
17
+ These installers do not use `sudo`, admin privileges, or `npm install -g`.
18
+ They install Gearbox into a user-owned directory, create the `gearbox` command,
19
+ then start onboarding before the coding app opens.
31
20
 
32
- ```bash
33
- bun install
34
- gearbox auth add <api-key> # paste-detects common providers when possible
35
- # or: gearbox auth add <provider> <api-key>
36
- # or: gearbox auth import # import keys from env/cloud credentials
37
- bun start # or: bun run src/cli.tsx
38
- bun start -- --model gemini-flash # pick a model
39
- ```
40
-
41
- No provider configured? Gearbox opens a setup screen and will not run a fake model. Preview the look without running anything:
21
+ Run without installing:
42
22
 
43
23
  ```bash
44
- bun run scripts/preview.tsx
24
+ npx gearbox-code@latest
45
25
  ```
46
26
 
47
- ## Install
27
+ ## First Run
48
28
 
49
- macOS, Linux, WSL:
29
+ Gearbox needs one provider account before it opens the coding app. The installer
30
+ runs setup automatically. You can also run it yourself:
50
31
 
51
32
  ```bash
52
- curl -fsSL https://unpkg.com/gearbox-code@latest/install.sh | bash
33
+ gearbox onboard
53
34
  ```
54
35
 
55
- Windows PowerShell:
36
+ Common setup commands:
56
37
 
57
- ```powershell
58
- irm https://unpkg.com/gearbox-code@latest/install.ps1 | iex
38
+ ```bash
39
+ gearbox auth add <api-key> # auto-detects known key prefixes
40
+ gearbox auth add <provider> <api-key> # anthropic, openai, google, deepseek, openrouter, groq, xai, mistral...
41
+ gearbox auth import # import credentials from env/cloud config
42
+ gearbox auth providers # list supported providers
59
43
  ```
60
44
 
61
- The installers are served from the published npm package, download the latest
62
- `gearbox-code` tarball, and create a user-owned `gearbox` command. They avoid
63
- `sudo`, admin privileges, and `npm install -g`.
64
-
65
- Then:
45
+ After setup:
66
46
 
67
47
  ```bash
68
- gearbox auth add <api-key> # each person uses their own provider account
69
- cd ~/any/project && gearbox # the current directory is the workspace
48
+ cd ~/your-project
49
+ gearbox
70
50
  ```
71
51
 
72
- If `~/.local/bin` is not on your PATH, the installer prints the exact line to
73
- add to your shell config.
52
+ No account configured means no fake/demo model: Gearbox runs onboarding first.
74
53
 
75
- You can still run without installing:
54
+ ## Uninstall
55
+
56
+ macOS, Linux, WSL:
76
57
 
77
58
  ```bash
78
- npx gearbox-code@latest
59
+ rm -f ~/.local/bin/gearbox
60
+ rm -rf ~/.local/share/gearbox
79
61
  ```
80
62
 
81
- **Upgrade** later by rerunning the install command. `gearbox upgrade` still works
82
- for git checkouts.
63
+ Windows PowerShell:
83
64
 
84
- ## Develop From Source
65
+ ```powershell
66
+ Remove-Item "$env:LOCALAPPDATA\Gearbox" -Recurse -Force
67
+ ```
85
68
 
86
- Requires [Bun](https://bun.sh). Clone the repo, then:
69
+ If you previously installed with npm global:
87
70
 
88
71
  ```bash
89
- bun install
90
- bun run src/cli.tsx
72
+ npm uninstall -g gearbox-code
91
73
  ```
92
74
 
93
- **Standalone binary** (no clone/install on the target, same OS/arch):
75
+ ## What It Is
94
76
 
95
- ```bash
96
- bun run build # dist/gearbox (single ~64MB executable)
97
- cp dist/gearbox ~/.bun/bin/ # or anywhere on PATH; share the file directly
98
- ```
77
+ Gearbox is a terminal coding agent that can use the model accounts you already
78
+ pay for. It supports provider accounts, local credential storage, model routing,
79
+ session history, file edits, shell commands, and permission gates.
99
80
 
100
- > **Before running on real code:** there is no permission/confirm gate yet — `write_file`, `edit_file`, `run_shell`, and the `!` prefix execute without asking. Fine for trusted internal use on your own repos; do not point it at anything you don't want modified. A confirm-gate is the next thing to land.
81
+ Supported setup paths include API keys, detected env/cloud credentials, Azure,
82
+ and provider CLIs where available.
101
83
 
102
84
  ## Develop
103
85
 
86
+ Requires [Bun](https://bun.sh).
87
+
104
88
  ```bash
105
- bun test # render + agent tests (no API key needed)
89
+ bun install
90
+ bun run src/cli.tsx
91
+ bun test
106
92
  bun run typecheck
107
93
  ```
108
-
109
- ## Principles
110
-
111
- - **Open + free.** MIT. No paid dependencies, no hosted backend, no telemetry. The only cost is your own model calls on your own keys.
112
- - **Beautiful + calm.** One accent color, generous spacing, consistent glyphs. The whole look lives in `src/ui/theme.ts`.
113
- - **Routing-ready.** Model choice happens in exactly one place (`src/model/selector.ts`); the router drops in there later with no changes upstream. See [`CLAUDE.md`](./CLAUDE.md).
114
-
115
- ## Status
116
-
117
- v0.1 — streaming agent loop, real file + shell tools, a polished Ink TUI, multi-provider support, accounts + spend ledger, BM25 context retrieval, and basic per-task routing (classify → quality bar → cheapest winner). The richer routing engine (shadow-eval, credit/limit/plan scoring, per-repo calibration) is next (`DESIGN.md`).
package/dist/cli.mjs CHANGED
@@ -63894,8 +63894,18 @@ var require_src6 = __commonJS((exports) => {
63894
63894
  });
63895
63895
 
63896
63896
  // src/proc.ts
63897
+ var exports_proc = {};
63898
+ __export(exports_proc, {
63899
+ write: () => writeFile,
63900
+ which: () => which,
63901
+ spawnSyncProc: () => spawnSyncProc,
63902
+ spawnProc: () => spawnProc,
63903
+ readStream: () => readStream,
63904
+ Glob: () => Glob
63905
+ });
63897
63906
  import { spawn, spawnSync as nodeSpawnSync, execFileSync } from "node:child_process";
63898
63907
  import { readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
63908
+ import { writeFile } from "node:fs/promises";
63899
63909
  import { resolve as resolve6 } from "node:path";
63900
63910
  function which(bin) {
63901
63911
  try {
@@ -64270,6 +64280,13 @@ var init_onboarding = __esm(() => {
64270
64280
  });
64271
64281
 
64272
64282
  // src/agent/cli-backend.ts
64283
+ var exports_cli_backend = {};
64284
+ __export(exports_cli_backend, {
64285
+ subscriptionEnv: () => subscriptionEnv,
64286
+ runCliTask: () => runCliTask,
64287
+ parseCliLines: () => parseCliLines,
64288
+ buildCliArgs: () => buildCliArgs
64289
+ });
64273
64290
  function newState() {
64274
64291
  return { text: "", usage: { inputTokens: 0, outputTokens: 0 }, rates: new Map, toolNames: new Map };
64275
64292
  }
@@ -64407,6 +64424,22 @@ function buildCliArgs(binary, prompt, opts = {}) {
64407
64424
  args.push("--resume", opts.sessionId);
64408
64425
  return args;
64409
64426
  }
64427
+ function parseCliLines(binary, lines, onEvent) {
64428
+ const state = newState();
64429
+ for (const line of lines) {
64430
+ const t2 = line.trim();
64431
+ if (!t2)
64432
+ continue;
64433
+ let obj;
64434
+ try {
64435
+ obj = JSON.parse(t2);
64436
+ } catch {
64437
+ continue;
64438
+ }
64439
+ mapCliEvent(binary, obj, state, onEvent);
64440
+ }
64441
+ return finalize(state);
64442
+ }
64410
64443
  function finalize(state) {
64411
64444
  return { messages: [], usage: state.usage, sessionId: state.sessionId, costUSD: state.costUSD, rates: [...state.rates.values()] };
64412
64445
  }
@@ -70267,7 +70300,8 @@ var import_react20 = __toESM(require_react(), 1);
70267
70300
  // node_modules/ink/build/hooks/use-focus-manager.js
70268
70301
  var import_react21 = __toESM(require_react(), 1);
70269
70302
  // src/cli.tsx
70270
- import { execFileSync as execFileSync4 } from "node:child_process";
70303
+ import { createInterface } from "node:readline/promises";
70304
+ import { execFileSync as execFileSync4, spawnSync } from "node:child_process";
70271
70305
  import { resolve as resolve11 } from "node:path";
70272
70306
  import { existsSync as existsSync8 } from "node:fs";
70273
70307
 
@@ -121288,6 +121322,9 @@ function pickDefaultModel(preferredId) {
121288
121322
  return wanted;
121289
121323
  return MODELS.find((m2) => providerAvailable(m2.provider));
121290
121324
  }
121325
+ function anyProviderAvailable() {
121326
+ return MODELS.some((m2) => providerAvailable(m2.provider));
121327
+ }
121291
121328
 
121292
121329
  // src/model/selector.ts
121293
121330
  class FixedSelector {
@@ -131808,7 +131845,7 @@ var uiMessagesSchema = lazyValidator3(() => zodSchema7(exports_external.array(ex
131808
131845
  })).nonempty("Messages array must not be empty")));
131809
131846
 
131810
131847
  // src/tools.ts
131811
- import { readFile, writeFile, readdir, stat as stat2 } from "node:fs/promises";
131848
+ import { readFile, writeFile as writeFile2, readdir, stat as stat2 } from "node:fs/promises";
131812
131849
  import { existsSync as existsSync3 } from "node:fs";
131813
131850
  import { resolve as resolve7, relative, isAbsolute } from "node:path";
131814
131851
  // node_modules/diff/libesm/diff/base.js
@@ -132171,7 +132208,7 @@ function createTools(onEvent) {
132171
132208
  if (!await requestPermission({ kind: "write", title: exists ? "Overwrite a file" : "Create a file", detail: path }))
132172
132209
  throw new Error(DENIED);
132173
132210
  const before2 = exists ? await readFile(abs, "utf8") : "";
132174
- await writeFile(abs, content, "utf8");
132211
+ await writeFile2(abs, content, "utf8");
132175
132212
  const diff2 = computeDiff(before2, content);
132176
132213
  return { summary: `wrote ${path} (${diffStat(diff2)})`, diff: diff2 };
132177
132214
  }
@@ -132187,7 +132224,7 @@ function createTools(onEvent) {
132187
132224
  if (!await requestPermission({ kind: "edit", title: "Edit a file", detail: path }))
132188
132225
  throw new Error(DENIED);
132189
132226
  const after2 = before2.replace(find2, replace2);
132190
- await writeFile(abs, after2, "utf8");
132227
+ await writeFile2(abs, after2, "utf8");
132191
132228
  const diff2 = computeDiff(before2, after2);
132192
132229
  return { summary: `edited ${path} (${diffStat(diff2)})`, diff: diff2 };
132193
132230
  }
@@ -136244,8 +136281,153 @@ function App2({ selector: initialSelector, runner, fullscreen = false, resumeId
136244
136281
  var jsx_dev_runtime13 = __toESM(require_jsx_dev_runtime(), 1);
136245
136282
  process.env.LANG = process.env.LANG || "en_US.UTF-8";
136246
136283
  process.env.LC_ALL = process.env.LC_ALL || "en_US.UTF-8";
136247
- var VERSION16 = "0.1.7";
136284
+ var VERSION16 = "0.1.8";
136248
136285
  var args = process.argv.slice(2);
136286
+ async function runCliOnboarding() {
136287
+ const { listAccounts: listAccounts2 } = await Promise.resolve().then(() => (init_store(), exports_store));
136288
+ const { importableEnvCreds: importableEnvCreds2, importEnvCred: importEnvCred2, importableCloudCreds: importableCloudCreds2, importCloudCred: importCloudCred2 } = await Promise.resolve().then(() => (init_detect(), exports_detect));
136289
+ const { addApiKeyAccount: addApiKeyAccount2, addAzureAccount: addAzureAccount2, addAzureFoundryAccount: addAzureFoundryAccount2, addByPastedKey: addByPastedKey2, testAccount: testAccount2, addableProviders: addableProviders2, addCliAccount: addCliAccount2, cliAuthStatus: cliAuthStatus2, cliLoginArgs: cliLoginArgs2 } = await Promise.resolve().then(() => (init_onboard(), exports_onboard));
136290
+ const { subscriptionEnv: subscriptionEnv2 } = await Promise.resolve().then(() => (init_cli_backend(), exports_cli_backend));
136291
+ const { detectProviderByKey: detectProviderByKey2 } = await Promise.resolve().then(() => (init_catalog(), exports_catalog));
136292
+ const { which: which2 } = await Promise.resolve().then(() => (init_proc(), exports_proc));
136293
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
136294
+ const ask = async (q) => (await rl.question(q)).trim();
136295
+ const providerRows = () => addableProviders2().map((p) => ` ${p.id.padEnd(16)} ${p.label}`).join(`
136296
+ `);
136297
+ const testAndReport = async (account) => {
136298
+ console.log("Testing credential...");
136299
+ const t2 = await testAccount2(account);
136300
+ console.log(t2.ok ? `OK: ${t2.message}` : `Stored, but the test failed: ${t2.message}`);
136301
+ };
136302
+ const addSubscription = async (provider) => {
136303
+ const res = addCliAccount2(provider);
136304
+ console.log(res.message);
136305
+ if (!res.ok || !res.account || res.account.auth.kind !== "cli")
136306
+ return false;
136307
+ const bin = res.account.auth.binary;
136308
+ const profile = res.account.auth.loginProfile;
136309
+ let status = await cliAuthStatus2(bin, profile);
136310
+ if (!status.loggedIn) {
136311
+ console.log(`Starting ${bin} sign-in...`);
136312
+ const r2 = spawnSync(bin, cliLoginArgs2(bin), { stdio: "inherit", env: subscriptionEnv2(bin, profile) });
136313
+ if ((r2.status ?? 1) !== 0)
136314
+ return false;
136315
+ status = await cliAuthStatus2(bin, profile);
136316
+ }
136317
+ if (!status.loggedIn) {
136318
+ console.log(`${bin} did not report a completed sign-in.`);
136319
+ return false;
136320
+ }
136321
+ console.log(`OK: ${bin} subscription ready${status.detail ? ` (${status.detail})` : ""}`);
136322
+ return true;
136323
+ };
136324
+ try {
136325
+ console.log("");
136326
+ console.log("Gearbox setup");
136327
+ console.log("One provider account is required before the coding app opens.");
136328
+ console.log("");
136329
+ while (!anyProviderAvailable()) {
136330
+ const env3 = importableEnvCreds2();
136331
+ const cloud = importableCloudCreds2();
136332
+ const existing = listAccounts2();
136333
+ if (existing.length)
136334
+ break;
136335
+ console.log("Choose a setup path:");
136336
+ if (env3.length || cloud.length)
136337
+ console.log(" 1) Import detected credentials");
136338
+ console.log(" 2) Paste an API key");
136339
+ console.log(" 3) Choose provider + API key");
136340
+ console.log(" 4) Azure OpenAI / Azure AI Foundry");
136341
+ if (which2("claude"))
136342
+ console.log(" 5) Claude subscription CLI");
136343
+ if (which2("codex"))
136344
+ console.log(" 6) ChatGPT subscription CLI");
136345
+ console.log(" p) Show providers");
136346
+ console.log(" q) Quit setup");
136347
+ console.log("");
136348
+ const choice = (await ask("Selection: ")).toLowerCase();
136349
+ if (choice === "q" || choice === "quit" || choice === "skip") {
136350
+ console.log("");
136351
+ console.log("Setup skipped. Run `gearbox onboard` when you are ready.");
136352
+ return false;
136353
+ }
136354
+ if (choice === "p" || choice === "providers") {
136355
+ console.log("");
136356
+ console.log(providerRows());
136357
+ console.log("");
136358
+ continue;
136359
+ }
136360
+ if (choice === "1" && (env3.length || cloud.length)) {
136361
+ for (const c of env3)
136362
+ await importEnvCred2(c);
136363
+ for (const c of cloud)
136364
+ await importCloudCred2(c);
136365
+ console.log(`Imported ${env3.length + cloud.length} credential${env3.length + cloud.length === 1 ? "" : "s"}.`);
136366
+ break;
136367
+ }
136368
+ if (choice === "2") {
136369
+ const key = await ask("Paste API key: ");
136370
+ if (!key)
136371
+ continue;
136372
+ const detected = detectProviderByKey2(key);
136373
+ if (!detected) {
136374
+ console.log("Could not detect the provider from that key. Use option 3.");
136375
+ continue;
136376
+ }
136377
+ const res = await addByPastedKey2(key);
136378
+ console.log(res.message);
136379
+ if (res.ok && res.account) {
136380
+ await testAndReport(res.account);
136381
+ break;
136382
+ }
136383
+ continue;
136384
+ }
136385
+ if (choice === "3") {
136386
+ console.log("");
136387
+ console.log(providerRows());
136388
+ console.log("");
136389
+ const provider = await ask("Provider id: ");
136390
+ const key = await ask("API key: ");
136391
+ const res = await addApiKeyAccount2(provider, key);
136392
+ console.log(res.message);
136393
+ if (res.ok && res.account) {
136394
+ await testAndReport(res.account);
136395
+ break;
136396
+ }
136397
+ continue;
136398
+ }
136399
+ if (choice === "4") {
136400
+ const endpoint = await ask("Azure resource name or endpoint: ");
136401
+ const key = await ask("API key: ");
136402
+ const apiVersion = await ask("API version (optional): ");
136403
+ const res = /^https?:\/\//i.test(endpoint) ? await addAzureFoundryAccount2(endpoint, key) : await addAzureAccount2(endpoint, key, { apiVersion: apiVersion || undefined });
136404
+ console.log(res.message);
136405
+ if (res.ok && res.account) {
136406
+ await testAndReport(res.account);
136407
+ break;
136408
+ }
136409
+ continue;
136410
+ }
136411
+ if (choice === "5" && which2("claude")) {
136412
+ if (await addSubscription("claude-cli"))
136413
+ break;
136414
+ continue;
136415
+ }
136416
+ if (choice === "6" && which2("codex")) {
136417
+ if (await addSubscription("codex-cli"))
136418
+ break;
136419
+ continue;
136420
+ }
136421
+ console.log("Choose one of the listed options.");
136422
+ }
136423
+ console.log("");
136424
+ console.log("Gearbox is ready.");
136425
+ console.log("Run `gearbox` inside a project.");
136426
+ return true;
136427
+ } finally {
136428
+ rl.close();
136429
+ }
136430
+ }
136249
136431
  if (args[0] === "upgrade" || args[0] === "update") {
136250
136432
  const root2 = resolve11(import.meta.dir, "..");
136251
136433
  if (!existsSync8(resolve11(root2, ".git"))) {
@@ -136270,6 +136452,7 @@ if (args.includes("--help") || args.includes("-h")) {
136270
136452
 
136271
136453
  Usage:
136272
136454
  gearbox start in the current directory (it becomes the workspace)
136455
+ gearbox onboard set up a provider before opening the app
136273
136456
  gearbox --model <name> start with a specific model
136274
136457
  gearbox --continue resume the most recent session in this directory
136275
136458
  gearbox upgrade pull the latest version + reinstall deps
@@ -136284,6 +136467,7 @@ Options:
136284
136467
  -h, --help this help
136285
136468
 
136286
136469
  Set up at least one provider first:
136470
+ gearbox onboard
136287
136471
  gearbox auth add <api-key>
136288
136472
  gearbox auth add <provider> <api-key>
136289
136473
  gearbox auth import
@@ -136296,6 +136480,10 @@ if (args.includes("--version") || args.includes("-v")) {
136296
136480
  console.log(VERSION16);
136297
136481
  process.exit(0);
136298
136482
  }
136483
+ if (args[0] === "onboard" || args[0] === "setup") {
136484
+ await runCliOnboarding();
136485
+ process.exit(0);
136486
+ }
136299
136487
  if (args[0] === "auth") {
136300
136488
  const { listAccounts: listAccounts2, loadAccounts: loadAccounts3, removeAccount: removeAccount2 } = await Promise.resolve().then(() => (init_store(), exports_store));
136301
136489
  const { importableEnvCreds: importableEnvCreds2, importEnvCred: importEnvCred2, importableCloudCreds: importableCloudCreds2, importCloudCred: importCloudCred2 } = await Promise.resolve().then(() => (init_detect(), exports_detect));
@@ -136343,6 +136531,18 @@ Importable from your env (gearbox auth import): ${imp.map((c) => c.envVar).join(
136343
136531
  }
136344
136532
  process.exit(0);
136345
136533
  }
136534
+ if (!anyProviderAvailable()) {
136535
+ if (process.stdin.isTTY && process.stdout.isTTY && process.env.GEARBOX_SKIP_ONBOARD !== "1") {
136536
+ const ready = await runCliOnboarding();
136537
+ if (!ready || !anyProviderAvailable())
136538
+ process.exit(0);
136539
+ } else {
136540
+ console.log("Gearbox needs one provider before the coding app can open.");
136541
+ console.log("Run: gearbox onboard");
136542
+ console.log("Or: gearbox auth add <api-key>");
136543
+ process.exit(1);
136544
+ }
136545
+ }
136346
136546
  var mi = args.indexOf("--model");
136347
136547
  var preferred = mi >= 0 ? args[mi + 1] : undefined;
136348
136548
  var pinned = preferred ?? loadPrefs().pinnedModel;
package/install.ps1 CHANGED
@@ -81,6 +81,12 @@ node "$TargetCli" %*
81
81
  if (-not $AlreadyOnPath) {
82
82
  Write-Host "Open a new terminal if this shell does not pick up the PATH change."
83
83
  }
84
+
85
+ if ($env:GEARBOX_SKIP_ONBOARD -ne "1") {
86
+ Write-Host ""
87
+ Write-Host "Starting setup..."
88
+ & $CmdPath onboard
89
+ }
84
90
  }
85
91
  finally {
86
92
  Remove-Item -Recurse -Force $Temp -ErrorAction SilentlyContinue
package/install.sh CHANGED
@@ -93,3 +93,13 @@ case ":${PATH}:" in
93
93
  echo "Then run: gearbox"
94
94
  ;;
95
95
  esac
96
+
97
+ if [[ "${GEARBOX_SKIP_ONBOARD:-}" != "1" ]]; then
98
+ echo ""
99
+ echo "Starting setup..."
100
+ if [[ -r /dev/tty && -w /dev/tty ]]; then
101
+ "${BIN_DIR}/gearbox" onboard < /dev/tty > /dev/tty
102
+ else
103
+ echo "No interactive terminal detected. Run: ${BIN_DIR}/gearbox onboard"
104
+ fi
105
+ fi
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gearbox-code",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "A beautiful multi-provider coding harness for the terminal. (Intelligent model routing lands on top of this soon.)",
5
5
  "type": "module",
6
6
  "license": "MIT",