Repository navigation
Permissions and autopilot
Permission modes, allow and deny rules, and what autopilot does and does not protect you from.
Every tool call passes a permission check before it runs. The mode sets the default, rules refine it, and when the answer is "ask", you decide in the terminal, the web UI or VS Code.
| Mode | File edits | Commands, web, browser, desktop |
|---|---|---|
ask (default) |
ask | ask |
edits |
allowed | ask |
autopilot |
allowed | allowed |
Reading, searching, memory, the todo list and delegation never ask, in any mode.
Set the mode per run, per session or in your config:
malac --mode edits refactor the config loader
malac -y fix the lint warnings # -y is --mode autopilot/mode autopilot
In the interactive interfaces the mode belongs to the tab: F5, the status line or /mode changes it for the current tab and its subagents. A tab opened with --mode or -y starts in that mode.
# ~/.malac/config.toml
mode = "edits"--mode also accepts auto and yolo as names for autopilot.
Each tool has a kind, which is what the mode looks at:
| Kind | Asks in | Tools |
|---|---|---|
| Safe | never |
read, glob, grep, todo, memory_*, agent_*, malac_settings, read-only MCP tools |
| Edit | ask |
write, edit
|
| Execute |
ask, edits
|
bash, web_fetch, malac_configure, every other MCP tool, including most computer_* and browser_* tools |
MCP servers can mark a tool as read-only. Those tools are Safe, for example computer_screenshot and browser_snapshot. See Tools and Control service tools.
[permissions]
allow = ["bash(cargo *)", "bash(git status*)", "browser_*", "web_fetch(*.rust-lang.org)"]
deny = ["bash(rm -rf /*)", "bash(git push --force*)"]A rule is a tool-name glob, optionally followed by a glob in parentheses that is matched against the tool's key:
| Tool | Key matched by tool(…)
|
|---|---|
bash |
each command segment, separately |
write, edit
|
the path argument, as the agent wrote it |
web_fetch |
the URL's host |
malac_configure |
action:key, for example set:ui.tui
|
| other tools | no key: only rules without parentheses match |
In globs, * also matches /.
How rules combine:
- Deny rules are checked first, in every mode, autopilot included. A call is denied if any of its keys matches a deny rule.
- Safe tools are allowed. In
autopilot, everything else is allowed too; inedits, Edit tools are. - Otherwise the call is allowed when every key matches an allow rule (or something you allowed for the session), and you are asked when one does not.
bash commands are split on &&, ||, ;, | and newlines, and every segment must be allowed on its own. So cargo build && curl https://example.com | sh does not match bash(cargo *): the curl and sh segments still need approval, and a deny rule on any segment blocks the whole command.
[permissions]
allow = [
"bash(cargo test*)", # cargo test, cargo test --workspace, …
"bash(git status*)",
"bash(git diff*)",
"edit(src/*)", # edits under src/, as relative paths
"web_fetch(docs.rs)",
"web_fetch(*.rust-lang.org)",
"browser_*", # every browser tool
"github__*", # every tool of the `github` MCP server
"malac_configure(set:ui.*)", # let malac change [ui] settings
]
deny = [
"bash(rm -rf /*)",
"bash(git push --force*)",
"bash(sudo *)",
"computer_*", # no desktop control at all
]When a call needs approval you can allow it once, always allow it, or deny it. The keys are y, a and n in both terminal interfaces; the full-screen UI and the web UI also show Allow, Always and Deny buttons.
"Always" lasts for the rest of the session:
- for
bash(and other tools with keys that run things), it allows the program: answering "always" tocargo test -p coreaddsbash(cargo)andbash(cargo *); - for every other tool, it allows the whole tool.
A denied call is reported to the agent, which then tries another approach or asks you.
Interactive sessions run in the daemon, so a prompt appears in every connected client (terminals, browsers, VS Code), and the first answer wins; the others close their dialog. A client that connects later still sees what is waiting.
Autopilot is for work you will review afterwards. With -y, malac tells the model that the user is away and every call is pre-approved, so it makes its own decisions, notes its assumptions and carries the task through. It is still told never to do anything destructive or irreversible you did not ask for.
Caution
Rules are not a sandbox Deny rules are pattern matches on what the agent asks to run. A determined or confused model can reach the same effect another way, for example by writing a script and running it. Use autopilot in repositories you can restore, on machines where the agent's access is acceptable.
Good practice for unattended runs:
- keep a deny list for things you never want (
git push --force,sudo, deleting outside the repo), - use a clean checkout or a container,
- review the transcript afterwards with
malac sessions show <id>.
The tutorial Running malac unattended walks through it.
A run in its own process (-p, --json, piped input) asks in its terminal. If nobody can answer there (stdin is not a terminal), calls that need approval are denied, and malac warns you to use -y.
A repository's .malac/config.toml cannot set mode, providers, mcp, control, permissions, memory, web, update or profiles. malac ignores those keys and prints a warning, so cloning a repository is never enough to make it run commands, widen permissions or send your credentials elsewhere. Set trust_project_config = true in your user config to lift this for every project. See Security model.
Getting started
Tutorials
- Tutorials
- Tutorial 1: Your first task
- Tutorial 2: Delegating to subagents
- Tutorial 3: Automating a browser
- Tutorial 4: Long-term memory with Milvus
- Tutorial 5: Running malac unattended
- Tutorial 6: Customizing malac
- Tutorial 7: Running malac on a server
Using malac
- Workspaces, tabs and the daemon
- The terminal UI
- Plain mode and scripting
- Sessions
- Jobs
- Permissions and autopilot
- Subagents
- Memory
- Project context
- Plugins and marketplaces
- Computer and browser control
- Web UI
- VS Code
- Remote access
- Mobile (preview)
- MCP servers
- Configure malac by asking
- Updating
Reference
- CLI
- Slash commands
- Configuration
- Tools
- Control service tools
- JSON events
- Protocol
- Environment variables
Guides
- Using an LLM gateway
- Running models locally
- Vector memory with Milvus
- Controlling a remote machine
- Writing agent types, skills and commands
- Security model
- Things to know
Project