@stage-labs/metro 0.1.0-beta.7 β†’ 0.1.0-beta.71

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 (279) hide show
  1. package/dist/api.js +14 -0
  2. package/dist/bedrock-eventstream.js +120 -0
  3. package/dist/bedrock-proxy.js +260 -0
  4. package/dist/bedrock-upstream.js +72 -0
  5. package/dist/bedrock.js +37 -0
  6. package/dist/claude-settings.js +40 -0
  7. package/dist/claude.js +107 -0
  8. package/dist/cli.js +101 -0
  9. package/dist/control.js +74 -0
  10. package/dist/hold.js +211 -0
  11. package/dist/local.js +93 -0
  12. package/dist/node-name.js +51 -0
  13. package/dist/plugin.js +80 -0
  14. package/dist/provider-flags.js +9 -0
  15. package/dist/runtime-install.js +84 -0
  16. package/dist/runtime.js +70 -0
  17. package/dist/serve.js +147 -0
  18. package/dist/service.js +224 -0
  19. package/dist/tail.js +119 -0
  20. package/dist/update.js +45 -0
  21. package/dist/version.js +97 -0
  22. package/package.json +14 -25
  23. package/runtime/node_modules/@metro-labs/discord-bot/package.json +28 -0
  24. package/runtime/node_modules/@metro-labs/discord-bot/src/accounts.ts +118 -0
  25. package/runtime/node_modules/@metro-labs/discord-bot/src/actions.ts +388 -0
  26. package/runtime/node_modules/@metro-labs/discord-bot/src/api-base.ts +1 -0
  27. package/runtime/node_modules/@metro-labs/discord-bot/src/attachments.ts +29 -0
  28. package/runtime/node_modules/@metro-labs/discord-bot/src/format.ts +220 -0
  29. package/runtime/node_modules/@metro-labs/discord-bot/src/group-actions.ts +50 -0
  30. package/runtime/node_modules/@metro-labs/discord-bot/src/group.ts +115 -0
  31. package/runtime/node_modules/@metro-labs/discord-bot/src/index.ts +127 -0
  32. package/runtime/node_modules/@metro-labs/discord-bot/src/members.ts +215 -0
  33. package/runtime/node_modules/@metro-labs/discord-bot/src/send-files.ts +43 -0
  34. package/runtime/node_modules/@metro-labs/discord-bot/src/station.ts +19 -0
  35. package/runtime/node_modules/@metro-labs/discord-bot/src/verify.ts +82 -0
  36. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-speak.ts +195 -0
  37. package/runtime/node_modules/@metro-labs/discord-bot/src/voice-transcribe.ts +292 -0
  38. package/runtime/node_modules/@metro-labs/discord-bot/src/voice.ts +197 -0
  39. package/runtime/node_modules/@metro-labs/discord-bot/src/wire.ts +5 -0
  40. package/runtime/node_modules/@metro-labs/mcp/package.json +64 -0
  41. package/runtime/node_modules/@metro-labs/mcp/src/channels/addressed.ts +25 -0
  42. package/runtime/node_modules/@metro-labs/mcp/src/channels/dedupe.ts +24 -0
  43. package/runtime/node_modules/@metro-labs/mcp/src/channels/inbound.ts +377 -0
  44. package/runtime/node_modules/@metro-labs/mcp/src/channels/media-note.ts +85 -0
  45. package/runtime/node_modules/@metro-labs/mcp/src/channels/pending.ts +75 -0
  46. package/runtime/node_modules/@metro-labs/mcp/src/channels/relay.ts +129 -0
  47. package/runtime/node_modules/@metro-labs/mcp/src/channels/webhook-note.ts +51 -0
  48. package/runtime/node_modules/@metro-labs/mcp/src/daemon/account-api.ts +311 -0
  49. package/runtime/node_modules/@metro-labs/mcp/src/daemon/agent-api.ts +302 -0
  50. package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-error.ts +8 -0
  51. package/runtime/node_modules/@metro-labs/mcp/src/daemon/api-http.ts +95 -0
  52. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-grant.ts +99 -0
  53. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-owner.ts +32 -0
  54. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-serve.ts +128 -0
  55. package/runtime/node_modules/@metro-labs/mcp/src/daemon/attach-session.ts +280 -0
  56. package/runtime/node_modules/@metro-labs/mcp/src/daemon/boot.ts +204 -0
  57. package/runtime/node_modules/@metro-labs/mcp/src/daemon/bundle-api.ts +111 -0
  58. package/runtime/node_modules/@metro-labs/mcp/src/daemon/claude-api.ts +97 -0
  59. package/runtime/node_modules/@metro-labs/mcp/src/daemon/claude-files.ts +329 -0
  60. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connect-hint.ts +39 -0
  61. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-api.ts +307 -0
  62. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-json.ts +21 -0
  63. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth-routes.ts +157 -0
  64. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-oauth.ts +127 -0
  65. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-tools.ts +98 -0
  66. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-url.ts +70 -0
  67. package/runtime/node_modules/@metro-labs/mcp/src/daemon/connector-verify.ts +330 -0
  68. package/runtime/node_modules/@metro-labs/mcp/src/daemon/control-api.ts +64 -0
  69. package/runtime/node_modules/@metro-labs/mcp/src/daemon/cors.ts +29 -0
  70. package/runtime/node_modules/@metro-labs/mcp/src/daemon/crash-guard.ts +49 -0
  71. package/runtime/node_modules/@metro-labs/mcp/src/daemon/events.ts +120 -0
  72. package/runtime/node_modules/@metro-labs/mcp/src/daemon/http.ts +390 -0
  73. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity-key.ts +33 -0
  74. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity-registry.ts +13 -0
  75. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity-routes.ts +54 -0
  76. package/runtime/node_modules/@metro-labs/mcp/src/daemon/identity.ts +7 -0
  77. package/runtime/node_modules/@metro-labs/mcp/src/daemon/is-record.ts +2 -0
  78. package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-cli-api.ts +63 -0
  79. package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-mode.ts +187 -0
  80. package/runtime/node_modules/@metro-labs/mcp/src/daemon/local-owner.ts +14 -0
  81. package/runtime/node_modules/@metro-labs/mcp/src/daemon/log.ts +42 -0
  82. package/runtime/node_modules/@metro-labs/mcp/src/daemon/machine-api.ts +61 -0
  83. package/runtime/node_modules/@metro-labs/mcp/src/daemon/mode-api.ts +32 -0
  84. package/runtime/node_modules/@metro-labs/mcp/src/daemon/model-api.ts +169 -0
  85. package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-client.ts +159 -0
  86. package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-discovery.ts +117 -0
  87. package/runtime/node_modules/@metro-labs/mcp/src/daemon/oauth-pending.ts +65 -0
  88. package/runtime/node_modules/@metro-labs/mcp/src/daemon/paths.ts +109 -0
  89. package/runtime/node_modules/@metro-labs/mcp/src/daemon/protocol.ts +226 -0
  90. package/runtime/node_modules/@metro-labs/mcp/src/daemon/relay.ts +295 -0
  91. package/runtime/node_modules/@metro-labs/mcp/src/daemon/return-to.ts +21 -0
  92. package/runtime/node_modules/@metro-labs/mcp/src/daemon/runtime-deps.ts +82 -0
  93. package/runtime/node_modules/@metro-labs/mcp/src/daemon/secure-fs.ts +57 -0
  94. package/runtime/node_modules/@metro-labs/mcp/src/daemon/server-types.ts +21 -0
  95. package/runtime/node_modules/@metro-labs/mcp/src/daemon/servers-api.ts +80 -0
  96. package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-api.ts +29 -0
  97. package/runtime/node_modules/@metro-labs/mcp/src/daemon/session-apis.ts +66 -0
  98. package/runtime/node_modules/@metro-labs/mcp/src/daemon/signed-identity.ts +36 -0
  99. package/runtime/node_modules/@metro-labs/mcp/src/daemon/supervisor-io.ts +97 -0
  100. package/runtime/node_modules/@metro-labs/mcp/src/daemon/supervisor.ts +320 -0
  101. package/runtime/node_modules/@metro-labs/mcp/src/daemon/terminal-api.ts +71 -0
  102. package/runtime/node_modules/@metro-labs/mcp/src/daemon/terminal-tickets.ts +40 -0
  103. package/runtime/node_modules/@metro-labs/mcp/src/daemon/terminal-ws.ts +114 -0
  104. package/runtime/node_modules/@metro-labs/mcp/src/daemon/train-call.ts +22 -0
  105. package/runtime/node_modules/@metro-labs/mcp/src/daemon/train-error.ts +53 -0
  106. package/runtime/node_modules/@metro-labs/mcp/src/daemon/tunnel.ts +352 -0
  107. package/runtime/node_modules/@metro-labs/mcp/src/daemon/update-api.ts +116 -0
  108. package/runtime/node_modules/@metro-labs/mcp/src/daemon/upload-api.ts +294 -0
  109. package/runtime/node_modules/@metro-labs/mcp/src/daemon/upload-store.ts +181 -0
  110. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-api.ts +78 -0
  111. package/runtime/node_modules/@metro-labs/mcp/src/daemon/vault-types.ts +12 -0
  112. package/runtime/node_modules/@metro-labs/mcp/src/daemon/version.ts +2 -0
  113. package/runtime/node_modules/@metro-labs/mcp/src/db/account-attach.ts +19 -0
  114. package/runtime/node_modules/@metro-labs/mcp/src/db/address.ts +6 -0
  115. package/runtime/node_modules/@metro-labs/mcp/src/db/agent-admin.ts +43 -0
  116. package/runtime/node_modules/@metro-labs/mcp/src/db/agent-map.ts +84 -0
  117. package/runtime/node_modules/@metro-labs/mcp/src/db/agent-scope.ts +64 -0
  118. package/runtime/node_modules/@metro-labs/mcp/src/db/client.ts +32 -0
  119. package/runtime/node_modules/@metro-labs/mcp/src/db/connector-config.ts +144 -0
  120. package/runtime/node_modules/@metro-labs/mcp/src/db/connector-relay.ts +39 -0
  121. package/runtime/node_modules/@metro-labs/mcp/src/db/connectors.ts +69 -0
  122. package/runtime/node_modules/@metro-labs/mcp/src/db/file-admin.ts +329 -0
  123. package/runtime/node_modules/@metro-labs/mcp/src/db/file-source.ts +155 -0
  124. package/runtime/node_modules/@metro-labs/mcp/src/db/ids.ts +21 -0
  125. package/runtime/node_modules/@metro-labs/mcp/src/db/key-map.ts +45 -0
  126. package/runtime/node_modules/@metro-labs/mcp/src/db/local-connectors.ts +277 -0
  127. package/runtime/node_modules/@metro-labs/mcp/src/db/materialize.ts +253 -0
  128. package/runtime/node_modules/@metro-labs/mcp/src/db/schema.ts +33 -0
  129. package/runtime/node_modules/@metro-labs/mcp/src/db/servers.ts +83 -0
  130. package/runtime/node_modules/@metro-labs/mcp/src/db/stations.ts +12 -0
  131. package/runtime/node_modules/@metro-labs/mcp/src/db/vault.ts +109 -0
  132. package/runtime/node_modules/@metro-labs/mcp/src/gateway/bedrock.ts +252 -0
  133. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-auth.ts +231 -0
  134. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-device.ts +91 -0
  135. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-stream.ts +288 -0
  136. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex-translate.ts +203 -0
  137. package/runtime/node_modules/@metro-labs/mcp/src/gateway/codex.ts +211 -0
  138. package/runtime/node_modules/@metro-labs/mcp/src/gateway/eventstream.ts +123 -0
  139. package/runtime/node_modules/@metro-labs/mcp/src/gateway/forward.ts +169 -0
  140. package/runtime/node_modules/@metro-labs/mcp/src/gateway/gateway.ts +193 -0
  141. package/runtime/node_modules/@metro-labs/mcp/src/gateway/model-config.ts +180 -0
  142. package/runtime/node_modules/@metro-labs/mcp/src/mcp/accounts.ts +141 -0
  143. package/runtime/node_modules/@metro-labs/mcp/src/mcp/call-tools.ts +216 -0
  144. package/runtime/node_modules/@metro-labs/mcp/src/mcp/channel-owner.ts +29 -0
  145. package/runtime/node_modules/@metro-labs/mcp/src/mcp/ctx.ts +62 -0
  146. package/runtime/node_modules/@metro-labs/mcp/src/mcp/event-store.ts +91 -0
  147. package/runtime/node_modules/@metro-labs/mcp/src/mcp/frame-scope.ts +21 -0
  148. package/runtime/node_modules/@metro-labs/mcp/src/mcp/group-tools.ts +129 -0
  149. package/runtime/node_modules/@metro-labs/mcp/src/mcp/index.ts +191 -0
  150. package/runtime/node_modules/@metro-labs/mcp/src/mcp/member-tools.ts +72 -0
  151. package/runtime/node_modules/@metro-labs/mcp/src/mcp/permission-relay.ts +66 -0
  152. package/runtime/node_modules/@metro-labs/mcp/src/mcp/raw-get-stream.ts +207 -0
  153. package/runtime/node_modules/@metro-labs/mcp/src/mcp/request-identity.ts +47 -0
  154. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-registry.ts +172 -0
  155. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session-route.ts +43 -0
  156. package/runtime/node_modules/@metro-labs/mcp/src/mcp/session.ts +215 -0
  157. package/runtime/node_modules/@metro-labs/mcp/src/mcp/str.ts +5 -0
  158. package/runtime/node_modules/@metro-labs/mcp/src/mcp/tool-dispatch.ts +215 -0
  159. package/runtime/node_modules/@metro-labs/mcp/src/mcp/tool-schemas.ts +400 -0
  160. package/runtime/node_modules/@metro-labs/mcp/src/mcp/upload-tool.ts +66 -0
  161. package/runtime/node_modules/@metro-labs/mcp/src/monitor/api.ts +237 -0
  162. package/runtime/node_modules/@metro-labs/mcp/src/server.ts +2 -0
  163. package/runtime/node_modules/@metro-labs/mcp/src/stations/account-store.ts +60 -0
  164. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-inline.ts +100 -0
  165. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-interactive.ts +161 -0
  166. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-resolve.ts +200 -0
  167. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach-xmtp.ts +111 -0
  168. package/runtime/node_modules/@metro-labs/mcp/src/stations/attach.ts +184 -0
  169. package/runtime/node_modules/@metro-labs/mcp/src/stations/attachments.ts +196 -0
  170. package/runtime/node_modules/@metro-labs/mcp/src/stations/lines.ts +82 -0
  171. package/runtime/node_modules/@metro-labs/mcp/src/stations/messaging-normalize.ts +88 -0
  172. package/runtime/node_modules/@metro-labs/mcp/src/stations/registry.ts +35 -0
  173. package/runtime/node_modules/@metro-labs/mcp/src/stations/station-runtime.ts +64 -0
  174. package/runtime/node_modules/@metro-labs/mcp/src/stations/types.ts +107 -0
  175. package/runtime/node_modules/@metro-labs/telegram/package.json +26 -0
  176. package/runtime/node_modules/@metro-labs/telegram/src/accounts.ts +80 -0
  177. package/runtime/node_modules/@metro-labs/telegram/src/actions.ts +254 -0
  178. package/runtime/node_modules/@metro-labs/telegram/src/attachments.ts +87 -0
  179. package/runtime/node_modules/@metro-labs/telegram/src/client.ts +77 -0
  180. package/runtime/node_modules/@metro-labs/telegram/src/format.ts +156 -0
  181. package/runtime/node_modules/@metro-labs/telegram/src/group.ts +261 -0
  182. package/runtime/node_modules/@metro-labs/telegram/src/history.ts +52 -0
  183. package/runtime/node_modules/@metro-labs/telegram/src/inbound.ts +78 -0
  184. package/runtime/node_modules/@metro-labs/telegram/src/index.ts +46 -0
  185. package/runtime/node_modules/@metro-labs/telegram/src/login.ts +166 -0
  186. package/runtime/node_modules/@metro-labs/telegram/src/media-actions.ts +80 -0
  187. package/runtime/node_modules/@metro-labs/telegram/src/members.ts +75 -0
  188. package/runtime/node_modules/@metro-labs/telegram/src/normalize.ts +22 -0
  189. package/runtime/node_modules/@metro-labs/telegram/src/reactions.ts +167 -0
  190. package/runtime/node_modules/@metro-labs/telegram/src/station.ts +24 -0
  191. package/runtime/node_modules/@metro-labs/telegram/src/types.ts +7 -0
  192. package/runtime/node_modules/@metro-labs/telegram/src/wire.ts +1 -0
  193. package/runtime/node_modules/@metro-labs/telegram-bot/package.json +25 -0
  194. package/runtime/node_modules/@metro-labs/telegram-bot/src/accounts.ts +120 -0
  195. package/runtime/node_modules/@metro-labs/telegram-bot/src/actions.ts +295 -0
  196. package/runtime/node_modules/@metro-labs/telegram-bot/src/attachments.ts +128 -0
  197. package/runtime/node_modules/@metro-labs/telegram-bot/src/format.ts +201 -0
  198. package/runtime/node_modules/@metro-labs/telegram-bot/src/index.ts +109 -0
  199. package/runtime/node_modules/@metro-labs/telegram-bot/src/media-actions.ts +166 -0
  200. package/runtime/node_modules/@metro-labs/telegram-bot/src/members.ts +47 -0
  201. package/runtime/node_modules/@metro-labs/telegram-bot/src/station.ts +17 -0
  202. package/runtime/node_modules/@metro-labs/telegram-bot/src/types.ts +58 -0
  203. package/runtime/node_modules/@metro-labs/telegram-bot/src/verify.ts +38 -0
  204. package/runtime/node_modules/@metro-labs/telegram-bot/src/wire.ts +3 -0
  205. package/runtime/node_modules/@metro-labs/webhook/package.json +23 -0
  206. package/runtime/node_modules/@metro-labs/webhook/src/station.ts +37 -0
  207. package/runtime/node_modules/@metro-labs/whatsapp/package.json +27 -0
  208. package/runtime/node_modules/@metro-labs/whatsapp/src/accounts.ts +66 -0
  209. package/runtime/node_modules/@metro-labs/whatsapp/src/ack.ts +101 -0
  210. package/runtime/node_modules/@metro-labs/whatsapp/src/actions.ts +178 -0
  211. package/runtime/node_modules/@metro-labs/whatsapp/src/attachments.ts +72 -0
  212. package/runtime/node_modules/@metro-labs/whatsapp/src/auth-state.ts +129 -0
  213. package/runtime/node_modules/@metro-labs/whatsapp/src/client.ts +327 -0
  214. package/runtime/node_modules/@metro-labs/whatsapp/src/delivery.ts +49 -0
  215. package/runtime/node_modules/@metro-labs/whatsapp/src/format.ts +138 -0
  216. package/runtime/node_modules/@metro-labs/whatsapp/src/inbound.ts +57 -0
  217. package/runtime/node_modules/@metro-labs/whatsapp/src/index.ts +40 -0
  218. package/runtime/node_modules/@metro-labs/whatsapp/src/keys.ts +59 -0
  219. package/runtime/node_modules/@metro-labs/whatsapp/src/logger.ts +60 -0
  220. package/runtime/node_modules/@metro-labs/whatsapp/src/login.ts +176 -0
  221. package/runtime/node_modules/@metro-labs/whatsapp/src/media.ts +84 -0
  222. package/runtime/node_modules/@metro-labs/whatsapp/src/normalize.ts +22 -0
  223. package/runtime/node_modules/@metro-labs/whatsapp/src/outbox.ts +38 -0
  224. package/runtime/node_modules/@metro-labs/whatsapp/src/parse.ts +185 -0
  225. package/runtime/node_modules/@metro-labs/whatsapp/src/station.ts +17 -0
  226. package/runtime/node_modules/@metro-labs/whatsapp/src/token-store.ts +98 -0
  227. package/runtime/node_modules/@metro-labs/whatsapp/src/types.ts +6 -0
  228. package/runtime/node_modules/@metro-labs/whatsapp/src/wire.ts +5 -0
  229. package/runtime/node_modules/@metro-labs/xmtp/package.json +33 -0
  230. package/runtime/node_modules/@metro-labs/xmtp/src/accounts.ts +112 -0
  231. package/runtime/node_modules/@metro-labs/xmtp/src/actions-close.ts +110 -0
  232. package/runtime/node_modules/@metro-labs/xmtp/src/actions-conv.ts +299 -0
  233. package/runtime/node_modules/@metro-labs/xmtp/src/actions-meta.ts +157 -0
  234. package/runtime/node_modules/@metro-labs/xmtp/src/actions-push.ts +87 -0
  235. package/runtime/node_modules/@metro-labs/xmtp/src/actions.ts +375 -0
  236. package/runtime/node_modules/@metro-labs/xmtp/src/attachments.ts +107 -0
  237. package/runtime/node_modules/@metro-labs/xmtp/src/codecs.ts +171 -0
  238. package/runtime/node_modules/@metro-labs/xmtp/src/conv-helpers.ts +239 -0
  239. package/runtime/node_modules/@metro-labs/xmtp/src/emit-core.ts +55 -0
  240. package/runtime/node_modules/@metro-labs/xmtp/src/emit-payloads.ts +335 -0
  241. package/runtime/node_modules/@metro-labs/xmtp/src/emit.ts +80 -0
  242. package/runtime/node_modules/@metro-labs/xmtp/src/group-members.ts +34 -0
  243. package/runtime/node_modules/@metro-labs/xmtp/src/group.ts +56 -0
  244. package/runtime/node_modules/@metro-labs/xmtp/src/identity.ts +33 -0
  245. package/runtime/node_modules/@metro-labs/xmtp/src/index.ts +125 -0
  246. package/runtime/node_modules/@metro-labs/xmtp/src/labels.ts +157 -0
  247. package/runtime/node_modules/@metro-labs/xmtp/src/member-args.ts +40 -0
  248. package/runtime/node_modules/@metro-labs/xmtp/src/push.ts +349 -0
  249. package/runtime/node_modules/@metro-labs/xmtp/src/station.ts +13 -0
  250. package/runtime/node_modules/@metro-labs/xmtp/src/tools-handlers.ts +126 -0
  251. package/runtime/node_modules/@metro-labs/xmtp/src/tools.ts +212 -0
  252. package/runtime/node_modules/@metro-labs/xmtp/src/transcribe.ts +90 -0
  253. package/runtime/node_modules/@metro-labs/xmtp/src/verify.ts +84 -0
  254. package/runtime/node_modules/@metro-labs/xmtp/src/wire.ts +53 -0
  255. package/runtime/runtime.json +3 -0
  256. package/runtime/stations.json +36 -0
  257. package/runtime/trains/.keep +0 -0
  258. package/LICENSE +0 -21
  259. package/README.md +0 -193
  260. package/dist/cache.js +0 -75
  261. package/dist/cli/actions.js +0 -139
  262. package/dist/cli/config.js +0 -185
  263. package/dist/cli/index.js +0 -159
  264. package/dist/cli/skill.js +0 -62
  265. package/dist/cli/util.js +0 -72
  266. package/dist/codex-rc.js +0 -236
  267. package/dist/dispatcher.js +0 -95
  268. package/dist/history.js +0 -84
  269. package/dist/ipc.js +0 -72
  270. package/dist/log.js +0 -15
  271. package/dist/paths.js +0 -68
  272. package/dist/stations/discord.js +0 -200
  273. package/dist/stations/index.js +0 -73
  274. package/dist/stations/telegram-md.js +0 -34
  275. package/dist/stations/telegram-upload.js +0 -113
  276. package/dist/stations/telegram.js +0 -213
  277. package/docs/agents.md +0 -185
  278. package/docs/uri-scheme.md +0 -71
  279. package/skills/metro/SKILL.md +0 -241
package/docs/agents.md DELETED
@@ -1,185 +0,0 @@
1
- # Metro: a guide for coding agents
2
-
3
- You are running inside a session that has **launched `metro`** in the background. Metro emits a live stream of JSON events from Discord, Telegram, and other agents on its stdout. Your job is to consume that stream and post replies back via subcommands.
4
-
5
- ## Starting the bridge
6
-
7
- The launch mechanics differ by runtime β€” pick the one that matches yours.
8
-
9
- ### Claude Code
10
-
11
- ```
12
- Bash(command: "metro", run_in_background: true)
13
- ```
14
-
15
- Then attach `Monitor` to its stdout. Each line is one JSON event you act on.
16
-
17
- ### Codex
18
-
19
- ```
20
- shell(command: "METRO_CODEX_RC=ws://127.0.0.1:8421 metro", run_in_background: true)
21
- ```
22
-
23
- Don't watch its stdout β€” Codex has no Monitor equivalent. Metro pushes each event into your thread via JSON-RPC `turn/start`, so events arrive as user input on your next turn. The user must have a daemon and TUI running for this to work:
24
-
25
- ```
26
- codex app-server --listen ws://127.0.0.1:8421 # daemon (terminal 1)
27
- codex --remote ws://127.0.0.1:8421 # TUI (this session β€” terminal 2)
28
- ```
29
-
30
- Run `metro doctor` if anything seems off.
31
-
32
- ## Event shape
33
-
34
- Every event is a **history entry** β€” the same record that's appended to `history.jsonl`. Fields: `kind` (`inbound`/`notification`/`outbound`/`edit`/`react`), `id` (`msg_…`), `ts`, `station`, `line` (conversation), `lineName?`, `from` (participant URI), `fromName?`, `to`, `text`, `messageId?` (platform-side id; inbound/outbound only), `payload?` (raw platform message; inbound only).
35
-
36
- ```json
37
- {"kind":"inbound","id":"msg_aB3xY7zP","ts":"2026-05-14T12:00:00Z","station":"telegram","line":"metro://telegram/-100…/247","lineName":"infra","from":"metro://telegram/user/12345","fromName":"@alice","to":"metro://claude/agent","messageId":"4567","text":"hello [image]","payload":{"message_id":4567,"chat":{"id":-100,"type":"supergroup","is_forum":true},"from":{"id":12345,"username":"alice"},"text":"hello","entities":[{"type":"mention","offset":0,"length":6}],"photo":[{"file_id":"…"}],"reply_to_message":{"message_id":4500,"text":"earlier","from":{"id":99,"username":"bob"}}}}
38
- ```
39
-
40
- ```json
41
- {"kind":"notification","id":"msg_pQ4r5sT0","ts":"…","station":"claude","line":"metro://claude/deploys","from":"metro://codex/ci","to":"metro://claude/deploys","text":"deploy succeeded"}
42
- ```
43
-
44
- ### `payload` by station
45
-
46
- `payload` is the platform's native message shape. Narrow on `event.station`:
47
-
48
- - **`discord`** β€” discord.js `Message.toJSON()`: camelCase fields (`channelId`, `guildId`, `content`, `author`, `mentions: { users[], roles[], everyone }`, `attachments[]`, `reference`, …). Collections come back as **arrays of IDs**. `referencedMessage` (also `toJSON()`-shaped) is added inline on replies (auto-fetched).
49
- - **`telegram`** β€” raw Bot API `Message` (snake_case): `{ message_id, chat, from, text, caption, entities[], photo[], document, voice, audio, reply_to_message, … }`. `reply_to_message` is inline on replies.
50
-
51
- Use `payload` for anything the envelope doesn't surface β€” mentions, reply chains, embeds, stickers, entities.
52
-
53
- Both `from` and `to` are **participant URIs** (the conversation lives in `line`): `metro://<station>/user/<id>` for a person, `metro://claude/<topic>` / `metro://codex/<topic>` for an agent, `metro://<station>/<channelId>` as a fallback `to` when sending to a group with no single recipient.
54
-
55
- When **you** call `metro send`/`reply`/`edit`/`react`, metro auto-stamps `from` to your runtime β€” `metro://claude/agent` (from `$CLAUDECODE`) or `metro://codex/agent` (from `$METRO_CODEX_RC`/`$CODEX_HOME`). Override with `--from=<uri>` or `$METRO_FROM`. When replying/reacting, `to` is auto-set to the original sender (history lookup).
56
-
57
- - `kind: "inbound"` β€” a human (or another bot) posted on a chat platform.
58
- - `kind: "notification"` β€” another agent called `metro send` against your agent line. This is how Codex pings Claude Code and vice versa.
59
-
60
- `text` may include `[image]` / `[voice]` / `[audio]` / `[file: <name>]` placeholders alongside the real text β€” non-image attachments are opaque markers, images can be materialized via `metro download`.
61
-
62
- ## Required flow on every event
63
-
64
- 1. **Echo the event** to your visible output: `[<line>#<messageId>] <text>`. Both Monitor and Codex collapse tool output, so this echo is the only thing the user sees without expanding cards.
65
- 2. **Decide and act** using the subcommands below.
66
-
67
- ## Detecting "is this for me?"
68
-
69
- Derive from `payload`. Bot id per station is in `$METRO_STATE_DIR/bot-ids.json` (`{discord:"<userId>", telegram:"<userId>"}`).
70
-
71
- - **`discord`** β€” DM if `payload.guildId == null`; otherwise pinged if `payload.mentions.users.includes(<bot-id>)`.
72
- - **`telegram`** β€” DM if `payload.chat.type === 'private'`; otherwise pinged if any entity in `payload.entities` (or `caption_entities`) is `{type:"mention"}` matching `@<bot-username>`, or `{type:"text_mention", user:{id:<bot-id>}}`.
73
-
74
- Default: only reply on DM or ping; otherwise stay silent or `metro react` to ack.
75
-
76
- ## Subcommands
77
-
78
- | Action | Command |
79
- |---|---|
80
- | Quote-reply (threads under original) | `metro reply <line> <messageId> <text>` |
81
- | Send a fresh message (no reply context) | `metro send <line> <text>` |
82
- | Edit a message you previously sent | `metro edit <line> <messageId> <text>` |
83
- | Reaction (empty emoji clears it) | `metro react <line> <messageId> <emoji>` |
84
- | Download `[image]` attachments | `metro download <line> <messageId> [--out=<dir>]` |
85
- | Recent-message lookback (Discord only) | `metro fetch <line> [--limit=20]` |
86
- | Cross-agent ping | `metro send <agent-line> <text> [--from=<line>]` |
87
-
88
- `reply` / `send` / `edit` accept multi-line text via stdin (heredoc).
89
-
90
- ### Rich content flags
91
-
92
- `send` and `reply` accept these flags; `edit` accepts `--buttons` only.
93
-
94
- - `--image=<path>` β€” local image. **Repeatable** for albums: `--image=a.png --image=b.png` (or comma-separated). Up to 10 / message. Text becomes the caption (on the first image for albums).
95
- - `--document=<path>` β€” local file (PDF, log, csv, …). Same repeat/comma syntax.
96
- - `--voice=<path>` β€” single voice message (`.ogg` Opus or `.mp3`). On Telegram renders as a voice bubble; on Discord uploaded as audio attachment.
97
- - `--buttons='[[{"text":"…","url":"…"}]]'` β€” inline URL-button keyboard (2D rows Γ— buttons). Pass `'[]'` to `edit` to clear.
98
-
99
- ```bash
100
- metro send <line> "screenshot" --image=/tmp/build.png
101
- metro send <line> "before/after" --image=/tmp/before.png --image=/tmp/after.png
102
- metro reply <line> <id> "voice note" --voice=/tmp/note.ogg
103
- metro send <line> "approve?" --buttons='[[{"text":"Open PR","url":"https://github.com/x/y/pull/1"}]]'
104
- ```
105
-
106
- Limits: 20 MB / file. Telegram albums are single-type (photos OR documents per album); mixing kinds still works β€” metro splits into two messages. Buttons are dropped on multi-attachment Telegram sends. URL buttons only for now.
107
-
108
- Append `--json` to any command for a single JSON line you can parse.
109
-
110
- ## When to use `reply` vs `send`
111
-
112
- - **`reply`** β€” responding to a specific inbound message. Threads under it. Default when handling an `inbound` event.
113
- - **`send`** β€” initiating without a triggering message: a long task you kicked off finished, a follow-up the user asked you to deliver later, or posting to an agent line (`metro://claude/...`, `metro://codex/...`) to notify a peer.
114
-
115
- ## Universal message IDs
116
-
117
- The `id` field on every event and `metro history` row is metro's **universal ID** (`msg_<8 chars>`). It works anywhere a `<message_id>` is expected β€” `metro reply`, `edit`, `react`, `download` β€” and resolves to the platform's own id via the history file. Use it for chaining commands or referring back across stations.
118
-
119
- ## `metro history` β€” read the universal message log
120
-
121
- Every inbound, outbound, edit, react, and notification is appended to `$METRO_STATE_DIR/history.jsonl` automatically.
122
-
123
- ```bash
124
- metro history --limit=20 # recent 20, newest first
125
- metro history --line=metro://discord/123 # only this conversation
126
- metro history --kind=inbound --since=2026-05-14 # inbounds since that day
127
- metro history --station=telegram --text=deploy # all Telegram entries containing "deploy"
128
- metro history --from='@alice' --json # everything from alice, JSON
129
- ```
130
-
131
- Filters: `--limit` (default 50), `--line`, `--station`, `--kind` (`inbound`/`outbound`/`edit`/`react`/`notification`), `--from`, `--text`, `--since` (ISO), `--json`.
132
-
133
- ## Discovery
134
-
135
- ### `metro lines`
136
-
137
- ```
138
- $ metro lines
139
- 2m ago metro://discord/1234567890 infra
140
- 5m ago metro://telegram/-100123/42 design-review
141
- ```
142
-
143
- Lines sorted by recency. Use when the user says "the Telegram channel" or "that PR thread."
144
-
145
- ### `metro stations`
146
-
147
- ```
148
- $ metro stations
149
- βœ“ discord chat in: text+image Β· out: text Β· features: reply, send, edit, react, download, fetch
150
- βœ“ telegram chat in: text+image Β· out: text Β· features: reply, send, edit, react, download, fetch
151
- Β· claude agent in: text Β· out: – Β· features: notify
152
- βœ“ codex agent in: text Β· out: – Β· features: notify
153
- ```
154
-
155
- `βœ“` = ready, `βœ—` = configured-but-broken, `Β·` = informational (agent stations have no setup).
156
-
157
- ## Image attachments
158
-
159
- When an inbound has an `[image]` tag in `text`:
160
-
161
- 1. `metro download <line> <messageId>` β†’ prints absolute paths.
162
- 2. `Read` each path with your `Read` tool β€” the image enters your context as a vision input.
163
- 3. Reply normally via `metro reply`.
164
-
165
- ## Cross-agent notification
166
-
167
- Both agents can post to each other's "agent line" β€” a logical channel under `metro://claude/<topic>` or `metro://codex/<topic>`. The daemon re-emits the post on its stdout stream (and pushes via codex-rc if configured), so the peer agent sees it as a notification:
168
-
169
- ```bash
170
- metro send metro://claude/deploys "build green, ready to ship"
171
- metro send metro://claude/deploys "build green" --from=metro://codex/ci # override sender
172
- ```
173
-
174
- This requires the metro daemon to be running on the machine. Without a daemon, agent-line sends error with a clear message.
175
-
176
- ## Don'ts
177
-
178
- - ❌ Spawning a second metro daemon β€” there's one per machine (lockfile-enforced).
179
- - ❌ `metro send` to a line that isn't in `metro lines` unless the user gave it to you explicitly.
180
- - ❌ Narrating the tool ("I'll now use metro reply to…"). The tool call is already visible.
181
-
182
- ## Further reading
183
-
184
- - URI scheme: [`uri-scheme.md`](uri-scheme.md)
185
- - Source: https://github.com/bonustrack/metro
@@ -1,71 +0,0 @@
1
- # Metro URI scheme
2
-
3
- Universal identifier for every conversational scope and notification sink in metro. Lines pass around as opaque strings; only the owning station parses its own paths.
4
-
5
- ## Grammar
6
-
7
- ```
8
- line = "metro://" station "/" path
9
- station = lowercase identifier (claude | codex | discord | telegram | …)
10
- path = station-specific, "/"-separated segments
11
- ```
12
-
13
- The URI parses cleanly with the WHATWG `URL` parser: `new URL(line)` gives `protocol="metro:"`, `host=<station>`, `pathname="/<path>"`.
14
-
15
- ## Registered stations
16
-
17
- | Station | Kind | Pattern | Example |
18
- |------------|-------|-------------------------------------------|---------------------------------------|
19
- | `discord` | chat | `metro://discord/<channel-id>` | `metro://discord/1234567890123456789` |
20
- | `telegram` | chat | `metro://telegram/<chat-id>[/<topic-id>]` | `metro://telegram/-1001234567890/42` |
21
- | `claude` | agent | `metro://claude/<topic>` | `metro://claude/deploys` |
22
- | `codex` | agent | `metro://codex/<topic>` | `metro://codex/ci` |
23
-
24
- ## Participants
25
-
26
- Every chat station also exposes participant URIs β€” used as `from` on inbound/outbound events and history rows.
27
-
28
- | Kind | Pattern | Example |
29
- |-------|------------------------------------------|----------------------------------|
30
- | user | `metro://<station>/user/<id>` | `metro://discord/user/87654321` |
31
- | agent | `metro://{claude,codex}/<topic>` | `metro://claude/agent` |
32
-
33
- `from` and `to` on history entries are always participant URIs. Discord/Telegram inbounds set `from` to the user URI; the daemon sets `to` to the agent identity (`metro://claude/agent` if `$CLAUDECODE` is detected, `metro://codex/agent` if `$METRO_CODEX_RC`/`$CODEX_HOME` is set, else `metro://agent`). On outbound, `from` = the same agent identity; `to` = the original sender for replies/reacts (looked up from history), or the channel `line` for fresh group sends. A `fromName` field carries the display name (`@alice`, `bonustrack_`).
34
-
35
- Override with `--from=<uri>` on any write command, or set `$METRO_FROM` to pin a custom identity for the whole session.
36
-
37
- Chat lines identify a Discord channel / Telegram chat (with optional forum topic). Agent lines are notification sinks β€” posting to one re-emits the message on the daemon's stdout stream and (if configured) pushes it to the Codex app-server. They have no inherent "messages"; only events.
38
-
39
- ## Message addressing
40
-
41
- Messages on chat lines are referenced by **line + message id** (two args), not as part of the URI. So:
42
-
43
- ```bash
44
- metro reply metro://discord/123… 4567 "ack"
45
- metro edit metro://discord/123… 9876 "fixed typo"
46
- metro react metro://telegram/-100…/42 4567 πŸ‘
47
- ```
48
-
49
- ## Properties
50
-
51
- - **Stable**: a Line is valid for the lifetime of the scope.
52
- - **Self-describing**: the station name is encoded; the dispatcher routes by station prefix.
53
- - **Persistable**: safe as a JSON key on disk (used by `lines.json`).
54
- - **Branded**: TypeScript type `Line` prevents mixing with arbitrary strings.
55
-
56
- ## API
57
-
58
- ```ts
59
- import { Line } from './stations/index.js'; // value namespace + type
60
-
61
- const l: Line = Line.discord('1234567890'); // typed Line
62
- Line.parse(l); // { station: 'discord', path: ['1234567890'] } | null
63
- Line.station(l); // 'discord'
64
- Line.isAgent(Line.claude('deploys')); // true
65
- ```
66
-
67
- ## Adding a new station
68
-
69
- 1. Pick a lowercase station name (`slack`, `matrix`, …).
70
- 2. Add a `Line.<station>(...)` formatter and a parser that returns your typed payload.
71
- 3. Document the path grammar in the table above.
@@ -1,241 +0,0 @@
1
- ---
2
- name: metro
3
- description: Run the metro Telegram/Discord bridge in this session β€” launch `metro` in the background, watch its stdout for inbound JSON events, and act on each. Use when the user asks to start/run/launch metro, when you see JSON lines on stdout shaped `{"kind":"inbound","station":...,"line":"metro://...","messageId":...,"text":...}`, or when handling a chat reply/edit/react/send/download/fetch/notify.
4
- ---
5
-
6
- # Metro β€” running the Telegram & Discord bridge
7
-
8
- Metro is a CLI bridge between this agent session and Telegram/Discord. You launch `metro` once when the user asks, then act on each inbound JSON line via `metro <subcommand>`.
9
-
10
- ## Starting the bridge
11
-
12
- When the user asks to run/start/launch metro:
13
-
14
- ### Claude Code
15
-
16
- ```
17
- Bash(command: "metro", run_in_background: true)
18
- ```
19
-
20
- Then attach `Monitor` to its stdout. Each line is one JSON event. Stderr is pino logs β€” don't act on it.
21
-
22
- ### Codex
23
-
24
- ```
25
- shell(command: "METRO_CODEX_RC=ws://127.0.0.1:8421 metro", run_in_background: true)
26
- ```
27
-
28
- Codex has no Monitor equivalent. Instead, metro pushes each event into your thread via JSON-RPC `turn/start`, so events arrive as user input on your next turn. The user must have a daemon + TUI running on the **same WebSocket URL**:
29
-
30
- ```
31
- codex app-server --listen ws://127.0.0.1:8421 # daemon (terminal 1)
32
- codex --remote ws://127.0.0.1:8421 # TUI (terminal 2) β€” type "hi" once to create a live thread
33
- ```
34
-
35
- Then metro starts third. If metro exits immediately or you see `thread not found` retries on its stderr, the TUI didn't create a thread yet β€” tell the user to type something in the TUI.
36
-
37
- ### Diagnostics
38
-
39
- If something seems off, run `metro doctor`. Common causes: missing tokens (`metro setup telegram <token>` / `metro setup discord <token>`), Discord Message Content Intent not toggled, stale lockfile, or (Codex) no live thread on the daemon.
40
-
41
- ## Event shape
42
-
43
- Every line on stdout is one **history entry** β€” the same record appended to `history.jsonl`. Fields:
44
- - `kind` β€” `"inbound"`, `"notification"`, `"outbound"`, `"edit"`, or `"react"`
45
- - `id` (`msg_…`) β€” universal message ID minted by metro
46
- - `ts` β€” ISO timestamp
47
- - `station` β€” `"discord"`, `"telegram"`, `"claude"`, `"codex"`
48
- - `line` β€” conversation URI; `lineName?` is the channel/topic display name
49
- - `from` / `fromName?` β€” sender participant URI + optional display name
50
- - `to` β€” recipient participant URI (agent for inbound, line for notification, original sender for replies/reacts)
51
- - `text` β€” universal display projection. Includes `[image]`/`[file: …]`/`[voice]`/`[audio]` tags inline.
52
- - `messageId?` β€” platform-side id (Discord snowflake, Telegram int). Set on inbound/outbound.
53
- - `payload?` β€” raw platform-native message object. Set on inbound only. Shape varies per `station`.
54
-
55
- ```json
56
- {"kind":"inbound","id":"msg_aB3xY7zP","ts":"2026-05-14T12:00:00Z","station":"telegram","line":"metro://telegram/-100…/247","lineName":"infra","from":"metro://telegram/user/12345","fromName":"@alice","to":"metro://claude/agent","messageId":"4567","text":"hi [image]","payload":{"message_id":4567,"chat":{"id":-100,"type":"supergroup","is_forum":true},"from":{"id":12345,"username":"alice"},"text":"hi","photo":[{"file_id":"…"}],"reply_to_message":{"message_id":4500,"text":"earlier","from":{"id":99,"username":"bob"}}}}
57
- ```
58
-
59
- ```json
60
- {"kind":"notification","id":"msg_pQ4r5sT0","ts":"…","station":"claude","line":"metro://claude/deploys","from":"metro://codex/ci","to":"metro://claude/deploys","text":"deploy green"}
61
- ```
62
-
63
- ### `payload` by station
64
-
65
- `payload` is the platform's native message shape. Narrow on `event.station`:
66
-
67
- - **`discord`** β€” discord.js `Message.toJSON()`: camelCase fields (`channelId`, `guildId`, `content`, `author`, `mentions: { users[], roles[], everyone }`, `attachments[]`, `reference`, …). Collections come back as **arrays of IDs**. `referencedMessage` is added inline on replies (auto-fetched).
68
- - **`telegram`** β€” raw Bot API `Message` (snake_case): `{ message_id, chat, from, text, caption, entities[], photo[], document, voice, audio, reply_to_message, … }`. `reply_to_message` is inline on replies.
69
-
70
- Use `payload` for anything the envelope doesn't surface β€” mentions, reply chains, embeds, entities.
71
-
72
- ## Detecting "is this for me?"
73
-
74
- Derive from `payload`. Bot id per station is cached in `$METRO_STATE_DIR/bot-ids.json` (`{discord:"<userId>", telegram:"<userId>"}`, written by the daemon on start).
75
-
76
- - **discord** β€” DM when `payload.guildId == null`; otherwise pinged when `payload.mentions.users.includes(<bot-id>)`.
77
- - **telegram** β€” DM when `payload.chat.type === 'private'`; otherwise pinged when any entity in `payload.entities` (or `caption_entities`) is `{type:"mention"}` matching `@<bot-username>` or `{type:"text_mention", user:{id:<bot-id>}}`.
78
-
79
- Default: only reply on DM or ping; otherwise stay silent or `metro react` to ack.
80
-
81
- Both `from` and `to` are **participant URIs** (the conversation context lives in `line`):
82
- - `metro://<station>/user/<id>` β€” a person on a chat platform
83
- - `metro://claude/<topic>` / `metro://codex/<topic>` β€” an agent
84
- - `metro://<station>/<channelId>` β€” a channel (used as `to` for fresh sends to a group, where no single recipient)
85
-
86
- When **you** send via `metro send`/`reply`/`edit`/`react`, metro auto-stamps `from = metro://claude/agent` (from `$CLAUDECODE`) or `metro://codex/agent` (from `$METRO_CODEX_RC` / `$CODEX_HOME`). Override with `--from=<uri>` or `$METRO_FROM`. When replying/reacting, `to` is automatically the original sender (looked up via the universal id).
87
-
88
- The `id` is the **canonical handle** for that message across all stations β€” store it if you want to refer back to it later.
89
-
90
- - `kind: "inbound"` β€” a human (or another bot) posted on a chat platform.
91
- - `kind: "notification"` β€” another agent called `metro send` against your agent line. This is how Codex pings Claude Code and vice versa.
92
-
93
- `text` may contain `[image]`, `[voice]`, `[audio]`, or `[file: <name>]` placeholders alongside the real text β€” non-image attachments are opaque markers; images can be materialized via `metro download`.
94
-
95
- ## Required flow on every event
96
-
97
- 1. **Echo to your visible output**: `[<line>#<messageId>] <text>` on its own line. Both Claude Code's Monitor and Codex collapse tool output, so this echo is the only way the user sees what arrived without expanding cards.
98
- 2. **Decide and act** using the subcommands below.
99
-
100
- No server-side auto-reaction β€” don't expect πŸ‘€ to be on the user's message; add one yourself with `metro react` if you want to ack quickly.
101
-
102
- ## Subcommands
103
-
104
- All take positional args (no `--to=`/`--text=` flags). Append `--json` to any for a parseable single-line result.
105
-
106
- | Action | Command |
107
- |---|---|
108
- | Quote-reply (threads under original) | `metro reply <line> <messageId> <text>` |
109
- | Send a fresh message (no reply context) | `metro send <line> <text>` |
110
- | Edit a message you previously sent | `metro edit <line> <messageId> <text>` |
111
- | Reaction (empty emoji clears) | `metro react <line> <messageId> <emoji>` |
112
- | Download `[image]` attachments β†’ paths | `metro download <line> <messageId> [--out=<dir>]` |
113
- | Recent channel history (Discord only) | `metro fetch <line> [--limit=20]` |
114
- | Ping another agent (cross-agent line) | `metro send metro://claude/<topic> <text> [--from=<line>]` |
115
-
116
- `reply` / `send` / `edit` accept multi-line text via stdin (heredoc).
117
-
118
- ### Rich content flags
119
-
120
- `send` and `reply` accept these extra flags; `edit` accepts `--buttons` only.
121
-
122
- - `--image=<path>` β€” upload a local image. **Repeatable** for albums: `--image=a.png --image=b.png`. Comma-separated also works: `--image='a.png,b.png'`. Up to 10 / message. Text becomes the caption (on the first image for albums).
123
- - `--document=<path>` β€” upload any local file (PDF, log, csv, …). Same repeat/comma syntax.
124
- - `--voice=<path>` β€” single voice message (`.ogg` Opus or `.mp3`). On Telegram renders as a voice bubble via `sendVoice`; on Discord uploaded as an audio attachment.
125
- - `--buttons='[[{"text":"…","url":"https://…"}]]'` β€” attach an inline URL-button keyboard. 2D array: outer = rows, inner = buttons on that row.
126
-
127
- ```bash
128
- metro send <line> "screenshot" --image=/tmp/build.png
129
- metro send <line> "before/after" --image=/tmp/before.png --image=/tmp/after.png
130
- metro reply <line> <id> "log + transcript" --document=/tmp/run.log --document=/tmp/transcript.txt
131
- metro send <line> "have a listen" --voice=/tmp/note.ogg
132
- metro send <line> "approve?" --buttons='[[{"text":"Open PR","url":"https://github.com/x/y/pull/1"}]]'
133
- metro edit <line> <id> "still working…" --buttons='[]' # clears buttons
134
- ```
135
-
136
- Limits / quirks:
137
- - 20 MB per file (both platforms).
138
- - Telegram albums are single-type (all photos OR all documents in one album). Mixing kinds in one send still works β€” metro splits into two album messages and returns the first id.
139
- - Telegram drops `--buttons` when multiple attachments are sent (the bot API doesn't allow `reply_markup` on media groups).
140
- - URL buttons only (no callback / interactive components yet).
141
-
142
- ## When to use `reply` vs `send`
143
-
144
- - **`reply`** β€” responding to a specific inbound message. Threads under it. Default for handling an `inbound` event.
145
- - **`send`** β€” initiating without a triggering message: a long task finished, a follow-up the user asked you to deliver later, or posting to an agent line (`metro://claude/...`, `metro://codex/...`) to notify a peer.
146
-
147
- ## Line URI scheme
148
-
149
- `metro://<station>/<path>` β€” see [docs/uri-scheme.md](https://github.com/bonustrack/metro/blob/main/docs/uri-scheme.md) for the full grammar.
150
-
151
- | Station | Pattern | Example |
152
- |------------|-------------------------------------------|--------------------------------------|
153
- | `discord` | `metro://discord/<channel-id>` | `metro://discord/1234567890` |
154
- | `telegram` | `metro://telegram/<chat-id>[/<topic-id>]` | `metro://telegram/-1001234567890/42` |
155
- | `claude` | `metro://claude/<topic>` | `metro://claude/deploys` |
156
- | `codex` | `metro://codex/<topic>` | `metro://codex/ci` |
157
-
158
- The `messageId` is **not** part of the URI β€” it's a separate positional arg for `reply` / `edit` / `react` / `download`.
159
-
160
- ## Image attachments
161
-
162
- When an event's `text` contains `[image]`:
163
-
164
- 1. `metro download <line> <messageId>` β€” writes images to disk and prints absolute paths.
165
- 2. `Read` each path with your Read tool β€” the image enters your context as a vision input.
166
- 3. Reply normally with `metro reply`.
167
-
168
- ## Opaque attachment markers
169
-
170
- `[voice]`, `[audio]`, and `[file: <name>]` are opaque β€” `metro download` only handles images. Acknowledge in text or ask the user to resend as a regular file.
171
-
172
- ## Cross-agent notification
173
-
174
- Both agents can post to each other's "agent line":
175
-
176
- ```bash
177
- metro send metro://claude/deploys "build green, ready to ship"
178
- metro send metro://codex/ci "build green" --from=metro://claude/deploys # override sender
179
- ```
180
-
181
- The daemon re-emits the post on its stdout stream (and pushes via codex-rc if configured), so the peer agent sees a `{"kind":"notification",...}` event. Requires the metro daemon to be running on the machine β€” agent-line sends error with `metro daemon is not running` otherwise.
182
-
183
- ## Discoverability
184
-
185
- - `metro lines` β€” list recently-seen conversations (sorted by recency).
186
- - `metro stations` β€” list stations + capability matrix.
187
- - `metro history` β€” universal message log (every inbound + outbound + notification across all stations). Newest first. Filters:
188
- - `--limit=N` (default 50)
189
- - `--line=<metro://…>` β€” only this conversation
190
- - `--station=<discord|telegram|claude|codex>`
191
- - `--kind=<inbound|outbound|edit|react|notification>`
192
- - `--from=<sender>`
193
- - `--text=<substring>`
194
- - `--since=<iso>` β€” e.g. `--since=2026-05-14T00:00:00Z`
195
- - `--json` β€” machine-parseable
196
-
197
- Every action you take is logged automatically β€” `metro send`/`reply`/`edit`/`react` append outbound entries, daemon-side inbounds + notifications append on arrival. Stored at `$METRO_STATE_DIR/history.jsonl`.
198
-
199
- ## Universal message IDs
200
-
201
- The `id` from `metro history` or an event JSON works **anywhere a `<message_id>` argument is expected**:
202
-
203
- ```bash
204
- # Either form works for reply/edit/react/download:
205
- metro reply <line> 4567 "ack" # platform messageId (Telegram int)
206
- metro reply <line> msg_aB3xY7zP "ack" # universal β€” resolves via history
207
- ```
208
-
209
- Use universal IDs when chaining commands or referring back to a specific message across stations.
210
-
211
- ## Exit codes
212
-
213
- - `0` success
214
- - `1` usage error (bad args, unknown subcommand)
215
- - `2` configuration error (no tokens β€” tell the user to run `metro setup`)
216
- - `3` upstream error (rate limit, auth, network) β€” retry once after a few seconds before surfacing
217
-
218
- `metro doctor` diagnoses tokens, gateways, dispatcher liveness, and codex-rc target.
219
-
220
- ## --json output
221
-
222
- Every command supports `--json` for stable parseable output:
223
-
224
- ```bash
225
- metro reply <line> <messageId> "ack" --json
226
- # {"ok":true,"line":"metro://discord/...","replyTo":"...","messageId":"..."}
227
-
228
- metro fetch metro://discord/1234 --limit=10 --json
229
- # {"ok":true,"line":"...","messages":[{"messageId":"...","author":"...","text":"...","timestamp":"..."},...]}
230
-
231
- metro download <line> <messageId> --json
232
- # {"ok":true,"line":"...","files":[{"path":"/abs/...png","mediaType":"image/png"}]}
233
- ```
234
-
235
- Use `--json` when you need to chain calls or capture the new `messageId` for a later edit.
236
-
237
- ## Don'ts
238
-
239
- - ❌ Spawning a second metro daemon β€” there's one per machine (lockfile-enforced).
240
- - ❌ Posting to a line that isn't in `metro lines` unless the user gave it to you explicitly.
241
- - ❌ Narrating the tool ("I'll now use metro reply to…"). The tool call is already visible to the user.