@cursor/july 0.1.2 → 0.1.4

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 (232) hide show
  1. package/AGENTS.md +16 -5
  2. package/README.md +8 -9
  3. package/dist/bin/agent-serve.d.ts +3 -1
  4. package/dist/bin/agent-serve.d.ts.map +1 -1
  5. package/dist/bin/agent-serve.js +416 -155
  6. package/dist/channels/slack/log.d.ts +1 -1
  7. package/dist/channels/slack/log.d.ts.map +1 -1
  8. package/dist/channels/slack/log.js +4 -5
  9. package/dist/channels/slack/setup.js +1 -1
  10. package/dist/channels/slack/socket-mode.d.ts.map +1 -1
  11. package/dist/channels/slack/socket-mode.js +10 -9
  12. package/dist/docs/404.html +2 -2
  13. package/dist/docs/ab.html +3 -3
  14. package/dist/docs/assets/{app.Oje4vhlk.js → app.DF-Yx4OP.js} +1 -1
  15. package/dist/docs/assets/chunks/@localSearchIndexroot.0XrheBv2.js +1 -0
  16. package/dist/docs/assets/chunks/{VPLocalSearchBox.H5XZ2zCB.js → VPLocalSearchBox.DSeJSudL.js} +1 -1
  17. package/dist/docs/assets/chunks/{theme.CTR_TuaE.js → theme.DZVLTXOC.js} +2 -2
  18. package/dist/docs/assets/{index.md.m81y7TY7.js → index.md.Cylk70gg.js} +1 -1
  19. package/dist/docs/assets/{quickstart.md.CfU8_uTC.js → quickstart.md.BU6Iwi_9.js} +18 -6
  20. package/dist/docs/assets/{reference_cli.md.DA730zCu.js → reference_cli.md.Bv6pOxcF.js} +11 -6
  21. package/dist/docs/assets/{reference_cli.md.DA730zCu.lean.js → reference_cli.md.Bv6pOxcF.lean.js} +1 -1
  22. package/dist/docs/building-with-agents.html +3 -3
  23. package/dist/docs/concepts.html +3 -3
  24. package/dist/docs/deployment.html +3 -3
  25. package/dist/docs/evals.html +3 -3
  26. package/dist/docs/guides/agent-to-agent.html +3 -3
  27. package/dist/docs/guides/cloud-runtime.html +3 -3
  28. package/dist/docs/guides/github.html +3 -3
  29. package/dist/docs/guides/human-in-the-loop.html +3 -3
  30. package/dist/docs/guides/slack.html +3 -3
  31. package/dist/docs/guides/webhooks.html +3 -3
  32. package/dist/docs/hashmap.json +1 -1
  33. package/dist/docs/hillclimbing.html +3 -3
  34. package/dist/docs/index.html +5 -5
  35. package/dist/docs/quickstart.html +22 -10
  36. package/dist/docs/reference/agent-config.html +3 -3
  37. package/dist/docs/reference/channels.html +3 -3
  38. package/dist/docs/reference/cli.html +14 -9
  39. package/dist/docs/reference/connections.html +3 -3
  40. package/dist/docs/reference/hooks.html +3 -3
  41. package/dist/docs/reference/http-api.html +3 -3
  42. package/dist/docs/reference/instructions.html +3 -3
  43. package/dist/docs/reference/playground.html +3 -3
  44. package/dist/docs/reference/project-layout.html +3 -3
  45. package/dist/docs/reference/schedules.html +3 -3
  46. package/dist/docs/reference/sessions.html +3 -3
  47. package/dist/docs/reference/skills.html +3 -3
  48. package/dist/docs/reference/subagents.html +3 -3
  49. package/dist/docs/reference/tools.html +3 -3
  50. package/dist/docs/scaffolding-agents.html +3 -3
  51. package/dist/docs/storage.html +3 -3
  52. package/dist/docs/troubleshooting.html +3 -3
  53. package/dist/internal/ab-collector.js +3 -3
  54. package/dist/internal/ab-fold.js +1 -1
  55. package/dist/internal/chat-client.d.ts +29 -3
  56. package/dist/internal/chat-client.d.ts.map +1 -1
  57. package/dist/internal/chat-client.js +180 -27
  58. package/dist/internal/cli-ax.d.ts +83 -2
  59. package/dist/internal/cli-ax.d.ts.map +1 -1
  60. package/dist/internal/cli-ax.js +626 -52
  61. package/dist/internal/cli-cursor.d.ts.map +1 -1
  62. package/dist/internal/cli-cursor.js +8 -36
  63. package/dist/internal/cli-deploy.d.ts +59 -3
  64. package/dist/internal/cli-deploy.d.ts.map +1 -1
  65. package/dist/internal/cli-deploy.js +316 -38
  66. package/dist/internal/cli-github.js +13 -13
  67. package/dist/internal/cursor/account-mcp.js +3 -3
  68. package/dist/internal/cursor/backend-client.js +1 -1
  69. package/dist/internal/cursor/credentials.d.ts +14 -3
  70. package/dist/internal/cursor/credentials.d.ts.map +1 -1
  71. package/dist/internal/cursor/credentials.js +21 -6
  72. package/dist/internal/cursor/github-credentials.js +3 -3
  73. package/dist/internal/cursor-event-relay.js +1 -1
  74. package/dist/internal/cursor-relay-core.d.ts +1 -1
  75. package/dist/internal/cursor-relay-core.d.ts.map +1 -1
  76. package/dist/internal/cursor-relay-core.js +2 -1
  77. package/dist/internal/cursor-slack-relay.js +1 -1
  78. package/dist/internal/deploy-client.d.ts +9 -1
  79. package/dist/internal/deploy-client.d.ts.map +1 -1
  80. package/dist/internal/deploy-client.js +23 -3
  81. package/dist/internal/deploy-source.d.ts +35 -0
  82. package/dist/internal/deploy-source.d.ts.map +1 -0
  83. package/dist/internal/deploy-source.js +118 -0
  84. package/dist/internal/discovery.d.ts +11 -0
  85. package/dist/internal/discovery.d.ts.map +1 -1
  86. package/dist/internal/discovery.js +43 -14
  87. package/dist/internal/distribution.d.ts +7 -0
  88. package/dist/internal/distribution.d.ts.map +1 -1
  89. package/dist/internal/distribution.js +7 -0
  90. package/dist/internal/docs-site.js +3 -3
  91. package/dist/internal/eval-run-store.d.ts.map +1 -1
  92. package/dist/internal/eval-run-store.js +10 -9
  93. package/dist/internal/eval-runner.d.ts +2 -0
  94. package/dist/internal/eval-runner.d.ts.map +1 -1
  95. package/dist/internal/eval-runner.js +2 -0
  96. package/dist/internal/event-mapper.d.ts +54 -1
  97. package/dist/internal/event-mapper.d.ts.map +1 -1
  98. package/dist/internal/event-mapper.js +151 -41
  99. package/dist/internal/github-fanout.js +2 -2
  100. package/dist/internal/host-platforms.js +5 -5
  101. package/dist/internal/init-project.d.ts +88 -1
  102. package/dist/internal/init-project.d.ts.map +1 -1
  103. package/dist/internal/init-project.js +221 -31
  104. package/dist/internal/install-cursor-skills.d.ts +64 -0
  105. package/dist/internal/install-cursor-skills.d.ts.map +1 -0
  106. package/dist/internal/install-cursor-skills.js +274 -0
  107. package/dist/internal/logs-client.d.ts +60 -0
  108. package/dist/internal/logs-client.d.ts.map +1 -0
  109. package/dist/internal/logs-client.js +311 -0
  110. package/dist/internal/mcp-endpoint.d.ts.map +1 -1
  111. package/dist/internal/mcp-endpoint.js +1 -1
  112. package/dist/internal/open-browser.d.ts +5 -0
  113. package/dist/internal/open-browser.d.ts.map +1 -0
  114. package/dist/internal/open-browser.js +34 -0
  115. package/dist/internal/playground/toolchain.d.ts.map +1 -1
  116. package/dist/internal/playground/toolchain.js +19 -14
  117. package/dist/internal/playground-proxy.d.ts +69 -0
  118. package/dist/internal/playground-proxy.d.ts.map +1 -0
  119. package/dist/internal/playground-proxy.js +468 -0
  120. package/dist/internal/prompt-context.d.ts +35 -0
  121. package/dist/internal/prompt-context.d.ts.map +1 -0
  122. package/dist/internal/prompt-context.js +71 -0
  123. package/dist/internal/reminder-runner.d.ts.map +1 -1
  124. package/dist/internal/reminder-runner.js +11 -11
  125. package/dist/internal/request-headers.d.ts +11 -0
  126. package/dist/internal/request-headers.d.ts.map +1 -0
  127. package/dist/internal/request-headers.js +14 -0
  128. package/dist/internal/resolve-prod-target.d.ts +44 -0
  129. package/dist/internal/resolve-prod-target.d.ts.map +1 -0
  130. package/dist/internal/resolve-prod-target.js +134 -0
  131. package/dist/internal/resolved-connections.js +5 -5
  132. package/dist/internal/run-client.d.ts +2 -2
  133. package/dist/internal/run-client.d.ts.map +1 -1
  134. package/dist/internal/run-client.js +38 -23
  135. package/dist/internal/schedule-runner.js +1 -1
  136. package/dist/internal/server.d.ts.map +1 -1
  137. package/dist/internal/server.js +23 -17
  138. package/dist/internal/session-engine.d.ts +1 -1
  139. package/dist/internal/session-engine.d.ts.map +1 -1
  140. package/dist/internal/session-engine.js +34 -19
  141. package/dist/internal/sessions-client.d.ts +34 -0
  142. package/dist/internal/sessions-client.d.ts.map +1 -0
  143. package/dist/internal/sessions-client.js +193 -0
  144. package/dist/internal/storage-coordinator.js +6 -6
  145. package/dist/internal/stream-progress.d.ts.map +1 -1
  146. package/dist/internal/stream-progress.js +31 -3
  147. package/dist/internal/terminal-style.d.ts +22 -0
  148. package/dist/internal/terminal-style.d.ts.map +1 -0
  149. package/dist/internal/terminal-style.js +49 -0
  150. package/dist/internal/trajectory.d.ts +10 -5
  151. package/dist/internal/trajectory.d.ts.map +1 -1
  152. package/dist/internal/trajectory.js +82 -10
  153. package/dist/internal/update-check.d.ts +93 -0
  154. package/dist/internal/update-check.d.ts.map +1 -0
  155. package/dist/internal/update-check.js +431 -0
  156. package/dist/internal/workspace.d.ts +11 -0
  157. package/dist/internal/workspace.d.ts.map +1 -1
  158. package/dist/internal/workspace.js +38 -4
  159. package/dist/playground/assets/index-Ct_Usdm8.css +1 -0
  160. package/dist/playground/assets/index-Dsyb-Vaj.js +319 -0
  161. package/dist/playground/index.html +2 -2
  162. package/dist/types.d.ts +29 -2
  163. package/dist/types.d.ts.map +1 -1
  164. package/docs/README.md +0 -1
  165. package/docs/quickstart.md +22 -7
  166. package/docs/reference/cli.md +51 -3
  167. package/package.json +4 -1
  168. package/skills/ab/SKILL.md +8 -8
  169. package/skills/create-agent/SKILL.md +28 -22
  170. package/skills/debug/SKILL.md +11 -11
  171. package/skills/evals/SKILL.md +16 -16
  172. package/skills/framework-map/SKILL.md +6 -6
  173. package/skills/github/SKILL.md +13 -13
  174. package/skills/hillclimb/SKILL.md +10 -10
  175. package/skills/setup-slack/SKILL.md +14 -14
  176. package/src/bin/agent-serve.ts +451 -191
  177. package/src/channels/slack/log.ts +5 -5
  178. package/src/channels/slack/setup.ts +1 -1
  179. package/src/channels/slack/socket-mode.ts +11 -9
  180. package/src/internal/ab-collector.ts +3 -3
  181. package/src/internal/ab-fold.ts +1 -1
  182. package/src/internal/chat-client.ts +252 -37
  183. package/src/internal/cli-ax.ts +761 -72
  184. package/src/internal/cli-cursor.ts +14 -42
  185. package/src/internal/cli-deploy.ts +428 -49
  186. package/src/internal/cli-github.ts +13 -15
  187. package/src/internal/cursor/account-mcp.ts +3 -3
  188. package/src/internal/cursor/backend-client.ts +1 -1
  189. package/src/internal/cursor/credentials.ts +26 -7
  190. package/src/internal/cursor/github-credentials.ts +3 -3
  191. package/src/internal/cursor-event-relay.ts +1 -1
  192. package/src/internal/cursor-relay-core.ts +4 -2
  193. package/src/internal/cursor-slack-relay.ts +1 -1
  194. package/src/internal/deploy-client.ts +45 -4
  195. package/src/internal/deploy-source.ts +133 -0
  196. package/src/internal/discovery.ts +53 -16
  197. package/src/internal/distribution.ts +8 -0
  198. package/src/internal/docs-site.ts +3 -3
  199. package/src/internal/eval-run-store.ts +10 -11
  200. package/src/internal/eval-runner.ts +5 -0
  201. package/src/internal/event-mapper.ts +222 -42
  202. package/src/internal/github-fanout.ts +2 -2
  203. package/src/internal/host-platforms.ts +5 -5
  204. package/src/internal/init-project.ts +333 -51
  205. package/src/internal/install-cursor-skills.ts +327 -0
  206. package/src/internal/logs-client.ts +442 -0
  207. package/src/internal/mcp-endpoint.ts +1 -3
  208. package/src/internal/open-browser.ts +41 -0
  209. package/src/internal/playground/toolchain.ts +18 -16
  210. package/src/internal/playground-proxy.ts +576 -0
  211. package/src/internal/prompt-context.ts +95 -0
  212. package/src/internal/reminder-runner.ts +11 -17
  213. package/src/internal/request-headers.ts +23 -0
  214. package/src/internal/resolve-prod-target.ts +182 -0
  215. package/src/internal/resolved-connections.ts +5 -5
  216. package/src/internal/run-client.ts +39 -36
  217. package/src/internal/schedule-runner.ts +1 -1
  218. package/src/internal/server.ts +25 -16
  219. package/src/internal/session-engine.ts +35 -18
  220. package/src/internal/sessions-client.ts +216 -0
  221. package/src/internal/storage-coordinator.ts +6 -6
  222. package/src/internal/stream-progress.ts +36 -2
  223. package/src/internal/terminal-style.ts +74 -0
  224. package/src/internal/trajectory.ts +91 -13
  225. package/src/internal/update-check.ts +552 -0
  226. package/src/internal/workspace.ts +42 -4
  227. package/src/types.ts +45 -7
  228. package/dist/docs/assets/chunks/@localSearchIndexroot.zwQ9RCQ7.js +0 -1
  229. package/dist/playground/assets/index-B1Qc9h2u.css +0 -1
  230. package/dist/playground/assets/index-CpDYCj8W.js +0 -79
  231. /package/dist/docs/assets/{index.md.m81y7TY7.lean.js → index.md.Cylk70gg.lean.js} +0 -0
  232. /package/dist/docs/assets/{quickstart.md.CfU8_uTC.lean.js → quickstart.md.BU6Iwi_9.lean.js} +0 -0
@@ -3,10 +3,12 @@
3
3
  * agent-serve CLI.
4
4
  *
5
5
  * agent-serve serve [--dir .] [--port 3000] [--host 127.0.0.1] [--dev]
6
+ * agent-serve dev [path] [--port 3000] [--host 127.0.0.1]
6
7
  * agent-serve chat [--url http://127.0.0.1:3000] [--message "..."] [--json]
8
+ * agent-serve resume [sessionId] [--url | --prod] [--message "..."]
7
9
  * agent-serve run [--dir .] [--message "..."] [--json|--text]
8
10
  * agent-serve trajectory --events <file.ndjson>
9
- * agent-serve init [dir]
11
+ * agent-serve init [dir] [--json]
10
12
  * agent-serve eval [--dir .] [evalId...]
11
13
  * agent-serve validate [--dir .]
12
14
  * agent-serve slack <subcommand>
@@ -22,13 +24,18 @@ import {
22
24
  serve,
23
25
  } from "../index.js";
24
26
  import { registerAuthoredModuleLoaders } from "../internal/authored-loaders.js";
25
- import { runChat } from "../internal/chat-client.js";
26
27
  import {
27
28
  type AxCliOptions,
28
29
  cmdCall,
30
+ cmdChat,
29
31
  cmdEval,
30
32
  cmdInit,
33
+ cmdLogs,
34
+ cmdPlayground,
35
+ cmdResume,
31
36
  cmdRun,
37
+ cmdSession,
38
+ cmdSessions,
32
39
  cmdTrajectory,
33
40
  } from "../internal/cli-ax.js";
34
41
  import {
@@ -44,8 +51,8 @@ import {
44
51
  type DeployCliOptions,
45
52
  } from "../internal/cli-deploy.js";
46
53
  import { CLI_COMMAND_NAME as CLI } from "../internal/distribution.js";
47
- import { runSession } from "../internal/run-client.js";
48
- import { formatTrajectoryText } from "../internal/trajectory.js";
54
+ import { clearTerminal, stdoutPalette } from "../internal/terminal-style.js";
55
+ import { cmdUpdate, warnIfOutdated } from "../internal/update-check.js";
49
56
  import type { AgentProject, AgentServeHandle } from "../types.js";
50
57
 
51
58
  const HELP = `${CLI} — serve a filesystem-defined Cursor agent over channels
@@ -55,24 +62,43 @@ Usage:
55
62
  [--mode single|multi] [--api-key <key>] [--no-schedules]
56
63
  [--public-url <url>]
57
64
  [--cursor-events --repo <owner/name>]...
58
- ${CLI} chat [--url <baseUrl>] [--message <text>] [--json] [--text]
59
- ${CLI} run [--dir <path>] [--message <text>]... [--url <baseUrl>]
65
+ ${CLI} dev [path] [--port <n>] [--host <host>]
66
+ Same flags as serve; implies --dev. Path defaults to
67
+ the current directory (or pass --dir).
68
+ ${CLI} chat [--url <baseUrl> | --prod] [--message <text>] [--json] [--text]
69
+ [--session <id> | --resume] [--continuation-token <t>]
70
+ [--slug <slug>] [--team <id>]
71
+ ${CLI} resume [sessionId] [--url <baseUrl> | --prod] [--message <text>]
72
+ [--json] [--text] [--continuation-token <t>]
73
+ [--slug <slug>] [--team <id>]
74
+ ${CLI} logs [--url <baseUrl> | --prod] [--once] [--json]
75
+ [--slug <slug>] [--team <id>] [--dir <path>]
76
+ ${CLI} sessions [--url <baseUrl> | --prod] [--json]
77
+ [--slug <slug>] [--team <id>] [--dir <path>]
78
+ ${CLI} session <sessionId> [--url <baseUrl> | --prod]
79
+ [--json | --text | --events]
80
+ [--slug <slug>] [--team <id>] [--dir <path>]
81
+ ${CLI} playground [--url <baseUrl> | --prod] [--session <id>] [--print]
82
+ [--slug <slug>] [--team <id>] [--dir <path>]
83
+ ${CLI} run [--dir <path>] [--message <text>]... [--url <baseUrl> | --prod]
60
84
  [--session <id>] [--continuation-token <t>]
61
85
  [--events <file.ndjson>] [--no-events] [--text]
62
- [--timeout-ms <n>] [--no-stream]
86
+ [--timeout-ms <n>] [--no-stream] [--slug <slug>] [--team <id>]
63
87
  ${CLI} trajectory --events <file.ndjson> [--text]
64
- ${CLI} call <tool> [--input <json>] [--dir <path> | --url <baseUrl>]
65
- [--session <id>] [--slug <slug>]
66
- ${CLI} init [dir]
88
+ ${CLI} call <tool> [--input <json>] [--dir <path> | --url <baseUrl> | --prod]
89
+ [--session <id>] [--slug <slug>] [--team <id>]
90
+ ${CLI} init [dir] [--json]
67
91
  ${CLI} eval [--dir <path>] [evalId...] [--list] [--json]
68
92
  [--tag <tag>]... [--verbose] [--timeout-ms <n>]
69
- [--no-stream]
93
+ [--no-stream] [--url <baseUrl> | --prod] [--slug <slug>]
94
+ [--team <id>]
70
95
  ${CLI} info [--dir <path>] [--json]
71
96
  ${CLI} validate [--dir <path>]
72
97
  ${CLI} login [--api-key <key>] [--key-name <name>]
73
98
  ${CLI} logout
74
99
  ${CLI} whoami [--json]
75
- ${CLI} deploy [--dir <path>] [--slug <slug>] [--team <id>] [--json]
100
+ ${CLI} update
101
+ ${CLI} deploy [--dir <path>] [--slug <slug> | --all] [--team <id>] [--json]
76
102
  [--no-wait] [--repo <url>] [--ref <ref>]
77
103
  [--path <agentPath>] [--cursor-events-repo <owner/name>]...
78
104
  [--allow-domain <domain>]...
@@ -89,15 +115,45 @@ Usage:
89
115
  Commands:
90
116
  serve Serve agents under /<slug>/... (index at /). On a TTY, press
91
117
  Enter to restart (reloads agent code + Vite HMR child).
92
- chat Talk to a running server (streams the reply). --json prints a trajectory.
118
+ dev Local development: same as \`${CLI} serve --dev\` (manual
119
+ schedule/reminder dispatch, unsigned GitHub loopback, Vite HMR).
120
+ chat Interactive REPL against a running server (follow-ups keep the
121
+ session + continuation token). Optional --message seeds the first
122
+ turn then stays open on a TTY. --session reattaches (looks up the
123
+ continuation token via /v1/sessions when omitted) and replays the
124
+ transcript. --resume reattaches the most recently updated
125
+ followable session (no id needed). --json is one-shot. Pass
126
+ --prod to hit the team's hosted deployment (slug from --slug or
127
+ the directory name).
128
+ resume Reattach chat to a session (same as \`${CLI} chat --session <id>\`
129
+ or \`${CLI} chat --resume\` with no id). Omit the session id to
130
+ resume the previous followable session from /v1/sessions. Looks
131
+ up the continuation token via /v1/sessions when
132
+ --continuation-token is omitted, then replays the transcript.
133
+ Pass --prod for a hosted deployment.
134
+ logs Tail agent logs. Default follows (Ctrl-C to stop); --once dumps
135
+ the current buffer. --prod shows deploy progress until the
136
+ hosted deployment is running, then tails runtime logs. Without
137
+ --prod, tails the local server (or --url).
138
+ sessions List sessions on a running agent (or --prod hosted deployment).
139
+ session Show one session. Default: text trajectory. --json for trajectory
140
+ JSON; --events for the raw event list. To continue interactively,
141
+ use \`${CLI} resume [id]\`.
142
+ playground Open the web playground. --prod starts a loopback proxy that
143
+ injects hosted engine credentials (browsers cannot set them).
144
+ --print skips opening a browser. Ctrl-C stops the proxy.
93
145
  run One-shot create→test loop: ephemeral server + JSON trajectory.
94
146
  Writes a single events.ndjson trace (visualize in the playground).
95
147
  Streams tool calls and reply text to stderr when stderr is a TTY.
148
+ Pass --prod to hit the hosted deployment instead of a local server.
96
149
  trajectory Summarize an events.ndjson file into a trajectory.
97
150
  call Call an authored server tool deterministically (no model turn)
98
151
  via POST /v1/tools/:toolName. --session runs it inside an
99
152
  existing session and records it on that session's event stream.
100
- init Scaffold a project, or print the coding-agent setup guide (no args).
153
+ init Scaffold a project (skipping existing files), npm install,
154
+ run login when unsigned, then print next steps. --json is
155
+ machine-readable and never blocks on login. No directory:
156
+ print the setup guide.
101
157
  eval Run filesystem evals under evals/**/*.eval.ts (streams on a TTY).
102
158
  Pass evalId args to select: one datapoint (weather/nyc), a whole
103
159
  file (weather → all cases in that file), several of either, or
@@ -109,9 +165,14 @@ Commands:
109
165
  inference, cloud runtime, and cursorAccount MCP connections.
110
166
  logout Remove the stored Cursor credentials.
111
167
  whoami Show which Cursor account powers this host (and why).
168
+ update Upgrade this install to the latest published version (detects
169
+ global npm/pnpm/yarn/bun installs and project dependencies).
112
170
  deploy Deploy onto Cursor's managed agent-serve hosting, then wait for
113
- the engine to come up. First deploy of a slug prints the alias
114
- token exactly once save it.
171
+ the engine to come up. --repo/--ref/--path stay available;
172
+ inside an agent git checkout they are inferred when omitted
173
+ (flags always win). When --dir is a multi-agent parent,
174
+ pick one interactively, or pass --slug / --all. First deploy
175
+ of a slug prints the alias token exactly once — save it.
115
176
  deployments List the team's deployments (slug, status, generation, kind).
116
177
  deployment Show one deployment in full (status, lastError, engine info).
117
178
  stop Stop a deployment and wait until it reports stopped.
@@ -132,6 +193,7 @@ Agent loop:
132
193
  ${CLI} info --dir . --json
133
194
  ${CLI} run --dir . --message "..."
134
195
  ${CLI} eval --dir .
196
+ ${CLI} dev .
135
197
 
136
198
  Options:
137
199
  --dir Project root (defaults to the current directory).
@@ -152,28 +214,53 @@ Options:
152
214
  send it as the Authorization bearer.
153
215
  --allow-anonymous serve: admit all HTTP callers (allowAll). For demos behind a
154
216
  trusted network only; mutually exclusive with --bearer-token.
217
+ --allow-anonymous-cursor-github
218
+ serve: allow --allow-anonymous together with
219
+ githubChannel({ cursorAccount }). Admitted callers can drive
220
+ sessions holding the account's repo-scoped GitHub credential,
221
+ so use only behind a trusted boundary (e.g. an SSO proxy).
155
222
  --public-url serve: base URL where this host is reachable from outside
156
223
  (e.g. https://agent-serve.example.com). Required for peer
157
224
  connections (defineConnection({ agent })) on cloud-runtime
158
225
  turns; local turns always use loopback.
159
226
  --no-schedules Disable the cron runner outside dev mode.
160
- --team deploy/deployments/deployment/stop/rotate-token: Cursor
161
- team id. Defaults to the account's team when it has one.
227
+ --team deploy/deployments/deployment/stop/rotate-token and
228
+ chat/resume/run/call/eval/logs/sessions/session/playground
229
+ --prod: Cursor team id. Defaults to the account's team when
230
+ it has one.
231
+ --prod chat/resume/run/call/eval/logs/sessions/session/playground:
232
+ use the team's hosted deployment. Slug from --slug or the
233
+ --dir basename. Mutually exclusive with --url. Requires
234
+ \`${CLI} login\`.
235
+ --once logs: print current progress / log buffer once and exit
236
+ (default is to follow).
237
+ --print playground: print the URL only; do not open a browser.
162
238
  --no-wait deploy/stop: return right after the request is accepted
163
239
  instead of polling until a terminal status.
164
240
  --no-playground Disable the bundled web playground at /playground (also skips
165
241
  auto-build / HMR).
166
242
  --no-docs Disable the documentation site at /docs (also skips its
167
243
  auto-build).
168
- --url chat/run/eval: base URL of a running agent (skip local host).
169
- --message chat/run: user message (repeatable for run).
244
+ --url chat/resume/run/call/eval/logs/sessions/session/playground:
245
+ base URL of a running agent (skip local host). Mutually
246
+ exclusive with --prod.
247
+ --message chat/resume/run: user message (repeatable for run).
170
248
  --input call: JSON object of tool arguments (default {}).
171
249
  --messages-file JSON array of strings (run).
172
- --session Existing session id for a follow-up turn.
173
- --continuation-token Token from a prior run/chat response.
250
+ --session Existing session id (run/call follow-up, or chat reattach).
251
+ Prefer \`${CLI} resume [sessionId]\` for interactive
252
+ reattach.
253
+ --resume chat: reattach the previous followable session (most
254
+ recently updated in /v1/sessions). Same as
255
+ \`${CLI} resume\` with no session id. Ignored when
256
+ --session is also set.
257
+ --continuation-token Token from a prior run/chat/resume response (optional
258
+ for resume / chat --session/--resume; looked up via
259
+ /v1/sessions when omitted).
174
260
  --events run: write NDJSON trace to this path (default
175
261
  <dir>/.agent-serve/traces/<sessionId>.ndjson).
176
- trajectory: read this file.
262
+ trajectory: read this file. session: print raw
263
+ { sessionId, events } JSON (boolean; no path).
177
264
  --no-events run: do not write a trace file.
178
265
  --slug Agent slug when --dir mounts multiple agents.
179
266
  --timeout-ms Abort a hung turn after N milliseconds.
@@ -181,7 +268,9 @@ Options:
181
268
  --list eval: print discovered cases without running.
182
269
  --verbose eval: stream t.log lines and reply snippets.
183
270
  --no-stream run/eval: silence live progress on stderr (JSON still prints).
184
- --json JSON output (info/chat/eval/github; run defaults to JSON).
271
+ --json JSON output (init/info/chat/eval/logs/sessions/session/
272
+ github; run defaults to JSON). logs: NDJSON progress/log
273
+ events. session: trajectory JSON (not raw events).
185
274
  --no-color chat: force plain output.
186
275
  --cursor-events serve: pull SCM webhook events from /v0/scm-events. The
187
276
  stream is read as your Cursor user, so serve requires
@@ -191,10 +280,15 @@ Options:
191
280
  --repo serve --cursor-events: repo to subscribe to (repeatable).
192
281
  github forward: owner/repo to forward from (inferred from
193
282
  the git remote when omitted; last wins).
194
- deploy: https git repo URL the control plane builds from.
195
- --ref deploy: git ref to build (defaults to the repo's default
196
- branch server-side).
197
- --path deploy: agent directory relative to the repo root.
283
+ deploy: https git repo URL (optional; inferred from
284
+ git remote origin when omitted).
285
+ --ref deploy: git ref to build (optional; inferred from the
286
+ current branch when omitted).
287
+ --path deploy: agent dir relative to repo root (optional;
288
+ inferred from --dir vs git toplevel when omitted).
289
+ --all deploy: every child agent under a multi-agent --dir
290
+ (skips the interactive picker; mutually exclusive with
291
+ --slug).
198
292
  --cursor-events-repo deploy: repo (owner/name) whose SCM events the
199
293
  deployed engine pulls (repeatable).
200
294
  --allow-domain deploy: egress domain the engine pod may reach
@@ -215,7 +309,7 @@ Options:
215
309
  `;
216
310
 
217
311
  async function main(argv: string[]): Promise<number> {
218
- const [command, ...rest] = argv;
312
+ const [command, ...restIn] = argv;
219
313
  if (
220
314
  command === undefined ||
221
315
  command === "help" ||
@@ -226,6 +320,13 @@ async function main(argv: string[]): Promise<number> {
226
320
  return command === undefined ? 1 : 0;
227
321
  }
228
322
 
323
+ // `session --events` means "dump raw events" (boolean). Rewrite so it does
324
+ // not collide with run/trajectory's `--events <file.ndjson>` string flag.
325
+ const rest =
326
+ command === "session"
327
+ ? restIn.map((arg) => (arg === "--events" ? "--raw-events" : arg))
328
+ : restIn;
329
+
229
330
  const { values, positionals } = parseArgs({
230
331
  args: rest,
231
332
  allowPositionals: true,
@@ -240,15 +341,18 @@ async function main(argv: string[]): Promise<number> {
240
341
  "state-root": { type: "string" },
241
342
  "bearer-token": { type: "string" },
242
343
  "allow-anonymous": { type: "boolean", default: false },
344
+ "allow-anonymous-cursor-github": { type: "boolean", default: false },
243
345
  "no-schedules": { type: "boolean", default: false },
244
346
  "no-playground": { type: "boolean", default: false },
245
347
  "no-docs": { type: "boolean", default: false },
246
348
  url: { type: "string" },
349
+ prod: { type: "boolean", default: false },
247
350
  message: { type: "string", multiple: true },
248
351
  input: { type: "string" },
249
352
  "messages-file": { type: "string" },
250
353
  "session-id": { type: "string" },
251
354
  session: { type: "string" },
355
+ resume: { type: "boolean", default: false },
252
356
  "continuation-token": { type: "string" },
253
357
  events: { type: "string" },
254
358
  "no-events": { type: "boolean", default: false },
@@ -260,6 +364,8 @@ async function main(argv: string[]): Promise<number> {
260
364
  text: { type: "boolean", default: false },
261
365
  "no-color": { type: "boolean", default: false },
262
366
  "no-stream": { type: "boolean", default: false },
367
+ once: { type: "boolean", default: false },
368
+ "raw-events": { type: "boolean", default: false },
263
369
  json: { type: "boolean", default: false },
264
370
  name: { type: "string" },
265
371
  env: { type: "string" },
@@ -287,12 +393,19 @@ async function main(argv: string[]): Promise<number> {
287
393
  "no-wait": { type: "boolean", default: false },
288
394
  ref: { type: "string" },
289
395
  path: { type: "string" },
396
+ all: { type: "boolean", default: false },
290
397
  "cursor-events-repo": { type: "string", multiple: true },
291
398
  "allow-domain": { type: "string", multiple: true },
292
399
  },
293
400
  });
294
401
  const dir = values.dir ?? ".";
295
402
 
403
+ // Best-effort, cached, and silent on failure. `update` does its own fresh
404
+ // lookup, and --json runs stay quiet for machine consumers.
405
+ if (command !== "update" && values.json !== true) {
406
+ await warnIfOutdated();
407
+ }
408
+
296
409
  switch (command) {
297
410
  case "slack": {
298
411
  const { cmdSlack } = await import("../internal/cli-slack.js");
@@ -352,6 +465,7 @@ async function main(argv: string[]): Promise<number> {
352
465
  return cmdInit({
353
466
  dir,
354
467
  initTarget: positionals[0],
468
+ json: values.json,
355
469
  });
356
470
  }
357
471
 
@@ -373,6 +487,10 @@ async function main(argv: string[]): Promise<number> {
373
487
  return cmdWhoami({ json: values.json });
374
488
  }
375
489
 
490
+ case "update": {
491
+ return cmdUpdate();
492
+ }
493
+
376
494
  case "deploy": {
377
495
  // `--repo` is repeatable for `serve --cursor-events`; deploy targets a
378
496
  // single source repo, so the last one wins.
@@ -381,6 +499,7 @@ async function main(argv: string[]): Promise<number> {
381
499
  ...deployOptionsFromValues(values),
382
500
  dir,
383
501
  ...(values.slug === undefined ? {} : { slug: values.slug }),
502
+ all: values.all === true,
384
503
  ...(repo === undefined ? {} : { repo }),
385
504
  ...(values.ref === undefined ? {} : { ref: values.ref }),
386
505
  ...(values.path === undefined ? {} : { path: values.path }),
@@ -454,6 +573,9 @@ async function main(argv: string[]): Promise<number> {
454
573
  : values.events,
455
574
  text: values.text,
456
575
  url: values.url,
576
+ prod: values.prod,
577
+ team: values.team,
578
+ apiKey: values["api-key"],
457
579
  slug: values.slug,
458
580
  bearerToken: values["bearer-token"],
459
581
  stateRoot: values["state-root"],
@@ -471,6 +593,9 @@ async function main(argv: string[]): Promise<number> {
471
593
  toolInput: values.input,
472
594
  sessionId: values["session-id"] ?? values.session,
473
595
  url: values.url,
596
+ prod: values.prod,
597
+ team: values.team,
598
+ apiKey: values["api-key"],
474
599
  slug: values.slug,
475
600
  bearerToken: values["bearer-token"],
476
601
  stateRoot: values["state-root"],
@@ -502,6 +627,9 @@ async function main(argv: string[]): Promise<number> {
502
627
  json: values.json,
503
628
  tags: values.tag,
504
629
  url: values.url,
630
+ prod: values.prod,
631
+ team: values.team,
632
+ apiKey: values["api-key"],
505
633
  slug: values.slug,
506
634
  bearerToken: values["bearer-token"],
507
635
  stateRoot: values["state-root"],
@@ -512,25 +640,112 @@ async function main(argv: string[]): Promise<number> {
512
640
  }
513
641
 
514
642
  case "chat": {
515
- if (values.json) {
516
- return chatJson({
517
- baseUrl: values.url ?? "http://127.0.0.1:3000",
518
- message: (values.message as string[] | undefined)?.[0],
643
+ return cmdChat(
644
+ axFromOptions({
645
+ dir,
646
+ messages: values.message,
647
+ url: values.url,
648
+ prod: values.prod,
649
+ team: values.team,
650
+ apiKey: values["api-key"],
651
+ slug: values.slug,
652
+ sessionId: values["session-id"] ?? values.session,
653
+ resume: values.resume,
654
+ continuationToken: values["continuation-token"],
519
655
  bearerToken: values["bearer-token"],
656
+ json: values.json,
520
657
  text: values.text,
521
- });
522
- }
523
- await runChat({
524
- baseUrl: values.url ?? "http://127.0.0.1:3000",
525
- ...((values.message as string[] | undefined)?.[0] === undefined
526
- ? {}
527
- : { message: (values.message as string[])[0]! }),
528
- ...(values["bearer-token"] === undefined
529
- ? {}
530
- : { bearerToken: values["bearer-token"] }),
531
- ...(values["no-color"] ? { noColor: true } : {}),
532
- });
533
- return 0;
658
+ noColor: values["no-color"],
659
+ })
660
+ );
661
+ }
662
+
663
+ case "resume": {
664
+ return cmdResume(
665
+ positionals[0],
666
+ axFromOptions({
667
+ dir,
668
+ messages: values.message,
669
+ url: values.url,
670
+ prod: values.prod,
671
+ team: values.team,
672
+ apiKey: values["api-key"],
673
+ slug: values.slug,
674
+ // Positional wins; --session is accepted as a redundant alias.
675
+ // No id → resume previous (cmdResume sets resume: true).
676
+ sessionId: positionals[0] ?? values["session-id"] ?? values.session,
677
+ continuationToken: values["continuation-token"],
678
+ bearerToken: values["bearer-token"],
679
+ json: values.json,
680
+ text: values.text,
681
+ noColor: values["no-color"],
682
+ })
683
+ );
684
+ }
685
+
686
+ case "logs": {
687
+ return cmdLogs(
688
+ axFromOptions({
689
+ dir,
690
+ url: values.url,
691
+ prod: values.prod,
692
+ team: values.team,
693
+ apiKey: values["api-key"],
694
+ slug: values.slug,
695
+ bearerToken: values["bearer-token"],
696
+ json: values.json,
697
+ once: values.once,
698
+ })
699
+ );
700
+ }
701
+
702
+ case "sessions": {
703
+ return cmdSessions(
704
+ axFromOptions({
705
+ dir,
706
+ url: values.url,
707
+ prod: values.prod,
708
+ team: values.team,
709
+ apiKey: values["api-key"],
710
+ slug: values.slug,
711
+ bearerToken: values["bearer-token"],
712
+ json: values.json,
713
+ })
714
+ );
715
+ }
716
+
717
+ case "session": {
718
+ return cmdSession(
719
+ positionals[0],
720
+ axFromOptions({
721
+ dir,
722
+ url: values.url,
723
+ prod: values.prod,
724
+ team: values.team,
725
+ apiKey: values["api-key"],
726
+ slug: values.slug,
727
+ bearerToken: values["bearer-token"],
728
+ json: values.json,
729
+ text: values.text,
730
+ rawEvents: values["raw-events"],
731
+ })
732
+ );
733
+ }
734
+
735
+ case "playground": {
736
+ return cmdPlayground(
737
+ axFromOptions({
738
+ dir,
739
+ url: values.url,
740
+ prod: values.prod,
741
+ team: values.team,
742
+ apiKey: values["api-key"],
743
+ slug: values.slug,
744
+ bearerToken: values["bearer-token"],
745
+ sessionId: values["session-id"] ?? values.session,
746
+ print: values.print,
747
+ })
748
+ );
534
749
  }
535
750
 
536
751
  case "validate": {
@@ -645,7 +860,19 @@ async function main(argv: string[]): Promise<number> {
645
860
  return info.diagnostics.some((d) => d.severity === "error") ? 1 : 0;
646
861
  }
647
862
 
863
+ case "dev":
648
864
  case "serve": {
865
+ const serveDirResult = resolveServeDir({
866
+ command,
867
+ dir,
868
+ positionals,
869
+ dirFlagPassed: rest.includes("--dir"),
870
+ });
871
+ if (typeof serveDirResult !== "string") {
872
+ process.stderr.write(serveDirResult.error);
873
+ return 1;
874
+ }
875
+ const serveDir = serveDirResult;
649
876
  const port =
650
877
  values.port === undefined ? 3000 : Number.parseInt(values.port, 10);
651
878
  if (Number.isNaN(port) || port < 0 || port > 65535) {
@@ -668,44 +895,45 @@ async function main(argv: string[]): Promise<number> {
668
895
  );
669
896
  return 1;
670
897
  }
898
+ const dev = command === "dev" || values.dev === true;
899
+ const style = stdoutPalette();
671
900
  const serveOptions = {
672
901
  port,
673
- ...(values.host === undefined ? {} : { host: values.host }),
674
- ...(mode === undefined ? {} : { mode: mode as "single" | "multi" }),
675
- dev: values.dev,
676
- ...(values["api-key"] === undefined
677
- ? {}
678
- : { apiKey: values["api-key"] }),
679
- ...(values["state-root"] === undefined
680
- ? {}
681
- : { stateRoot: values["state-root"] }),
682
- ...(values["bearer-token"] === undefined
683
- ? {}
684
- : { authToken: values["bearer-token"] }),
685
- ...(values["allow-anonymous"] ? { allowAnonymous: true } : {}),
686
- ...(values["no-schedules"] ? { schedules: false } : {}),
687
- ...(values["no-playground"] ? { playground: false } : {}),
688
- ...(values["no-docs"] ? { docs: false } : {}),
689
- ...(values["public-url"] === undefined
690
- ? {}
691
- : { publicUrl: values["public-url"] }),
692
- ...(values["cursor-events"]
693
- ? { cursorEvents: { repos: values.repo ?? [] } }
694
- : {}),
902
+ host: values.host,
903
+ mode: mode as "single" | "multi" | undefined,
904
+ dev,
905
+ apiKey: values["api-key"],
906
+ stateRoot: values["state-root"],
907
+ authToken: values["bearer-token"],
908
+ allowAnonymous: values["allow-anonymous"] === true ? true : undefined,
909
+ allowAnonymousCursorGithub:
910
+ values["allow-anonymous-cursor-github"] === true ? true : undefined,
911
+ schedules: values["no-schedules"] === true ? false : undefined,
912
+ playground: values["no-playground"] === true ? false : undefined,
913
+ docs: values["no-docs"] === true ? false : undefined,
914
+ publicUrl: values["public-url"],
915
+ cursorEvents:
916
+ values["cursor-events"] === true
917
+ ? { repos: values.repo ?? [] }
918
+ : undefined,
919
+ // Soft boot logs (GitHub auth, etc.) stay secondary to the banner.
920
+ logger: (line: string) => {
921
+ process.stdout.write(`${style.dim(line)}\n`);
922
+ },
695
923
  };
696
924
  const enterToRestart = process.stdin.isTTY === true;
697
925
  const bannerOpts = {
698
926
  noPlayground: values["no-playground"] === true,
699
- dev: values.dev === true,
927
+ dev,
700
928
  bearerToken: values["bearer-token"] !== undefined,
701
929
  noSchedules: values["no-schedules"] === true,
702
930
  };
703
931
 
704
932
  const start = async (): Promise<AgentServeHandle> => {
705
- const next = await serve(dir, serveOptions);
933
+ const next = await serve(serveDir, serveOptions);
706
934
  printServeBanner(next, bannerOpts);
707
935
  if (enterToRestart) {
708
- process.stdout.write(" press Enter to restart\n");
936
+ process.stdout.write(style.dim(" press Enter to restart\n"));
709
937
  }
710
938
  return next;
711
939
  };
@@ -738,16 +966,22 @@ async function main(argv: string[]): Promise<number> {
738
966
  return;
739
967
  }
740
968
  restarting = true;
741
- process.stdout.write("\nrestarting…\n");
742
- void handle
743
- .close()
744
- .then(start)
969
+ // Close + re-serve reloads authored agent modules and respawns Vite.
970
+ // Hold the "restarting…" frame briefly so a fast close doesn't look
971
+ // like Enter did nothing.
972
+ clearTerminal();
973
+ process.stdout.write(style.dim("restarting…\n"));
974
+ void Promise.all([handle.close(), sleep(450)])
975
+ .then(() => {
976
+ clearTerminal();
977
+ return start();
978
+ })
745
979
  .then((next) => {
746
980
  handle = next;
747
981
  })
748
982
  .catch((error: unknown) => {
749
983
  process.stderr.write(
750
- `[agent-serve] restart failed: ${
984
+ `[agentkit] restart failed: ${
751
985
  error instanceof Error
752
986
  ? (error.stack ?? error.message)
753
987
  : String(error)
@@ -790,40 +1024,35 @@ function axFromOptions(
790
1024
  ): AxCliOptions {
791
1025
  return {
792
1026
  dir: partial.dir,
793
- ...(partial.cwd === undefined ? {} : { cwd: partial.cwd }),
794
- ...(partial.slug === undefined ? {} : { slug: partial.slug }),
795
- ...(partial.bearerToken === undefined
796
- ? {}
797
- : { bearerToken: partial.bearerToken }),
798
- ...(partial.stateRoot === undefined
799
- ? {}
800
- : { stateRoot: partial.stateRoot }),
801
- ...(partial.messages === undefined ? {} : { messages: partial.messages }),
802
- ...(partial.sessionId === undefined
803
- ? {}
804
- : { sessionId: partial.sessionId }),
805
- ...(partial.continuationToken === undefined
806
- ? {}
807
- : { continuationToken: partial.continuationToken }),
808
- ...(partial.timeoutMs === undefined
809
- ? {}
810
- : { timeoutMs: partial.timeoutMs }),
811
- ...(partial.events === undefined ? {} : { events: partial.events }),
812
- ...(partial.text === undefined ? {} : { text: partial.text }),
813
- ...(partial.json === undefined ? {} : { json: partial.json }),
814
- ...(partial.list === undefined ? {} : { list: partial.list }),
815
- ...(partial.verbose === undefined ? {} : { verbose: partial.verbose }),
816
- ...(partial.tags === undefined ? {} : { tags: partial.tags }),
817
- ...(partial.evalIds === undefined ? {} : { evalIds: partial.evalIds }),
818
- ...(partial.initTarget === undefined
819
- ? {}
820
- : { initTarget: partial.initTarget }),
821
- ...(partial.toolName === undefined ? {} : { toolName: partial.toolName }),
822
- ...(partial.toolInput === undefined
823
- ? {}
824
- : { toolInput: partial.toolInput }),
825
- ...(partial.url === undefined ? {} : { url: partial.url }),
826
- ...(partial.stream === undefined ? {} : { stream: partial.stream }),
1027
+ cwd: partial.cwd,
1028
+ slug: partial.slug,
1029
+ bearerToken: partial.bearerToken,
1030
+ stateRoot: partial.stateRoot,
1031
+ messages: partial.messages,
1032
+ sessionId: partial.sessionId,
1033
+ resume: partial.resume,
1034
+ continuationToken: partial.continuationToken,
1035
+ timeoutMs: partial.timeoutMs,
1036
+ events: partial.events,
1037
+ text: partial.text,
1038
+ json: partial.json,
1039
+ list: partial.list,
1040
+ verbose: partial.verbose,
1041
+ tags: partial.tags,
1042
+ evalIds: partial.evalIds,
1043
+ initTarget: partial.initTarget,
1044
+ toolName: partial.toolName,
1045
+ toolInput: partial.toolInput,
1046
+ url: partial.url,
1047
+ prod: partial.prod,
1048
+ team: partial.team,
1049
+ apiKey: partial.apiKey,
1050
+ fetchImpl: partial.fetchImpl,
1051
+ stream: partial.stream,
1052
+ noColor: partial.noColor,
1053
+ once: partial.once,
1054
+ rawEvents: partial.rawEvents,
1055
+ print: partial.print,
827
1056
  };
828
1057
  }
829
1058
 
@@ -862,42 +1091,6 @@ function parseTimeoutMs(value: string | undefined): number | undefined {
862
1091
  return n;
863
1092
  }
864
1093
 
865
- async function chatJson(args: {
866
- baseUrl: string;
867
- message?: string;
868
- bearerToken?: string;
869
- text?: boolean;
870
- }): Promise<number> {
871
- if (args.message === undefined) {
872
- process.stderr.write("chat --json requires --message\n");
873
- return 2;
874
- }
875
- const result = await runSession({
876
- baseUrl: args.baseUrl,
877
- messages: [args.message],
878
- ...(args.bearerToken === undefined
879
- ? {}
880
- : { bearerToken: args.bearerToken }),
881
- });
882
- if (args.text) {
883
- process.stdout.write(formatTrajectoryText(result.trajectory));
884
- } else {
885
- console.log(
886
- JSON.stringify(
887
- {
888
- ok: result.ok,
889
- sessionId: result.sessionId,
890
- continuationToken: result.continuationToken ?? null,
891
- trajectory: result.trajectory,
892
- },
893
- null,
894
- 2
895
- )
896
- );
897
- }
898
- return result.ok ? 0 : 1;
899
- }
900
-
901
1094
  /**
902
1095
  * Load mounts the same way `serve` does (multi-agent layout by default).
903
1096
  */
@@ -918,6 +1111,42 @@ function isEnterOnly(text: string): boolean {
918
1111
  return text.length > 0 && [...text].every((ch) => ch === "\n" || ch === "\r");
919
1112
  }
920
1113
 
1114
+ function sleep(ms: number): Promise<void> {
1115
+ return new Promise((resolve) => {
1116
+ setTimeout(resolve, ms);
1117
+ });
1118
+ }
1119
+
1120
+ /**
1121
+ * `dev [path]` takes a positional project root; `serve` keeps `--dir` only.
1122
+ * Reject mixing a positional with an explicit `--dir`, and extra args on `dev`.
1123
+ */
1124
+ function resolveServeDir(args: {
1125
+ command: string;
1126
+ dir: string;
1127
+ positionals: string[];
1128
+ dirFlagPassed: boolean;
1129
+ }): string | { error: string } {
1130
+ if (args.command !== "dev") {
1131
+ return args.dir;
1132
+ }
1133
+ if (args.positionals.length > 1) {
1134
+ return {
1135
+ error: `${CLI} dev: unexpected arguments: ${args.positionals.slice(1).join(" ")}\n`,
1136
+ };
1137
+ }
1138
+ const positionalDir = args.positionals[0];
1139
+ if (positionalDir === undefined) {
1140
+ return args.dir;
1141
+ }
1142
+ if (args.dirFlagPassed && args.dir !== positionalDir) {
1143
+ return {
1144
+ error: `${CLI} dev: pass a path as a positional or --dir, not both\n`,
1145
+ };
1146
+ }
1147
+ return positionalDir;
1148
+ }
1149
+
921
1150
  function printServeBanner(
922
1151
  handle: AgentServeHandle,
923
1152
  opts: {
@@ -927,57 +1156,66 @@ function printServeBanner(
927
1156
  noSchedules: boolean;
928
1157
  }
929
1158
  ): void {
930
- const multi = handle.agents.length > 1 || handle.agents[0]?.slug !== "";
931
- if (multi) {
932
- process.stdout.write(
933
- `${handle.agents.length} agents listening on ${handle.url}\n`
934
- );
935
- if (!opts.noPlayground) {
936
- process.stdout.write(` index: ${handle.url}/\n`);
937
- }
938
- for (const agent of handle.agents) {
939
- const info = projectInfo(agent.project);
940
- const suffix = opts.noPlayground
941
- ? `${agent.url}/v1/session`
942
- : `${agent.url}/playground`;
943
- process.stdout.write(` /${agent.slug} ${info.name} — ${suffix}\n`);
944
- }
1159
+ const c = stdoutPalette();
1160
+ const agents = handle.agents;
1161
+ if (agents.length > 1) {
1162
+ process.stdout.write(`${agents.length} agents listening\n`);
945
1163
  } else {
946
- const info = projectInfo(handle.project);
947
- process.stdout.write(`${info.name} listening on ${handle.url}\n`);
948
- if (!opts.noPlayground) {
949
- process.stdout.write(` playground: ${handle.url}/playground\n`);
950
- }
951
- process.stdout.write(` POST ${handle.url}/v1/session\n`);
952
- process.stdout.write(` GET ${handle.url}/v1/session/:sessionId/stream\n`);
953
- for (const channel of info.channels) {
954
- if (channel.id === "http") {
955
- continue;
1164
+ const info = projectInfo(agents[0]?.project ?? handle.project);
1165
+ process.stdout.write(`${info.name} listening\n`);
1166
+ }
1167
+
1168
+ const playgroundUrl = resolvePlaygroundBannerUrl(handle, opts.noPlayground);
1169
+ if (playgroundUrl !== undefined) {
1170
+ process.stdout.write(` playground ${c.cyan(playgroundUrl)}\n`);
1171
+ }
1172
+
1173
+ // Dev is playground-first (Vite proxies the API). Keep API/route detail for
1174
+ // plain `serve`, where operators often curl the HTTP surface directly.
1175
+ if (!opts.dev) {
1176
+ process.stdout.write(c.dim(` api ${handle.url}\n`));
1177
+ if (agents.length > 1 || agents[0]?.slug !== "") {
1178
+ for (const agent of agents) {
1179
+ const info = projectInfo(agent.project);
1180
+ process.stdout.write(c.dim(` /${agent.slug} ${info.name}\n`));
956
1181
  }
957
- for (const route of channel.routes) {
958
- process.stdout.write(` ${route.method} ${handle.url}${route.url}\n`);
1182
+ } else {
1183
+ const info = projectInfo(handle.project);
1184
+ process.stdout.write(c.dim(` POST ${handle.url}/v1/session\n`));
1185
+ process.stdout.write(
1186
+ c.dim(` GET ${handle.url}/v1/session/:sessionId/stream\n`)
1187
+ );
1188
+ for (const channel of info.channels) {
1189
+ if (channel.id === "http") {
1190
+ continue;
1191
+ }
1192
+ for (const route of channel.routes) {
1193
+ process.stdout.write(
1194
+ c.dim(` ${route.method} ${handle.url}${route.url}\n`)
1195
+ );
1196
+ }
959
1197
  }
960
- }
961
- if (info.schedules.length > 0) {
962
- const scheduleMode = opts.dev
963
- ? "dev mode: dispatch with POST /v1/dev/schedules/:scheduleId"
964
- : opts.noSchedules
1198
+ if (info.schedules.length > 0) {
1199
+ const scheduleMode = opts.noSchedules
965
1200
  ? "disabled"
966
1201
  : "running on cron cadence (UTC)";
967
- process.stdout.write(
968
- ` schedules: ${info.schedules.map((s) => s.name).join(", ")} — ${scheduleMode}\n`
969
- );
1202
+ process.stdout.write(
1203
+ c.dim(
1204
+ ` schedules: ${info.schedules.map((s) => s.name).join(", ")} — ${scheduleMode}\n`
1205
+ )
1206
+ );
1207
+ }
1208
+ }
1209
+ if (handle.docsUrl !== undefined) {
1210
+ process.stdout.write(c.dim(` docs ${handle.docsUrl}\n`));
970
1211
  }
971
1212
  }
972
- if (handle.playgroundDevUrl !== undefined) {
973
- process.stdout.write(` playground (HMR): ${handle.playgroundDevUrl}\n`);
974
- }
975
- if (handle.docsUrl !== undefined) {
976
- process.stdout.write(` docs: ${handle.docsUrl}\n`);
977
- }
1213
+
978
1214
  if (opts.bearerToken) {
979
1215
  process.stdout.write(
980
- " auth: bearer token required on API routes (playground has a token field)\n"
1216
+ c.dim(
1217
+ " auth: bearer token required on API routes (playground has a token field)\n"
1218
+ )
981
1219
  );
982
1220
  }
983
1221
  if (
@@ -989,11 +1227,33 @@ function printServeBanner(
989
1227
  )
990
1228
  ) {
991
1229
  process.stdout.write(
992
- ` github: dev accepts unsigned loopback deliveries (${CLI} github forward works without a secret; set GITHUB_WEBHOOK_SECRET to verify signatures)\n`
1230
+ c.dim(
1231
+ ` github: dev accepts unsigned loopback deliveries (${CLI} github forward works without a secret; set GITHUB_WEBHOOK_SECRET to verify signatures)\n`
1232
+ )
993
1233
  );
994
1234
  }
995
1235
  }
996
1236
 
1237
+ /** Prefer the Vite playground URL in --dev; otherwise the static SPA path. */
1238
+ function resolvePlaygroundBannerUrl(
1239
+ handle: AgentServeHandle,
1240
+ noPlayground: boolean
1241
+ ): string | undefined {
1242
+ if (noPlayground) {
1243
+ return undefined;
1244
+ }
1245
+ if (handle.playgroundDevUrl !== undefined) {
1246
+ return handle.playgroundDevUrl.replace(/\/$/, "");
1247
+ }
1248
+ if (handle.agents.length === 1) {
1249
+ return `${handle.agents[0]!.url}/playground`;
1250
+ }
1251
+ if (handle.agents.length > 1) {
1252
+ return handle.url;
1253
+ }
1254
+ return undefined;
1255
+ }
1256
+
997
1257
  function formatModel(model: unknown): string {
998
1258
  if (model === undefined) {
999
1259
  return "(unset)";
@@ -1045,7 +1305,7 @@ function installTransportErrorGuards(): void {
1045
1305
  const log = (label: string, reason: unknown): void => {
1046
1306
  const text = reason instanceof Error ? reason.message : String(reason);
1047
1307
  process.stderr.write(
1048
- `[agent-serve] ${label} (server stays up): ${text.slice(0, 400)}\n`
1308
+ `[agentkit] ${label} (server stays up): ${text.slice(0, 400)}\n`
1049
1309
  );
1050
1310
  };
1051
1311
  process.on("unhandledRejection", (reason) => {
@@ -1061,7 +1321,7 @@ function installTransportErrorGuards(): void {
1061
1321
  return;
1062
1322
  }
1063
1323
  process.stderr.write(
1064
- `[agent-serve] uncaughtException: ${error.stack ?? error.message}\n`
1324
+ `[agentkit] uncaughtException: ${error.stack ?? error.message}\n`
1065
1325
  );
1066
1326
  process.exit(1);
1067
1327
  });