Switch AI agent behaviors instantly. Apply persona defaults and policies (strict enforcement optional).
Define reusable instruction profiles for AI coding agents. Share them across repos, switch personas on the fly, and lock down what agents can do. Works with Claude, Codex, Gemini, and OpenCode.
| Problem | Solution |
|---|---|
| Different tasks need different agent instructions | Swap personas instantly without editing files |
AGENTS.md changes clutter git history |
Overlay system leaves no on-disk changes (Linux) |
| Need safe defaults but occasional overrides | Policy applies by default; CLI args can override (use --strict-policy to enforce) |
| MCP servers configured per-project | Portable MCP definitions in persona.json |
| Team conventions scattered across repos | Shared personas and includes for consistency |
# Install
git clone https://github.com/GoodFarming/agent-persona.git
cd agent-persona && ./install.sh
# Launch Claude with the "blank" persona
agent-persona claude blank
# See what personas are available
agent-persona --list
# Check everything is working
agent-persona doctorA persona is a folder containing instructions (and optional config) for an AI agent:
.personas/
my-persona/
AGENTS.md # Instructions the agent sees (required)
CLAUDE.md # Claude-specific instructions (optional)
GEMINI.md # Gemini-specific instructions (optional)
persona.json # Defaults, MCP servers, policy (optional)
When you run agent-persona claude my-persona, the launcher:
- Finds your persona
- Overlays the instructions onto the target file (
CLAUDE.md) - Injects any MCP servers and defaults
- Launches Claude with everything configured
┌─────────────────────────────────────────────────────────────────┐
│ agent-persona │
├─────────────────────────────────────────────────────────────────┤
│ 1. Find persona (repo → home → system) │
│ 2. Merge repo-wide meta instructions │
│ 3. Expand include directives │
│ 4. Inject MCP servers from persona.json │
│ 5. Translate policy to tool-specific flags │
│ 6. If `--strict-policy`, filter user args that conflict │
│ 7. Overlay composed file onto working directory │
│ 8. Launch tool with: defaults + policy + user_args │
└─────────────────────────────────────────────────────────────────┘
- Normal mode: user args override policy.
- Strict mode (
--strict-policy): policy overrides user args.
On Linux: Uses bind-mount via unshare — your actual AGENTS.md is never modified.
Elsewhere: Swaps the file, runs the tool, restores on exit. If a crash occurs, run agent-persona recover.
Best for project-specific instructions that travel with your repo:
cd your-project
agent-persona init # Creates .personas/ scaffold
mkdir .personas/dev
cat > .personas/dev/AGENTS.md << 'EOF'
# Development Persona
You are helping with active development on this project.
## Guidelines
- Write tests for new functionality
- Keep changes focused and minimal
- Explain trade-offs when relevant
EOFBest for personal preferences that apply everywhere:
mkdir -p ~/.personas/reviewer
cat > ~/.personas/reviewer/AGENTS.md << 'EOF'
# Code Reviewer
Focus on code quality, security, and best practices.
Be thorough but constructive.
EOFClaude and Gemini can have their own instruction files:
.personas/my-persona/
AGENTS.md # Default (used by Codex, OpenCode)
CLAUDE.md # Used by Claude (if present)
GEMINI.md # Used by Gemini (if present)
Policies define baseline constraints in persona.json (tools/paths/network) that agent-persona translates into tool-specific flags/config.
By default, user tool flags override policy. This lets you keep safe defaults in persona.json, while still allowing power users to push boundaries for a single run (for example, --yolo on Codex).
To enforce policies (non-overridable), run with --strict-policy (or AGENT_PERSONA_STRICT_POLICY=1).
Add a policy block to persona.json:
{
"policy": {
"tools": {
"allow": ["bash", "read", "edit", "write", "glob", "grep"],
"deny": ["webfetch", "websearch", "task"]
},
"paths": {
"allow": ["./src", "./tests", "/tmp"],
"deny": [".env", "credentials.json", "~/.ssh/**"]
},
"network": {
"deny": ["*"]
}
}
}- Normal mode (default):
defaults→policy→ user tool args - Strict mode (
--strict-policy):defaults→ user tool args (filtered) →policy - Auto-bypass defaults (
codex --full-auto,claude --permission-mode bypassPermissions) are suppressed when a policy exists; pass them explicitly if you want them.
When --strict-policy is used, these user tool flags are ignored/filtered so policy can’t be overridden:
| Tool | User Tool Flags Controlled by --strict-policy |
|---|---|
| Claude | --permission-mode, --tools, --allowedTools, --disallowedTools, --settings, --dangerously-skip-permissions |
| Codex | --full-auto, --yolo, --dangerously-bypass-*, -c sandbox_mode=*, -c sandbox_workspace_write.* |
| Gemini | Strict mode forces GEMINI_CLI_SYSTEM_SETTINGS_PATH to the generated settings file |
| OpenCode | Strict mode forces OPENCODE_CONFIG to the generated config file |
See exactly how your policy will be translated:
agent-persona print-policy claude my-persona
agent-persona print-policy codex my-personaEnforce policy and fail if it can't be reliably enforced:
agent-persona claude my-persona --strict-policyThis catches issues like:
- Using
network.denywhilebashis allowed (shell cancurl/wget) - Using
paths.denywith Codex (not supported) - Using
pathsrestrictions with Gemini (not supported)
| Policy Element | Codex | Claude | Gemini | OpenCode |
|---|---|---|---|---|
| tools.allow | — | Strong | Strong | Strong |
| tools.deny | Partial (websearch only) | Strong | Strong | Strong |
| paths.allow | Strong | — | None | — |
| paths.deny | None | Partial (Claude settings) | None | — |
network.deny ("*") |
Strong | None | None | None |
Legend: Strong = sandbox/config enforced, Partial = has known gaps, None = not supported, — = not implemented
Notes:
- Codex tools.deny: only
websearchis translated today (features.web_search_request=false). - No-network on non-Codex tools: deny network-capable tools (e.g.,
websearch/webfetch) and denybashif you need “no network” guarantees. - Claude paths.deny: Partial via
--settingsdeny rules; has edge-cases with MCP tools - Non-Codex network.deny: No sandbox-level network isolation exists; see Hardening Guidance below
For "no network access" on Claude, Gemini, or OpenCode:
These tools lack OS-level network sandboxing. To achieve network isolation:
-
Deny bash AND deny web tools — prevents
curl/wgetin shell and blockswebfetch/websearch:{ "policy": { "tools": { "deny": ["bash", "webfetch", "websearch"] } } } -
Or run inside an external network sandbox (container, VM, network namespace)
-
Use
--strict-policyto fail fast when guarantees aren't possible:agent-persona claude my-persona --strict-policy
This fails if
network.deny: ["*"]is set butbashis allowed.
Bash command restrictions are not reliably enforceable. Once bash is in tools.allow, the agent can run arbitrary shell commands. There is no cross-tool mechanism to restrict specific commands (e.g., git clean). If you need command-level control, deny bash entirely or use an OS-level sandbox.
Use Codex for strongest isolation. Codex's sandbox mode provides actual OS-level path and network restrictions that other tools cannot match.
Create reusable blocks in .personas/.shared/:
# .personas/.shared/security-rules.md
## Security Requirements
- Never expose credentials
- Validate all user input
- Use parameterized queriesInclude them in any persona:
# My Persona
<!-- include {"file":"security-rules.md"} -->
## Additional Guidelines
...# Extended Persona
<!-- include {"persona":"base-persona"} -->
## My Additions
...persona.json supports includes too:
{
"include": [
{ "file": "policy-base.json" },
{ "persona": "secure-base" }
],
"policy": {
"tools": {
"deny": ["task"]
}
}
}Includes merge additively. Conflicts (e.g., same tool in both allow and deny) cause errors.
Add context that applies to all personas in a repo:
# .personas/.shared/meta.AGENTS.md
## Project Context
This is a TypeScript monorepo using pnpm workspaces.
## Conventions
- Use vitest for tests
- Run `pnpm lint` before committing
## Off-Limits
- Don't modify `packages/legacy/`Meta is merged at the top of every persona (or bottom with --meta-position=bottom).
The template created by agent-persona init is ignored until you edit it.
Define MCP servers in persona.json and they're automatically configured:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@anthropic/mcp-filesystem"],
"env": { "ALLOWED_PATHS": "/home/user/projects" }
},
"database": {
"command": "mcp-postgres",
"args": ["--connection-string", "postgres://..."]
}
}
}- Claude: Generates temp
--mcp-configJSON file - Codex: Emits
-c mcp_servers.*=...overrides - Disable with
--no-mcporAGENT_PERSONA_MCP=0
{
"defaults": {
"*": ["--verbose"],
"codex": ["--model", "o3"],
"claude": ["--model", "sonnet"]
}
}Global defaults (*) apply first; tool-specific defaults append after.
Unless policy exists, agent-persona adds sensible defaults:
- Codex:
--full-auto(auto-approve safe operations) - Claude:
--permission-mode bypassPermissions(skip prompts)
These are suppressed when a policy exists (policy controls permissions).
# persona.json: "claude": ["--model", "opus"]
agent-persona claude my-persona --model sonnet
# Result: only --model sonnet is passedagent-persona claude my-persona --no-defaultsResolution order (first match wins):
- Repo-local:
.personas/<name>/in current directory or parent directories - Extra paths:
AGENT_PERSONA_PATHSenvironment variable (colon-separated) - Home:
~/.personas/<name>/ - User:
~/.local/share/agent-persona/.personas/<name>/ - System:
/usr/local/share/agent-persona/.personas/<name>/
agent-persona which my-persona # Show where persona resolves fromSet AGENT_PERSONA_PREFER_REPO=0 to check home/user before repo.
| Command | Description |
|---|---|
agent-persona <tool> <persona> |
Launch tool with persona |
agent-persona init |
Scaffold .personas/ in current repo |
agent-persona doctor |
Verify installation and check for issues |
agent-persona recover |
Restore files after hard-kill (swap mode) |
agent-persona which <persona> |
Show where persona resolves from |
agent-persona print-overlay <tool> <persona> |
Preview composed instructions |
agent-persona print-policy <tool> <persona> |
Show policy translation summary |
agent-persona --list |
List all available personas |
Symlinks let you skip specifying the tool:
claude-persona my-agent # same as: agent-persona claude my-agent
codex-persona my-agent
gemini-persona my-agent
opencode-persona my-agent| Flag | Description |
|---|---|
--no-meta |
Skip repo meta merge |
--no-mcp |
Skip MCP injection |
--no-defaults |
Skip all defaults |
--meta-file=<path> |
Override meta file location |
--meta-position=top|bottom |
Where to merge meta (default: top) |
--force-swap |
Force swap-and-restore (skip bind-mount) |
--strict-policy |
Fail if policy cannot be reliably enforced |
--version |
Show version |
-h, --help |
Show help |
| Variable | Description | Default |
|---|---|---|
AGENT_PERSONA_DEBUG |
Enable debug logging | off |
AGENT_PERSONA_META |
Enable meta merge | 1 |
AGENT_PERSONA_MCP |
Enable MCP injection | 1 |
AGENT_PERSONA_DEFAULTS |
Enable persona/tool defaults | 1 |
AGENT_PERSONA_STRICT_POLICY |
Fail on unenforced policy | 0 |
AGENT_PERSONA_FORCE_SWAP |
Force swap mode | 0 |
AGENT_PERSONA_PATHS |
Extra search paths (colon-separated) | empty |
AGENT_PERSONA_HOME |
User persona directory | ~/.local/share/agent-persona |
AGENT_PERSONA_PREFER_REPO |
Prefer repo-local personas | 1 |
AGENT_PERSONA_INCLUDE_DEPTH |
Max include recursion depth | 10 |
AGENT_PERSONA_GEMINI_DISABLE_IDE |
Disable Gemini IDE mode | 0 |
AGENT_PERSONA_GEMINI_FORCE_TTY |
Force pseudo-TTY for Gemini | auto |
Useful for hooks, scripts, memory, and logging:
| Variable | Description | Example |
|---|---|---|
AGENT_PERSONA_NAME |
Persona slug | code-reviewer |
AGENT_PERSONA_PATH |
Resolved persona directory | /home/user/.personas/code-reviewer |
AGENT_PERSONA_TOOL |
Tool being launched | claude |
AGENT_PERSONA_OVERLAY_FILE |
Target overlay file | CLAUDE.md |
AGENT_PERSONA_RUN_MODE |
Launch mode | unshare or swap |
agent-persona claude researcher # Deep research, thorough exploration
agent-persona codex fixer # Quick fixes, minimal changes
agent-persona claude reviewer # Code review, security focus{
"policy": {
"tools": { "allow": ["bash", "read", "edit", "write", "glob", "grep"] },
"paths": { "allow": ["./src", "./tests"] },
"network": { "deny": ["*"] }
}
}Same persona, different tools:
agent-persona codex architect # Planning with Codex
agent-persona claude architect # Implementation with ClaudeShare personas via dotfiles or a team repo:
export AGENT_PERSONA_PATHS="$HOME/team-personas:$AGENT_PERSONA_PATHS"// frontend/.personas/dev/persona.json
{
"mcpServers": {
"browser": { "command": "mcp-browser-tools" }
}
}
// backend/.personas/dev/persona.json
{
"mcpServers": {
"postgres": { "command": "mcp-postgres", "args": ["--local"] }
}
}| Environment | Method | On-Disk Changes | Hard-Kill Risk |
|---|---|---|---|
Linux with unshare |
Bind-mount | None | None |
Other / --force-swap |
Swap-and-restore | Temporary | Use recover |
If a session is killed unexpectedly (SIGKILL, crash, power loss) while in swap mode:
agent-persona recover # Restores from backup
agent-persona doctor # Shows any orphaned backupsSee INSTALL.md for detailed instructions.
git clone https://github.com/GoodFarming/agent-persona.git
cd agent-persona && ./install.sh
agent-persona doctor- Linux (tested on Ubuntu, should work on most distros)
- Bash 4.0+ (required for policy features)
- Python 3 (required for policy enforcement, persona.json parsing, include expansion)
- One or more AI tools:
codex,claude,gemini,opencode
./uninstall.sh
# or manually:
rm -f ~/.local/bin/agent-persona ~/.local/bin/*-persona
rm -rf ~/.local/share/agent-persona# Core functionality
bash tests/smoke.sh
# CLI argument/env translation (no model calls)
bash tests/integration-cli-parse.sh
# Real CLI tests (requires credentials, may incur cost)
AGENT_PERSONA_RUN_REAL_TESTS=1 bash tests/integration-real.shFor full test options and manual test procedures, see tests/MANUAL-TESTS.md.
| Tool | Overlay File | Policy Support |
|---|---|---|
| Claude / Claude Code | CLAUDE.md |
Full |
| Codex | AGENTS.md |
Full (sandbox-based) |
| Gemini | GEMINI.md |
Full (settings-based) |
| OpenCode | AGENTS.md |
Full (config-based) |
| Any executable on PATH | AGENTS.md |
None |
Issues and PRs welcome at github.com/GoodFarming/agent-persona.
MIT