heya

Tools and safety

Heya runs one streaming function-calling loop. The model asks for a tool, Heya runs it, and the result goes back into the loop. The safety model is simple and visible.

What runs without asking, and what asks first

Reads run on their own. Anything that changes the world asks first.

Approve a prompted action once, approve it for the session, or decline it. With --auto-approve, the prompted tools run without asking. Use that only in a sandbox you trust.

The allow-list

The file and command tools are confined to an allow-list of folders. The current directory is always allowed; add more with --allow DIR or the [workspace] config. A path that escapes the allow-list is rejected. Commands always carry a timeout.

The tools

How tools behave

Tools never raise into the agent loop. On a problem they return a short Error: ... string, so a single failing tool never crashes a task. Long tool output is truncated with an explicit marker, never a silent cut.

Sub-agents

A sub-agent is a fresh agent with its own context. It sees only the task you give it, not your conversation. Parallel sub-agents are read-only by design: they get the read-only tool surface and the shared browser and WordPress sessions are withheld, so several can run at once with no races.

Git

Three git tools are read-only: git_status, git_log, and git_diff run without asking and return repository state. git_commit is gated (it asks before committing) and strips any AI-attribution footer from the message before writing the commit, so no "Co-Authored-By: Claude" or "Generated with" lines can slip in.

Heya commits only when you ask. It never auto-commits at the end of a task. Pull requests go through gh pr create via the gated run_command, so you approve the push and PR creation before anything is sent to the remote.

Web and domain diagnostics

Four read-only tools query public infrastructure to answer questions about domains and sites without guessing:

None of these tools modify anything. See the bundled web-diagnostics guidance (read_guidance('web-diagnostics')) for how to read RDAP dates, status flags, and common WordPress hosting fingerprints.

Web safety

web_fetch and browser_navigate reach any real site. By default they block link-local addresses (including 169.254.169.254, where cloud instance-metadata lives). Loopback and private network addresses are allowed, so local dev sites work fine. You can turn this off by setting block_metadata = false under [web], but there is rarely a reason to.

Checkpoints

Before every file write, Heya snapshots the prior content of the affected file. If the file did not exist yet, that fact is recorded too, so an undo can remove it cleanly. Snapshots live under ~/.config/heya/checkpoints/ and are never written into your project tree or your git history.

Three slash commands expose the checkpoint store:

run_command side effects (database writes, test runs, external API calls) are not captured. Checkpoints cover only files that Heya's file tools wrote.

To disable checkpoints entirely, add this to your config.toml:

[checkpoints]
enabled = false

Plan mode

Plan mode is a read-only session state. When it is on, Heya blocks writes, commands, and site actions in code: the tools themselves return an error rather than asking, so nothing slips through. The model can still read files, search, fetch pages, check DNS, and run read-only sub-agents. It uses that access to research the problem and return a concrete, step-by-step plan for you to review.

Start a session in plan mode with the --plan flag:

heya --plan

Toggle plan mode on or off at any time during an interactive session:

/plan

The typical flow: start with --plan (or /plan) to get a full picture of what needs to change before any file is touched. Review the proposed steps. When you are satisfied, type /plan again to switch to act mode and let Heya carry out the work.

Privacy

Heya is local-first. With a local model, nothing leaves your machine. With a cloud model, only what you send to that model's API leaves. Heya resolves a key from the environment variable you name in api_key_env first; if that is unset, it reads from the locked credentials file (~/.config/heya/credentials.toml, mode 0600) that heya init writes. A key is never stored in config.toml.