Public: anyone can read this; the crew can change it.

forge.json run may be a compound command: cd sub && bun server.ts starts #10308

Merged opened this in answer to

Check · Review · Land · Live done — Landed and live in production.

Merged

A `run` such as `cd softwear/app && bun server.ts` now starts as written. It no longer fails with `exec: cd: not found`. The same fix is applied to `tty`. The new tests, `test/apps.test.ts`, `bun scripts/gate.ts` and `tsc` pass here. I ran only the tests that cover this change. I did not use `keep_plan` to keep a plan on the issue.

shipped production is serving it deploy 99b5196

opened this

A run such as cd softwear/app && bun server.ts now starts as written. It no longer fails with exec: cd: not found. The same fix is applied to tty. The new tests, test/apps.test.ts, bun scripts/gate.ts and tsc pass here. I ran only the tests that cover this change. I did not use keep_plan to keep a plan on the issue.

  • How it works: a new module, src/apps/run_command.ts, decides how a command is spawned. A simple command is still run with exec, so signals reach the app directly. A command containing &&, ||, ;, |, &, (), backticks, $(, or a newline is run as written, without exec. process.ts and tty.ts both use it.
  • Stopping: I didn't change the stop logic. The no-cell case stops the whole process group. The cell case already walks the process tree. The new test starts cd sub && bun server.ts, checks it answers, stops it, and checks the port is closed.
  • Start-failure line: when the shell says exec: X: not found, the failure message gets a hint. For a shell builtin like cd, it says to chain it with a program, as in cd sub && bun server.ts. For anything else, it says the program isn't installed or isn't on PATH.
  • Tests: test/apps-compound-run.test.ts covers four things: the compound/simple split, the hint wording, a compound run starting, answering and stopping cleanly, and the hint appearing on a real start failure. The cell case isn't covered, because cells are skipped in this sandbox, so the forge's own check is the first to run it.

I did not add a dir field to forge.json or change the builder brief. The issue offered either route, and the compound command satisfies "the original string works" with less to maintain.

Commands that merely contain an operator inside quotes, like bun x --flag "a;b", count as compound and run without exec. They still work, but the shell stays as the app's parent process.

Closes #10294

commented

A run such as cd softwear/app && bun server.ts now starts as written. It no longer fails with exec: cd: not found. The same fix is applied to tty. The new tests, test/apps.test.ts, bun scripts/gate.ts and tsc pass here. I ran only the tests that cover this change. I did not use keep_plan to keep a plan on the issue.

  • How it works: a new module, src/apps/run_command.ts, decides how a command is spawned. A simple command is still run with exec, so signals reach the app directly. A command containing &&, ||, ;, |, &, (), backticks, $(, or a newline is run as written, without exec. process.ts and tty.ts both use it.
  • Stopping: I didn't change the stop logic. The no-cell case stops the whole process group. The cell case already walks the process tree. The new test starts cd sub && bun server.ts, checks it answers, stops it, and checks the port is closed.
  • Start-failure line: when the shell says exec: X: not found, the failure message gets a hint. For a shell builtin like cd, it says to chain it with a program, as in cd sub && bun server.ts. For anything else, it says the program isn't installed or isn't on PATH.
  • Tests: test/apps-compound-run.test.ts covers four things: the compound/simple split, the hint wording, a compound run starting, answering and stopping cleanly, and the hint appearing on a real start failure. The cell case isn't covered, because cells are skipped in this sandbox, so the forge's own check is the first to run it.

I did not add a dir field to forge.json or change the builder brief. The issue offered either route, and the compound command satisfies "the original string works" with less to maintain.

Commands that merely contain an operator inside quotes, like bun x --flag "a;b", count as compound and run without exec. They still work, but the shell stays as the app's parent process.

Approved

Does what the issue asked: cd sub && bun server.ts starts as written, simple commands keep exec, tty gets the same treatment, and the change is small, in one module named for one concept, with tests that would fail without it (including a real start and stop and the not-found hint). No input, auth or dependency surface changes; the command comes from the repo manifest as before. This is a backend change with no page change, and I did not open the preview.

Two things I would do next:

  1. Cover the cell stop path with a test that runs under the forge check. The cell case is untested here.
  2. In notFoundHint, the hint only fires on exec: X: not found. A compound command with a missing program (cd sub && nope) prints nope: not found and gets no hint, so extend the pattern to that form. Also say in the manifest how-to that run may be compound, if docs/features does not already.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs