Shell + jobs API
Run shell commands programmatically with cancellation, timeouts, and SSE streaming.
Endpoints
| Endpoint | Purpose |
|---|---|
POST /api/shell/run | Execute a shell command, stream stdout/stderr as SSE. |
POST /api/shell/test | Auto-detect and run the project's test framework. |
POST /api/shell/suggest | LLM-powered command suggestion for a goal. |
GET /api/shell/jobs | List in-flight shell jobs. |
POST /api/shell/cancel/<job_id> | Cancel a running job. |
GET /api/shell/recent | List recent commands (for re-run). |
Run a command
POST /api/shell/run
{
"cmd": "pytest -k test_auth",
"cwd": "<workspace-relative path, defaults to root>",
"timeout": 300
}
Returns text/event-stream with frames:
data: {"type":"stdout","line":"…"}
data: {"type":"stderr","line":"…"}
data: {"type":"exit","code":0}
Hard timeout 300 seconds. Long-running processes (dev servers) should use the terminal PTY instead.
Friendly detector
shell_friendly_detector reads package.json scripts, Makefile targets, .env keys, and common CLI conventions to surface "things you probably want to run":
- "Run tests" →
pytestornpm testorcargo test - "Start dev server" →
npm run devorflask runorcargo run - "Lint" →
eslint .orruff check . - "Build" →
npm run buildormake buildorcargo build
These appear as buttons in the terminal panel and as palette commands.
Test runner
POST /api/shell/test auto-detects the framework (pytest, jest, mocha, vitest, go test, cargo test) and runs it. Output is parsed for pass/fail counts.
Suggest
POST /api/shell/suggest:
{ "goal": "find all unused imports" }
Returns:
{ "command": "ruff check . --select=F401", "explanation": "..." }
The user always confirms before running.
Free-port substitution
Shell command templates can use $FREE_PORT. When KrowForge spawns the process, it scans for an open port and substitutes it. Useful for:
npm run dev -- --port $FREE_PORT
The chosen port is logged so you can navigate to http://localhost:<port>.
Job listing & cancel
GET /api/shell/jobs returns active jobs:
[{ "job_id": "j_…", "cmd": "pytest", "started_at": "…", "pid": 12345 }]
POST /api/shell/cancel/j_… sends SIGTERM, waits 3 s, then SIGKILL.
Recent
GET /api/shell/recent returns the last 50 commands (per workspace). Used by the terminal's "↑ Recent" picker.