Tools
Tools are how the model acts on your machine. FreeCode ships 19 built-ins — file I/O, search, code intelligence, shell, web access, sub-agents, memory — plus whatever an MCP server exposes. Concurrency-safe tools are batched and run in parallel; mutating tools run one at a time, in order.
Long-running commands
A bash call holds the model’s turn until the command finishes, so anything
long — a full test or eval suite, a build, a dev server — has to leave the
foreground. Three mechanisms make sure it does, and that the result still
comes back.
Background shells. bash with run_in_background: true returns a shell
id (bash_1) at once and the process keeps running. Watch it with /shells;
the model reads new output with bashoutput and stops it with killbash.
You are told when it exits. When a background command exits, the agent
gets a <task-notification> with the exit code and the last 4,000 characters
of output, and you see Background command completed: <command>. If the agent
is mid-turn it arrives between tool calls; if the session is idle, FreeCode
starts a turn so the agent reports back without you asking. So “run the eval
suite and tell me the result” works even when the suite takes hours. No
notification is sent when the agent already knows the outcome — it read the
finished shell with bashoutput, or stopped it with killbash.
A slow foreground command is moved, not killed. timeout defaults to 60
seconds and is capped at 10 minutes. If a command is still running when its
timeout expires, it is handed to a background shell with the output it has
printed so far, and the agent is told its id — the run continues and its exit
is reported as above. The one exception: when the agent set timeout itself
below the cap, it meant “stop it then”, so the command is killed and the
agent sees the partial output.
Watching a run as it happens: monitor. A background shell reports once,
at exit. monitor runs a command in the background and sends the agent a
notification for each batch of output lines while it runs — or only the lines
matching a pattern, e.g. FAIL|Error|Traceback. So “run the eval and tell me
the first failure” gets an answer at the first failure, not three hours later.
Lines arriving within a second are one notification; a monitor stops itself
after 20 notifications (the filter was too loose) or after timeout_ms
(default 5 minutes, at most 60), and sends a final notification when it ends.
It needs notifications on, and its permission rules match on the command
exactly like bash’s (Monitor(pnpm eval:*)).
A monitor can also watch a background shell that is already running: pass its
bash_id instead of a command. Output printed before it attached is checked
too. When it hits a limit it stops watching and leaves the shell running, and
the shell’s own exit notification reports the end. Attaching starts no new
command, so it has its own rule, Monitor(bash_id:*), which never approves a
command.
| Setting | Effect |
|---|---|
tasks.notify: false in settings.json, or FREECODE_TASK_NOTIFY=0 | No notifications, so no turn ever starts without you. Background shells still run; the agent has to check them with bashoutput. monitor is unavailable. |
When a background task is stopped early. Shells die with their session and with FreeCode itself — a command that must outlive the session belongs in your own terminal. What changes is that the agent is told: when you resume a session whose background tasks were stopped before finishing (you switched away, FreeCode restarted or crashed), you see a notice listing them, and the agent is told on your next message instead of waiting for a result that cannot come. Resuming never starts a turn by itself.
On this page (coming soon)
- File operations:
read,write,edit,ls - Search and code intelligence:
glob,grep,lsp - Execution and delegation:
bash,agent - Web access:
webfetch,websearch - Workflow:
skill,todowrite,question,output,memory - Parallel vs sequential execution, and why it matters
- Per-tool parameters — see the tools reference