Permissions#
PacketCode evaluates every built-in and MCP tool against a permission profile. The result is allow, ask or deny. Ordered rules can narrow the decision for a specific tool or command prefix.
Before you start#
- The project is under version control.
- You understand which files and commands the task requires.
- Important credentials are not exposed to the process unnecessarily.
Profile and rule example#
A [permissions.profiles.<name>] table defines a custom profile, and
[permissions] profile selects it by name. The name must not be a built-in
profile or one of its aliases — balanced, ask, read_only, accept_edits,
auto, full and the rest — because a built-in name resolves to the built-in
profile and the table beside it is then ignored without a warning.
[permissions]
profile = "reviewed"
[permissions.profiles.reviewed]
default = "ask"
read_file = "allow"
search_codebase = "allow"
list_directory = "allow"
write_file = "ask"
patch_file = "ask"
execute_command = "ask"
spawn_agent = "ask"
mcp = "ask"
[[permissions.rules]]
tool = "execute_command"
action = "deny"
command_prefix = ["rm"]
reason = "refuse deletes from the agent"
To run a built-in profile instead, set profile = "balanced" and omit the
profiles table. Ordered rules apply either way.
Use deny rules as a floor for actions that should never be approved. A prompt approval is scoped to the option shown; do not interpret it as proof that the command is safe.
Current source builds show whether an approval applies once or for the session.
A remembered shell approval covers the exact command text in any working
directory; a remembered tool approval permits that tool with any arguments or
paths for the rest of the session.
Review session rules with /permissions and revoke them with
/permissions reset. Skill
allowed-tools grants are temporary permissions for the loading turn; they
never override a deny rule and do not grant authority to later queued work.
See Skills, MCP and hooks.
How the deny floor is applied#
A deny rule whose prefix is written from plain command words is checked on every allow, including an allow that came from a session grant or a skill's allowed-tools list. Such a deny is not weakened by a later allow.
The comparison sees through shell quoting, so "git" push matches a git push
deny. When the command reaches the denied program indirectly — sh -c, sudo,
xargs or a scripting interpreter such as python -c — or when an option makes
the match impossible to settle from the command string alone, as in
git -C . push, the decision escalates to an approval prompt instead of an
allow. A floor that cannot be evaluated does not read as "not denied".
Prefer ["rm"] for a blanket deny of that program. Current source builds also
honour a prefix containing a flag such as ["rm", "-rf"], but that rule covers
the matched form rather than every equivalent invocation. Current deny checks
also recognise case variants and executable suffixes such as .exe; commands
whose expansions or wrappers cannot be resolved require approval rather than
inheriting an allow. Older builds may handle those forms differently, so verify
the installed version with a harmless test command.
Files PacketCode will not read#
read_file, search_codebase and @-mention expansion refuse dotenv secret
files: .env and any .env.<suffix>. The example spellings .env.example,
.env.sample, .env.template and .env.dist are exempt. PacketCode reads
provider keys from the project .env and the data home's .env itself, so
inlining one of those files would copy credentials into the transcript, the
stored session and every later provider request.
Current source builds apply the same secret-file restriction to code intelligence tools, including symbol, definition, reference and diagnostic lookups, even when the file is named explicitly.
This is a name rule, not a sandbox. execute_command is unchanged and a shell
can still read any file the account can, which is why that tool is
approval-gated and shows the command before it runs.
Clients connected over ACP#
When a client connects to packetcode acp, the permission modes the server
advertises are capped at the profile the server itself runs. A client may narrow
its session but never widen it. The default balanced profile and any custom
profile both resolve to ask, so such a server offers only ask and read-only.
Raising the ceiling means raising what the server itself enforces. A configured
profile of bypass, full or trusted, or starting the server with
packetcode acp --permission-mode bypass, offers the full range;
accept-edits and auto raise it part of the way. Setting trust_mode under
[behavior] is the only option that raises the ceiling without naming a
profile, because it raises the policy to full on its own.
Verify#
- Start a session in a disposable repository.
- Request a file read and confirm it proceeds under the profile.
- Request a harmless file edit and confirm an approval appears.
- Request a command matched by a deny rule and confirm it does not run.
- Request the same command through
sh -cand confirm it is denied or asked, never allowed. - Ask for a
.envfile to be read and confirm the tool refuses it. - Inspect Git status to verify no unapproved change occurred.
The policy limits PacketCode's decisions, not the authority of the operating system account. Run untrusted projects in an appropriate external sandbox.
If it does not work#
| Symptom | Check | Recovery |
|---|---|---|
| An allowed action is still refused | Whether a deny rule applies — deny is a floor | An explicit deny is not weakened by a later allow |
| A file you expect to be readable is refused | Whether it is on the never-read list | See A file read is refused |
| An ACP client is refused a session | The client's own permissions, not the profile | See An ACP client is refused a session |
| A rule appears to have no effect | Whether the profile is the active one | Do not widen the policy to make an error stop — confirm which profile is loaded first |