Configuration
snaga.toml
Project and global configuration — agent behaviour, memory, permissions, hooks, MCP servers — and why a config file from a repo you cloned asks before it does anything.
Snaga reads snaga.toml from the working directory or ~/.config/snaga/.
Layers apply in order: defaults, then global, then project, then environment.
[agent]
max_rounds = 20
temperature = 0.7
[memory]
enabled = true
playbook = true
reflection = true
[permissions]
auto_approve = ["read_file", "grep", "glob"]
deny = ["rm_all"]
[hooks]
enabled = true
[[hooks.after_tool_call]]
command = "cargo check"
tools = ["edit_file", "write_file"]
[[mcp.servers]]
name = "postgres"
command = "npx"
args = ["@modelcontextprotocol/server-postgres"]
The recognised sections are agent, memory, permissions, hooks, mcp and
models. There is no model selection here — the platform chooses; see
Getting started.
A config file from a cloned repo does not just run
This is the part worth knowing before anything else.
snaga.toml can declare shell hooks and MCP servers — that is, commands to run
and subprocesses to spawn. A project-local one can also be committed to a public
repository. So running snaga in a directory you just cloned would otherwise
silently execute whatever its config said.
It does not. Project-local configs are untrusted by default. When one asks for side effects, Snaga stops and shows you what it wants:
Project-local snaga.toml requests side effects:
/path/to/snaga.toml
· shell hook — cargo check after edit_file
· mcp server — npx @modelcontextprotocol/server-postgres
You approve or you do not. Approval is remembered per project, and a changed
snaga.toml asks again — otherwise someone who landed a commit in your
repository would inherit a decision you made about a different file.
A global config in ~/.config/snaga/ is yours and is not treated this way.
Hooks
Hooks run around tool execution. Note the shape: [[hooks.after_tool_call]] is
an array of tables, one per hook, not a single string.
[hooks]
enabled = true
[[hooks.after_tool_call]]
command = "cargo check"
tools = ["edit_file", "write_file"]
tools narrows a hook to the tools that should trigger it. Available points are
before_tool_call, after_tool_call, on_error and on_turn_complete.
A hook is a command that runs on your machine every time it fires. Keep them
fast — a slow before_tool_call is paid on every single tool call.
MCP servers
Servers declared here are connected at startup:
[[mcp.servers]]
name = "github"
command = "npx"
args = ["-y", "@modelcontextprotocol/server-github"]
env = { GITHUB_TOKEN = "${GITHUB_TOKEN}" }
Environment variables interpolate, so credentials stay out of the file and out of your repository. Declaring a server counts as a side effect for the trust prompt above.
See Skills and MCP.
Permissions
[permissions]
auto_approve = ["read_file", "grep", "glob"]
deny = ["rm_all"]
This is per-tool. The shell command policy is a separate file with its own merge rules — see Changing the rules.