@stage-labs/metro 0.1.0-beta.60 → 0.1.0-beta.61

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/dist/cli.js CHANGED
@@ -10,13 +10,13 @@ import { serve } from './serve.js';
10
10
  import { currentVersion } from './version.js';
11
11
  const USAGE = `metro — run your agent on this machine
12
12
 
13
- metro serve [--port <n>] [--tunnel] [--owner <address>]
13
+ metro serve [--port <n>] [--owner <address>]
14
14
  run the daemon: the agent, its channels and its connectors live in
15
- ~/.metro/agents here, and the page at metro.box manages it through the
16
- link it prints; --owner names the one wallet that may sign in (remembered
17
- after the first start); --tunnel publishes the daemon through Tailscale
18
- Funnel at a permanent https://<machine>.<tailnet>.ts.net (Tailscale
19
- installed and signed in on this machine), so the link works from anywhere
15
+ ~/.metro/agents here, and it is published through Tailscale Funnel at a
16
+ permanent https://<machine>.<tailnet>.ts.net (Tailscale installed and
17
+ signed in on this machine); the page at metro.box manages it through the
18
+ link it prints; --owner names the one wallet that may sign in, needed on
19
+ the first start only
20
20
  metro stop stop the metro daemon on this machine
21
21
  metro tail <agent-id>
22
22
  follow this machine's inbound events, one JSON line each
package/dist/serve.js CHANGED
@@ -10,8 +10,8 @@ const SCRUBBED = new Set(['METRO_RUN_TOKEN', 'METRO_AGENT', 'DATABASE_URL']);
10
10
  const PORT_FLAG = /^--port=(.*)$/;
11
11
  const OWNER_FLAG = /^--owner=(.*)$/;
12
12
  const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
13
- const USAGE = 'usage: metro serve [--port <n>] [--tunnel] [--owner <address>]';
14
- const TUNNEL_FLAG = /^--tunnel=(.*)$/;
13
+ const USAGE = 'usage: metro serve [--port <n>] [--owner <address>]';
14
+ const TUNNEL_FLAG = /^--(no-)?tunnel(=.*)?$/;
15
15
  const TAILSCALE_APP = '/Applications/Tailscale.app/Contents/MacOS/Tailscale';
16
16
  function portOf(raw) {
17
17
  const n = Number(raw);
@@ -19,23 +19,6 @@ function portOf(raw) {
19
19
  throw new Error(`'${raw ?? ''}' is not a port — ${USAGE}`);
20
20
  return n;
21
21
  }
22
- function tunnelOf(raw) {
23
- if (raw === undefined || raw === '' || raw === 'tailscale')
24
- return true;
25
- throw new Error(`'${raw}' is not a tunnel metro knows; the public address is Tailscale Funnel — ${USAGE}`);
26
- }
27
- function tunnelFlag(argv, i) {
28
- const arg = argv[i] ?? '';
29
- const inline = TUNNEL_FLAG.exec(arg);
30
- if (inline)
31
- return { consumed: Number(tunnelOf(inline[1])) - 1 };
32
- if (arg !== '--tunnel')
33
- return null;
34
- const next = argv[i + 1];
35
- const takesValue = next !== undefined && !next.startsWith('-');
36
- tunnelOf(takesValue ? next : undefined);
37
- return { consumed: takesValue ? 1 : 0 };
38
- }
39
22
  function ownerOf(raw) {
40
23
  if (raw === undefined || !ADDRESS.test(raw))
41
24
  throw new Error(`'${raw ?? ''}' is not an Ethereum address — ${USAGE}`);
@@ -43,16 +26,11 @@ function ownerOf(raw) {
43
26
  }
44
27
  export function parseServeArgs(argv) {
45
28
  let port = localPort();
46
- let tunnel = false;
47
29
  let owner = null;
48
30
  for (let i = 0; i < argv.length; i += 1) {
49
31
  const arg = argv[i] ?? '';
50
- const tunnelArg = tunnelFlag(argv, i);
51
- if (tunnelArg) {
52
- tunnel = true;
53
- i += tunnelArg.consumed;
54
- continue;
55
- }
32
+ if (TUNNEL_FLAG.test(arg))
33
+ throw new Error('--tunnel is gone: metro serve always publishes through Tailscale Funnel — ' + USAGE);
56
34
  const inlineOwner = OWNER_FLAG.exec(arg);
57
35
  if (inlineOwner) {
58
36
  owner = ownerOf(inlineOwner[1]);
@@ -75,7 +53,7 @@ export function parseServeArgs(argv) {
75
53
  }
76
54
  throw new Error(`unknown argument '${arg}' — ${USAGE}`);
77
55
  }
78
- return { port, tunnel, owner };
56
+ return { port, owner };
79
57
  }
80
58
  export function requireOwner(owner, dir = agentsDir()) {
81
59
  if (owner !== null || existsSync(join(dir, '.owner')))
@@ -100,7 +78,7 @@ function tailscaleStatus(bin) {
100
78
  export function findTailscale(candidates = ['tailscale', TAILSCALE_APP]) {
101
79
  const bin = candidates.find((c) => spawnSync(c, ['version'], { stdio: 'ignore' }).status === 0);
102
80
  if (bin === undefined)
103
- throw new Error('metro serve --tunnel tailscale needs Tailscale on this machine.\n' +
81
+ throw new Error('metro serve needs Tailscale on this machine: the daemon is published through Tailscale Funnel.\n' +
104
82
  'macOS: brew install --cask tailscale (or the App Store app)\n' +
105
83
  'Linux: curl -fsSL https://tailscale.com/install.sh | sh\n' +
106
84
  'Then sign the machine in: tailscale up');
@@ -128,20 +106,20 @@ export function servePlan(opts) {
128
106
  ? {}
129
107
  : { METRO_RUNTIME_STORE: opts.runtime.dir, METRO_RUNTIME_MANIFEST: opts.runtime.manifest }),
130
108
  METRO_STATE_DIR: process.env.METRO_STATE_DIR ?? serveStateDir(),
131
- ...(opts.tunnel ? { METRO_TUNNEL: 'tailscale' } : {}),
132
- ...(opts.tailscaleBin === undefined ? {} : { METRO_TAILSCALE_BIN: opts.tailscaleBin }),
109
+ METRO_TUNNEL: 'tailscale',
110
+ METRO_TAILSCALE_BIN: opts.tailscaleBin,
133
111
  ...(opts.owner === null ? {} : { METRO_OWNER: opts.owner }),
134
112
  },
135
113
  };
136
114
  }
137
115
  export function serve(argv) {
138
- const { port, tunnel, owner } = parseServeArgs(argv);
116
+ const { port, owner } = parseServeArgs(argv);
139
117
  const running = serveLockedBy();
140
118
  if (running !== null)
141
119
  throw new Error(`a metro serve daemon is already running on this machine (pid ${String(running)}). ` +
142
120
  'Stop it first: metro stop');
143
121
  requireOwner(owner);
144
- const tailscaleBin = tunnel ? findTailscale() : undefined;
122
+ const tailscaleBin = findTailscale();
145
123
  process.stderr.write(`Starting a metro daemon of your own on http://127.0.0.1:${String(port)}\n`);
146
- return spawnPlan(() => servePlan({ runtime: prepareRuntime(), port, tunnel, owner, ...(tailscaleBin === undefined ? {} : { tailscaleBin }) }));
124
+ return spawnPlan(() => servePlan({ runtime: prepareRuntime(), port, owner, tailscaleBin }));
147
125
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stage-labs/metro",
3
- "version": "0.1.0-beta.60",
3
+ "version": "0.1.0-beta.61",
4
4
  "description": "The metro command line. Sign in once per machine, then hand your MCP connector list to Claude Code without the credentials touching disk, argv or shell history.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.1.0-beta.60"
2
+ "version": "0.1.0-beta.61"
3
3
  }