@hanamorilabs/tab 0.1.4 → 0.1.5

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
@@ -45,8 +45,8 @@ kill switch stay on flocktab.com. It is one small Rust binary. `tab up` asks
45
45
  for the keys once (typed without echo, saved owner-only to
46
46
  `~/.flocktab/proxy.env`), fetches `flocktab-proxy` for this machine into
47
47
  `~/.flocktab/bin`, and starts it in the background (log: `~/.flocktab/proxy.log`).
48
- `tab down` stops it; `tab update` fetches the newest proxy and restarts;
49
- `tab claude` starts it when it is down. No Docker, no Rust, no checkout: the
48
+ `tab down` stops it; `tab update` installs the newest tab, which brings the
49
+ newest proxy, and restarts it; `tab claude` starts it when it is down. No Docker, no Rust, no checkout: the
50
50
  binary comes with `tab` as the `@hanamorilabs/flocktab-proxy-<platform>`
51
51
  package for your machine. Then
52
52
  `tab login`, pick **2 Self-hosted**: the proxy says which console it settles
@@ -64,7 +64,7 @@ tab alias remove <name>... undo that; `tab alias list` shows them
64
64
  tab status flock, folder Agent, proxy health, provider key state
65
65
  tab version tab and proxy versions
66
66
  tab up | down self-hosted: start or stop the local proxy
67
- tab update self-hosted: newest proxy (npm i -g @hanamorilabs/tab@latest)
67
+ tab update the newest tab and proxy from npm; restarts a running local proxy
68
68
  tab logout forget the session and keys on this machine
69
69
  tab help this list
70
70
  ```
@@ -77,19 +77,19 @@ this folder's Agent. Every read takes `--json`.
77
77
 
78
78
  ```
79
79
  tab list every Agent: state, spent of cap, window, project
80
- tab close crawler tab open crawler the kill switch (402 tab_closed on the next call)
81
- tab cap crawler 25 --window week cap in dollars, and the window
82
- tab rename crawler "Nightly crawler" the slug stays
83
- tab policy crawler --velocity 60 --models gpt-5,claude-sonnet-5 --allow email.send
84
- tab project crawler Foley --create attribute to a project (--repo owner/name; none clears)
80
+ tab close my-project tab open my-project the kill switch (402 tab_closed on the next call)
81
+ tab cap my-project 25 --window week cap in dollars, and the window
82
+ tab rename my-project "My project (nightly)" the slug stays
83
+ tab policy my-project --velocity 60 --models gpt-5,claude-sonnet-5 --allow email.send
84
+ tab project my-project Foley --create attribute to a project (--repo owner/name; none clears)
85
85
  tab projects add Foley projects
86
- tab key rotate crawler [--show] new key, kept on this machine; --show prints it once
87
- tab archive crawler closes for good, leaves the bill (asks first; -y skips)
88
- tab ledger [crawler] --limit 20 --blocked one row per call: settled of held, status, reason
86
+ tab key rotate my-project [--show] new key, kept on this machine; --show prints it once
87
+ tab archive my-project closes for good, leaves the bill (asks first; -y skips)
88
+ tab ledger [my-project] --limit 20 --blocked one row per call: settled of held, status, reason
89
89
  tab spend [agent|project|day] --since 7d meter and outside spend, the console's numbers
90
90
  tab outside connections, per-project outside spend, unattributed
91
91
  tab live --watch 4 who is working now, refreshed every 4 seconds
92
- tab web [crawler] the Agent's console page in the browser
92
+ tab web [my-project] the Agent's console page in the browser
93
93
  ```
94
94
 
95
95
  ## Aliases: plain `codex` on the tab
package/dist/cli.js CHANGED
@@ -11,7 +11,8 @@
11
11
  * tab alias remove codex undo that; `tab alias list` shows them
12
12
  * tab status which flock, which Agent here, is the proxy up
13
13
  * tab version tab and proxy versions
14
- * tab up | down | update self-hosted: start, stop, or fetch the newest proxy
14
+ * tab up | down self-hosted: start or stop the local proxy
15
+ * tab update the newest tab and proxy from npm
15
16
  * tab logout forget the session and keys
16
17
  *
17
18
  * Login is per machine. The Agent is per folder: the first `tab claude` in
@@ -73,7 +74,7 @@ function usage() {
73
74
  cmd("... --json", "every read command as JSON, for scripts and agents"),
74
75
  cmd("up", "self-hosted: start the local proxy (fetches it the first time)"),
75
76
  cmd("down", "self-hosted: stop the local proxy"),
76
- cmd("update", "self-hosted: fetch the newest proxy and restart it"),
77
+ cmd("update", "the newest tab (and proxy) from npm; restarts a running local proxy"),
77
78
  cmd("logout", "forget the session and keys"),
78
79
  ].map(([k, v]) => [cyan(k), v])));
79
80
  say(`
@@ -621,6 +622,48 @@ async function collectProviderKeys() {
621
622
  ok(`Saved to ${dim(file)} ${dim("(owner-only)")}`);
622
623
  return true;
623
624
  }
625
+ /**
626
+ * `tab update`: the newest tab from npm, which carries the newest proxy as
627
+ * its platform package. A self-hosted proxy that was running is restarted
628
+ * on the new binary; a hosted machine just gets the new tab.
629
+ */
630
+ async function update() {
631
+ const config = await loadConfig();
632
+ const wasUp = config?.mode === "self-hosted" && (await proxyHealth(config.proxyUrl)).ok;
633
+ say(dim(`tab ${TAB_VERSION} now; asking npm for the newest.`));
634
+ const code = await new Promise((resolve) => {
635
+ const child = spawn(process.platform === "win32" ? "npm.cmd" : "npm", ["i", "-g", "@hanamorilabs/tab@latest"], {
636
+ stdio: ["ignore", "ignore", "inherit"],
637
+ shell: process.platform === "win32",
638
+ });
639
+ child.on("error", () => resolve(1));
640
+ child.on("close", (c) => resolve(c ?? 1));
641
+ });
642
+ if (code !== 0) {
643
+ fail(`npm could not update tab. Try: ${bold("npm i -g @hanamorilabs/tab@latest")}`);
644
+ return 1;
645
+ }
646
+ // The version now on PATH is the new install's, not this process's.
647
+ const installed = await new Promise((resolve) => {
648
+ const child = spawn(process.platform === "win32" ? "tab.cmd" : "tab", ["version"], { shell: process.platform === "win32" });
649
+ let text = "";
650
+ child.stdout?.on("data", (d) => (text += d.toString()));
651
+ child.stderr?.on("data", (d) => (text += d.toString()));
652
+ child.on("close", () => resolve(text.trim()));
653
+ child.on("error", () => resolve(""));
654
+ });
655
+ ok(installed ? `Updated.
656
+ ${installed}` : "Updated.");
657
+ if (!wasUp) {
658
+ if (!packagedBinPath() && config?.mode === "self-hosted") {
659
+ const fetched = await downloadProxy((t) => say(dim(t)));
660
+ (fetched.ok ? ok : fail)(fetched.ok ? `Fetched flocktab-proxy ${PROXY_VERSION}.` : fetched.message);
661
+ }
662
+ return 0;
663
+ }
664
+ await stopProxy();
665
+ return (await bringUp(config.proxyUrl)) ? 0 : 1;
666
+ }
624
667
  async function selfHosted(action) {
625
668
  const config = await loadConfig();
626
669
  const proxyUrl = config?.mode === "self-hosted" ? config.proxyUrl : LOCAL_PROXY;
@@ -629,30 +672,6 @@ async function selfHosted(action) {
629
672
  (stopped ? ok : warn)(stopped ? "Proxy stopped." : "Proxy was not running.");
630
673
  return 0;
631
674
  }
632
- if (action === "update") {
633
- await stopProxy();
634
- if (packagedBinPath()) {
635
- // The binary is part of the npm install; the newest one comes with the newest tab.
636
- say(`The proxy ships with tab. Updating tab updates it: ${bold("npm i -g @hanamorilabs/tab@latest")}`);
637
- const code = await new Promise((resolve) => {
638
- const child = spawn(process.platform === "win32" ? "npm.cmd" : "npm", ["i", "-g", "@hanamorilabs/tab@latest"], { stdio: "inherit" });
639
- child.on("error", () => resolve(1));
640
- child.on("close", (c) => resolve(c ?? 1));
641
- });
642
- if (code !== 0) {
643
- fail("npm could not update tab.");
644
- return 1;
645
- }
646
- }
647
- else {
648
- const fetched = await downloadProxy((t) => say(dim(t)));
649
- if (!fetched.ok) {
650
- fail(fetched.message);
651
- return 1;
652
- }
653
- ok(`Fetched flocktab-proxy ${PROXY_VERSION}.`);
654
- }
655
- }
656
675
  if (!(await hasProxyEnv())) {
657
676
  const written = await collectProviderKeys();
658
677
  if (!written)
@@ -759,7 +778,7 @@ async function main(argv) {
759
778
  case "down":
760
779
  return selfHosted("down");
761
780
  case "update":
762
- return selfHosted("update");
781
+ return update();
763
782
  default:
764
783
  return runAgent(command, rest);
765
784
  }
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** Written by scripts/write-version.mjs from package.json at build; `tab version` prints it. */
2
- export const TAB_VERSION = "0.1.4";
2
+ export const TAB_VERSION = "0.1.5";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanamorilabs/tab",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Run any AI agent on a FlockTab tab: tab claude, tab codex, tab <command>.",
5
5
  "license": "MIT",
6
6
  "type": "module",