If you already use Claude Code, a project set up for it should not need setting up a second time. Codey reads three kinds of thing from Claude Code's files — its MCP servers, its permission rules, and its CLAUDE.md files — and none of it is copied anywhere or written back: change it in Claude Code and the next start here sees the change.
Permissions. The permissions block of three settings files, in the order
Claude Code reads them:
| File | Whose | deny / ask | allow | defaultMode |
|---|---|---|---|---|
~/.claude/settings.json | yours, every project | honoured | honoured | acceptEdits only |
.claude/settings.json | the repository's, committed | honoured | only once trusted | ignored |
.claude/settings.local.json | yours, this project, git-ignored | honoured | honoured | acceptEdits only |
The rule underneath that table is who wrote the file. A deny or an ask rule can
only make the agent do less or ask more, and nobody comes to harm from that, so
a repository may add as many as it likes. An allow rule is the opposite: it is
a decision that something runs without you being asked, and a decision written
into a repository was made by whoever wrote the repository. The shared file's
allow rules therefore wait for the same trust question as its .mcp.json, and
until you answer it they are listed and ignored. A settings.local.json that
git turns out to be tracking arrived with the clone, whatever its name says,
and is treated as shared.
The rules act before anything else in the approval policy. A deny holds in
every mode, -yolo included — that is what writing it down is for — and it
holds for the read-only tools too, since Read(.env) is a rule about reading.
An ask rule puts the call to you even when the mode would have let it through,
and even when you said "always this tool" earlier in the session. An allow rule
lets a call through without a prompt. Between them deny beats ask beats allow,
as in Claude Code, so no allow rule anywhere argues a call past a deny. The
denial the model reads names the rule and the file, so it can tell you which
line to change instead of retrying. /allowed lists every rule under the file
it came from, and says which are in force and why the others are not.
Claude Code's names map onto Codey's: Bash is bash, Read is read_file
(and, as best it can, glob and grep), Edit is both edit_file and
write_file, MultiEdit is edit_file, Write is write_file, Glob,
Grep, WebFetch, WebSearch and TodoWrite are the obvious ones, and
mcp__server and mcp__server__tool are unchanged. A rule naming a tool Codey
does not have, or written in a form it does not understand, is reported at
startup and takes no part. Paths follow Claude Code's conventions: //path is
absolute, ~/path is under your home, /path is under the project root, and
anything else is relative to it, with a bare name such as .env matching at
any depth the way .gitignore would. Links are followed, so a rule about
.env also catches a symlink to it.
Bash(npm run test:*) is matched one simple command at a time, using the same
parser as the approval prompt. An allow rule covers npm run test && rm -rf ~
only if something also allows rm; a deny rule catches the line if it catches
any part of it. A command the parser cannot see through — $(...), backticks,
bash -c, a variable in command position — never matches an allow rule, and
where a deny rule cannot be ruled out for it, the call is asked about rather
than run. So is anything that does more than its words say: PATH=. git status, or echo hi > ~/.bashrc, is not covered by an allow rule for git or
echo. None of this makes shell allowlisting a security boundary — see
Safety — but it does stop the commonest way a prefix rule says yes to
something nobody wrote down.
defaultMode: "acceptEdits" in a file of yours lets file edits through, as
Claude Code's mode of that name does. default is the default. The other modes
are ignored with a notice, from every file: bypassPermissions in particular,
because in Codey the way to stop being asked is -yolo, typed on the command
line for one run, and neither a file of yours nor a repository's gets to say it
for you.
CLAUDE.md. The files Claude Code loads into every conversation are loaded
into this one's system prompt, at startup, in Claude Code's order:
~/.claude/CLAUDE.md, then — from the top of the project down to the working
root — each directory's CLAUDE.md, .claude/CLAUDE.md and CLAUDE.local.md.
The top is the nearest directory with a .git in it, or your home directory if
there is none on the way; a root that is in neither is a project of one
directory, because walking up to / would read whatever happened to be lying
in /tmp. Later files are more specific and the prompt says they win.
@path/to/file imports are followed, relative to the file they appear in and up
to five deep, skipping anything in a code block. A project's files may import
only from the project, and that is checked where symlinks lead: a repository's
CLAUDE.md that could import @~/.aws/credentials would be a repository reading
your credentials into a conversation that is then sent to the model. Your own
~/.claude/CLAUDE.md and CLAUDE.local.md may import from your home
directory. The whole thing is read once per session, so the cached prompt
prefix stays the same from request to request; restart to pick up an edit.
AGENTS.md is not loaded this way, but the agent is still told to read one if
the repository has it, as before, and a CLAUDE.md that says @AGENTS.md brings
it in.
What is not carried over, so nobody has to find out the hard way:
PreToolUse, PostToolUse and the rest).
Codey's hooks are a different thing — they watch, they cannot
veto — and a script written to block a tool call would silently block
nothing here.env, model, apiKeyHelper, statusLine, outputStyle, cleanupPeriodDays
and the other non-permission settings. Codey has its own config for the ones
it has an equivalent of.permissions.additionalDirectories: the file tools keep the working root as
their only root..mcp.json servers you approved
(enabledMcpjsonServers, enableAllProjectMcpServers). It approves by name,
so a server whose command changed under the same name would still count;
Codey asks its own question about the exact definitions instead..claude/rules/.