---
title: "Lifecycle hooks, server mode, and auto-PR"
date: "2026-03-08"
---

## Lifecycle hooks

You can now intercept tool calls at three points during agent execution: before a tool runs (`PreToolUse`), after it succeeds (`PostToolUse`), and after it fails (`PostToolUseFailure`). Each hook receives the tool name and arguments, and can modify, skip, or block the call. This makes it possible to enforce project conventions — like auto-formatting after file writes — or add guardrails without modifying agent prompts.

```toml title="fabro.toml"
[[hooks]]
event = "PostToolUse"
tool = "write"
command = "cargo fmt"
```

## Server mode for `fabro exec`

`fabro exec` can now run as a long-lived server that proxies requests through a `/completions` endpoint. Instead of running a single agent session and exiting, server mode keeps the agent process alive and accepts Anthropic-style streaming requests over HTTP. This enables integrating Fabro agents into applications that speak the standard completions API.

```bash
fabro exec --server --port 8080
```

## Auto-PR on workflow completion

Workflows can now automatically open a GitHub pull request when a run completes successfully. Fabro creates the PR from the agent's working branch with the run summary as the description. No extra scripting or post-run steps needed — just enable the option in your run configuration.

<Warning>
**Breaking: CLI commands renamed.** `fabro run start` is now `fabro run`, and `fabro agent` is now `fabro exec`. The old command names no longer work.

To migrate, update any scripts or aliases:
1. Replace `fabro run start` with `fabro run`
2. Replace `fabro agent` with `fabro exec`
</Warning>

## More

<Accordion title="API">
- Renamed `/runs/{id}/compare` to `/runs/{id}/files` with standard paginated response
- Added `POST /runs/{id}/pause` and `POST /runs/{id}/unpause` endpoints
- Added `POST /completions` endpoint with Anthropic-style SSE streaming
- Removed `List Projects` and `List Branches` endpoints
</Accordion>

<Accordion title="CLI">
- Added `--goal-file` flag to `fabro run` for reading goal from a file instead of inline text
- MCP servers can now be configured in TOML via `cli.toml` instead of JSON
- `verbose = true` in `cli.toml` defaults to verbose output without needing `-v`
- `goal` is now optional in run config TOML — precedence is CLI `--goal` > TOML `goal` > DOT graph attribute
- Configurable git author identity for checkpoint commits via `[git.author]`
- Added `[log]` config section to `server.toml` and `cli.toml` for log level and format control
</Accordion>

<Accordion title="Workflows">
- Script nodes now execute inside the configured sandbox instead of on the host — fixes issues where agents edited files in the sandbox but lint/test commands ran on the host
- Artifact collection is now opt-in via `[artifacts]` config with custom include globs, eliminating ~30s file scans per stage when not needed
- Workflow runs now fail immediately on git checkpoint commit failure instead of silently continuing
- GitHub webhook listener via Tailscale funnel — auto-configures webhook URL on startup
- `[sandbox.env]` support passes environment variables through to sandbox tool execution
- Dockerfile path syntax (`dockerfile = { path = "..." }`) in snapshot config
- `fabro validate` and the workflow validator now catch unresolved `@file` references before execution
- Fixed `@file` references with `~` home directory and `..` parent directory paths
- Compaction progress now visible in non-verbose `fabro run` output
- Run ID printed at start of `fabro run` and on resume for cross-referencing
- Git checkpoint commit skipped for start node to reduce noise
</Accordion>

<Accordion title="Improvements">
- Daytona sandboxes now named `fabro-{run_id}` for easy correlation with workflow runs
- Logs directory naming changed from `fabro-run-YYYYMMDD-HHMMSS` to `YYYYMMDD-{run_id}`
- Truncated stage failure error display to show only the last line in `fabro run` output
- `apply_patch` error responses now include file contents for better debugging of failed edits
- v4a patch parser/applier rewritten to match canonical OpenAI codex spec
- Accept bare `@@` hunk headers in v4a `apply_patch` parser
- Added Sprites (Fly.io) VM sandbox provider
</Accordion>

<Accordion title="Fixes">
- Fixed SSE streaming format mismatch in `/completions` endpoint
- Exempted `/tmp/` paths from sandbox read-before-write guard
- Fixed sandbox file-write validation incorrectly blocking valid operations
- Fixed stall watchdog killing agent during long LLM reasoning turns
- Added 5-minute stream read timeout with 5-second retry backoff for sandbox connections
- Increased default stall watchdog timeout from 10 to 30 minutes
- Fixed subagent and system prompt handling when prompt text is empty
- Fixed parallel stage compaction bars interfering with each other
</Accordion>
