unfold-deploy 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.0 (unreleased)
3
+ ## 0.2.0 (2026-11-05)
4
+
5
+ - `unfold gcloud`: Cloud Run deploys (`gcloud run deploy`) as Prepare → Build → Deploy → Live, with build and revision log links, troubleshooting links, and readable errors from gcloud's HTML error pages.
6
+ - `unfold claude "<task>"` and `unfold codex "<task>"`: run Claude Code or Codex non-interactively and show Start → Explore → Change → Verify → Done, with files changed, checks run, the final answer and cost or tokens. Verify is only confirmed by a passing check.
7
+ - Providers that emit JSON events are shown as readable lines instead of raw JSON; their saved runs replay from recorded events.
8
+ - New demos: `gcloud success`, `gcloud deploy-failure`, `claude success`, `codex checks-failing` (`unfold demo <provider> <name>`).
9
+ - Summary headlines and labels now come from the provider ("Deployed", "Done", …).
10
+
11
+ ## 0.1.0 (2026-11-05)
4
12
 
5
13
  First release.
6
14
 
package/README.md CHANGED
@@ -2,7 +2,14 @@
2
2
 
3
3
  **Watch what happens after you hit Enter.**
4
4
 
5
- Unfold wraps a CLI command and shows what it's doing as a flow, right in your terminal. The command's own output and prompts work exactly as before, and a small panel pinned to the bottom of the terminal tracks each stage as it happens. It starts with one workflow: a Vercel preview deploy.
5
+ Unfold wraps a CLI command and shows what it's doing as a flow, right in your terminal. The command's own output and prompts work exactly as before, and a small panel pinned to the bottom of the terminal tracks each stage as it happens.
6
+
7
+ | Command | Wraps | Flow |
8
+ | --- | --- | --- |
9
+ | `unfold vercel` | `vercel deploy` | Prepare → Upload → Build → Preview |
10
+ | `unfold gcloud` | `gcloud run deploy` (Cloud Run) | Prepare → Build → Deploy → Live |
11
+ | `unfold claude "<task>"` | Claude Code, non-interactive | Start → Explore → Change → Verify → Done |
12
+ | `unfold codex "<task>"` | Codex CLI, non-interactive | Start → Explore → Change → Verify → Done |
6
13
 
7
14
  ```
8
15
  Vercel CLI 65.2.0
@@ -35,15 +42,19 @@ npm install -g unfold-deploy
35
42
 
36
43
  The package is `unfold-deploy`; the command is `unfold`. To try it without installing, prefix commands with `npx unfold-deploy` (for example `npx unfold-deploy demo success`).
37
44
 
38
- ## Try it without a Vercel account
45
+ ## Try it without an account
39
46
 
40
47
  The demos play recorded terminal output through the same pipeline a real run uses:
41
48
 
42
49
  ```sh
43
- unfold demo success # a preview deploy that succeeds
44
- unfold demo build-failure # the build fails on a TypeScript error
45
- unfold demo interrupted # Ctrl+C while Vercel is building
46
- unfold show # explore the run you just watched
50
+ unfold demo success # Vercel: a preview deploy that succeeds
51
+ unfold demo build-failure # Vercel: the build fails on a TypeScript error
52
+ unfold demo interrupted # Vercel: Ctrl+C while building
53
+ unfold demo gcloud success # Cloud Run: a source deploy that goes live
54
+ unfold demo gcloud deploy-failure # Cloud Run: the container never listens on $PORT
55
+ unfold demo claude success # Claude Code fixes a failing test and confirms it
56
+ unfold demo codex checks-failing # Codex finishes, but the tests still fail
57
+ unfold show # explore the run you just watched
47
58
  ```
48
59
 
49
60
  Add `--speed 2` to play faster. Press Ctrl+C during any demo to see the interrupted state.
@@ -67,6 +78,31 @@ unfold vercel --yes # any vercel deploy flags pass straight through
67
78
 
68
79
  Unfold options: `--fix claude|codex` (see below), `--no-panel` (no pinned panel, summary only), `--speed <n>` (demos and replays).
69
80
 
81
+ ## Deploy to Cloud Run
82
+
83
+ You need the Google Cloud CLI, logged in (`gcloud auth login`) with a project set. From your service's folder:
84
+
85
+ ```sh
86
+ unfold gcloud --source . --region us-central1 # runs: gcloud run deploy --source . --region us-central1
87
+ unfold gcloud my-api --image us-docker.pkg.dev/… # prebuilt image: no Build stage
88
+ ```
89
+
90
+ Everything after `unfold gcloud` goes to `gcloud run deploy`, and its questions (service name, region, unauthenticated access) still appear in your terminal. On failure the summary shows the error, the Cloud Build or revision logs link, and the troubleshooting link gcloud printed. HTML error pages gcloud sometimes prints are reduced to their readable sentence.
91
+
92
+ ## Watch a coding agent: Claude Code and Codex
93
+
94
+ Unfold runs the agent in its non-interactive mode, which reports every step as a structured event, and shows it as a flow: what it read (**Explore**), which files it edited (**Change**), whether checks such as `npm test` or `tsc` passed (**Verify**), and its final answer (**Done**). The summary lists the files changed, the answer, and the cost or token use.
95
+
96
+ ```sh
97
+ unfold claude "fix the failing test" --allowedTools Read Edit "Bash(npm test)"
98
+ unfold claude "add input validation to the signup form" --permission-mode acceptEdits
99
+ unfold codex "fix the failing test" --sandbox workspace-write
100
+ ```
101
+
102
+ - Non-interactive agents can't stop to ask for permission. Give Claude Code the tools it needs with `--allowedTools` or `--permission-mode acceptEdits`; give Codex write access with `--sandbox workspace-write`. Denied tools are listed in the summary.
103
+ - **Verify is only confirmed when a check passes.** If the agent never runs one, or the last one failed, Verify stays `?` with the reason, even when the agent says it's done.
104
+ - Edits go straight to your working tree. Review them with `git diff`.
105
+
70
106
  ### Browser view (optional)
71
107
 
72
108
  Nothing is served unless you ask for it. Add `--web` to also open the flow in a local browser page, for example `unfold vercel --web` or `unfold show --web`. The page is served on `127.0.0.1` only. With `--web` you can also use `--no-open`, `--once` (exit when the run ends) and `--port <n>` (default 4317).
@@ -99,7 +135,8 @@ Try it without an account: `unfold demo build-failure`.
99
135
 
100
136
  ## Troubleshooting
101
137
 
102
- - **"Could not find vercel on your PATH"**: install it with `npm i -g vercel`, then run `vercel login`.
138
+ - **"Could not find vercel / gcloud / claude / codex on your PATH"**: install that CLI and log in to it first; Unfold prints the install command.
139
+ - **Agent stopped without changing anything**: it probably wasn't allowed to. Check "Permission denied" in the summary and allow the tool (see above).
103
140
  - **Stuck at a Vercel question**: Unfold passes your keystrokes straight to the Vercel CLI, so answer it as usual. In scripts, pass `--yes` and `--scope <team>`.
104
141
  - **"Unfold didn't recognize any of this output"**: your Vercel CLI may print a format Unfold doesn't know yet. The deploy itself is unaffected. Please open an issue and include your `vercel --version`.
105
142
  - **No live panel**: the panel needs a terminal at least 50×12 and the `node-pty` package. On Linux without build tools, node-pty may not install; Unfold then runs the CLI through the system `script` command, prints only the summary, and keeps prompts working. `UNFOLD_TERMINAL=script` or `UNFOLD_TERMINAL=pipe` forces a fallback, and `--no-panel` turns the panel off.
@@ -0,0 +1,72 @@
1
+ {
2
+ "provider": "claude",
3
+ "description": "Claude Code fixes a failing test and confirms it with npm test.",
4
+ "command": [
5
+ "claude",
6
+ "-p",
7
+ "Fix the failing test",
8
+ "--permission-mode",
9
+ "acceptEdits",
10
+ "--output-format",
11
+ "stream-json",
12
+ "--verbose"
13
+ ],
14
+ "cwd": "/home/dev/tiny-app",
15
+ "exitCode": 0,
16
+ "signal": null,
17
+ "interrupted": false,
18
+ "chunks": [
19
+ {
20
+ "t": 300,
21
+ "d": "{\"type\":\"system\",\"subtype\":\"init\",\"cwd\":\"/home/dev/tiny-app\",\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\",\"model\":\"claude-opus-5-5\",\"permissionMode\":\"acceptEdits\",\"claude_code_version\":\"2.1.292\",\"tools\":[\"Read\",\"Edit\",\"Bash\"]}\r\n"
22
+ },
23
+ {
24
+ "t": 1800,
25
+ "d": "{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"text\",\"text\":\"I'll look at the code and run the tests first.\"}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
26
+ },
27
+ {
28
+ "t": 2700,
29
+ "d": "{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"tool_use\",\"id\":\"t1\",\"name\":\"Read\",\"input\":{\"file_path\":\"/home/dev/tiny-app/sum.js\"}}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
30
+ },
31
+ {
32
+ "t": 3000,
33
+ "d": "{\"type\":\"user\",\"message\":{\"content\":[{\"type\":\"tool_result\",\"tool_use_id\":\"t1\",\"content\":\"1\\texport function sum(a, b) {\\n2\\t return a - b;\\n3\\t}\\n\",\"is_error\":false}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
34
+ },
35
+ {
36
+ "t": 4200,
37
+ "d": "{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"tool_use\",\"id\":\"t2\",\"name\":\"Bash\",\"input\":{\"command\":\"npm test\",\"description\":\"Run the tests\"}}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
38
+ },
39
+ {
40
+ "t": 6000,
41
+ "d": "{\"type\":\"user\",\"message\":{\"content\":[{\"type\":\"tool_result\",\"tool_use_id\":\"t2\",\"content\":\"Exit code 1\\nAssertionError [ERR_ASSERTION]: Expected values to be strictly equal:\\n\\n-1 !== 5\\n\",\"is_error\":true}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
42
+ },
43
+ {
44
+ "t": 7400,
45
+ "d": "{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"text\",\"text\":\"`sum` subtracts instead of adding. Fixing it.\"}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
46
+ },
47
+ {
48
+ "t": 8500,
49
+ "d": "{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"tool_use\",\"id\":\"t3\",\"name\":\"Edit\",\"input\":{\"file_path\":\"/home/dev/tiny-app/sum.js\",\"old_string\":\"return a - b;\",\"new_string\":\"return a + b;\"}}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
50
+ },
51
+ {
52
+ "t": 8800,
53
+ "d": "{\"type\":\"user\",\"message\":{\"content\":[{\"type\":\"tool_result\",\"tool_use_id\":\"t3\",\"content\":\"The file /home/dev/tiny-app/sum.js has been updated.\",\"is_error\":false}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
54
+ },
55
+ {
56
+ "t": 9700,
57
+ "d": "{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"tool_use\",\"id\":\"t4\",\"name\":\"Bash\",\"input\":{\"command\":\"npm test\",\"description\":\"Run the tests again\"}}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
58
+ },
59
+ {
60
+ "t": 11400,
61
+ "d": "{\"type\":\"user\",\"message\":{\"content\":[{\"type\":\"tool_result\",\"tool_use_id\":\"t4\",\"content\":\"> tiny-app@1.0.0 test\\n> node test.js\\n\\nok\\n\",\"is_error\":false}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
62
+ },
63
+ {
64
+ "t": 12600,
65
+ "d": "{\"type\":\"assistant\",\"message\":{\"content\":[{\"type\":\"text\",\"text\":\"Fixed `sum` in sum.js: it returned `a - b` instead of `a + b`. `npm test` now passes.\"}]},\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
66
+ },
67
+ {
68
+ "t": 12800,
69
+ "d": "{\"type\":\"result\",\"subtype\":\"success\",\"is_error\":false,\"duration_ms\":13800,\"num_turns\":6,\"result\":\"Fixed `sum` in sum.js: it returned `a - b` instead of `a + b`. `npm test` now passes.\",\"total_cost_usd\":0.1876,\"permission_denials\":[],\"session_id\":\"7b1c2d3e-4f50-4a6b-8c7d-9e0f1a2b3c4d\"}\r\n"
70
+ }
71
+ ]
72
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "provider": "codex",
3
+ "description": "Codex edits a date helper, but the tests still fail when it stops.",
4
+ "command": [
5
+ "codex",
6
+ "exec",
7
+ "--json",
8
+ "Fix the time zone bug in startOfDay",
9
+ "--sandbox",
10
+ "workspace-write"
11
+ ],
12
+ "cwd": "/home/dev/tiny-app",
13
+ "exitCode": 0,
14
+ "signal": null,
15
+ "interrupted": false,
16
+ "chunks": [
17
+ {
18
+ "t": 300,
19
+ "d": "{\"type\":\"thread.started\",\"thread_id\":\"01a1ae40-5b6c-7d8e-9f01-23456789abcd\"}\r\n"
20
+ },
21
+ {
22
+ "t": 400,
23
+ "d": "{\"type\":\"turn.started\"}\r\n"
24
+ },
25
+ {
26
+ "t": 2600,
27
+ "d": "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_0\",\"type\":\"agent_message\",\"text\":\"I'll read the date helper and its tests, then fix the time zone bug.\"}}\r\n"
28
+ },
29
+ {
30
+ "t": 3500,
31
+ "d": "{\"type\":\"item.started\",\"item\":{\"id\":\"item_1\",\"type\":\"command_execution\",\"command\":\"/bin/zsh -lc \\\"cat src/dates.js test/dates.test.js\\\"\",\"aggregated_output\":\"\",\"exit_code\":null,\"status\":\"in_progress\"}}\r\n"
32
+ },
33
+ {
34
+ "t": 3800,
35
+ "d": "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_1\",\"type\":\"command_execution\",\"command\":\"/bin/zsh -lc \\\"cat src/dates.js test/dates.test.js\\\"\",\"aggregated_output\":\"export function startOfDay(d) { … }\\n\",\"exit_code\":0,\"status\":\"completed\"}}\r\n"
36
+ },
37
+ {
38
+ "t": 6400,
39
+ "d": "{\"type\":\"item.started\",\"item\":{\"id\":\"item_2\",\"type\":\"file_change\",\"changes\":[{\"path\":\"/home/dev/tiny-app/src/dates.js\",\"kind\":\"update\"}],\"status\":\"in_progress\"}}\r\n"
40
+ },
41
+ {
42
+ "t": 6600,
43
+ "d": "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_2\",\"type\":\"file_change\",\"changes\":[{\"path\":\"/home/dev/tiny-app/src/dates.js\",\"kind\":\"update\"}],\"status\":\"completed\"}}\r\n"
44
+ },
45
+ {
46
+ "t": 7400,
47
+ "d": "{\"type\":\"item.started\",\"item\":{\"id\":\"item_3\",\"type\":\"command_execution\",\"command\":\"/bin/zsh -lc \\\"npm test\\\"\",\"aggregated_output\":\"\",\"exit_code\":null,\"status\":\"in_progress\"}}\r\n"
48
+ },
49
+ {
50
+ "t": 9800,
51
+ "d": "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_3\",\"type\":\"command_execution\",\"command\":\"/bin/zsh -lc \\\"npm test\\\"\",\"aggregated_output\":\"> tiny-app@1.0.0 test\\n> node --test\\n\\n✖ startOfDay keeps the local date (2.1ms)\\n AssertionError: Expected \\\"2026-11-05\\\" but got \\\"2026-11-04\\\"\\n\\nℹ tests 6 pass 5 fail 1\\n\",\"exit_code\":1,\"status\":\"failed\"}}\r\n"
52
+ },
53
+ {
54
+ "t": 12400,
55
+ "d": "{\"type\":\"item.completed\",\"item\":{\"id\":\"item_4\",\"type\":\"agent_message\",\"text\":\"I changed startOfDay to use local time, but one test still fails: it expects 2026-11-05 and gets 2026-11-04, so the test itself may assume UTC. Can you confirm which time zone the dates should use?\"}}\r\n"
56
+ },
57
+ {
58
+ "t": 12600,
59
+ "d": "{\"type\":\"turn.completed\",\"usage\":{\"input_tokens\":64210,\"cached_input_tokens\":51200,\"output_tokens\":812}}\r\n"
60
+ }
61
+ ]
62
+ }