Pillar 1: Identity

One command transforms your agent’s entire identity.

A profile is not just a config file — it is the complete persona, permissions, and toolset your agent carries into every session. Swap it in seconds. Layer them for precision.

Table of contents

  1. What is a profile?
  2. Profile structure
  3. Built-in profiles
  4. Profile chaining
    1. What each entity does in a chain
    2. CLAUDE.md concatenation
  5. The two-axis model
    1. Usage
  6. Per-repo identity
    1. Querying the active profile
    2. Monorepo example
  7. The bundle system
  8. Environment variables
  9. Reference: profile.yml fields
  10. Creating a custom profile
  11. Runtime overlays — mid-session profile shifting

What is a profile?

A profile is a named bundle that defines who your agent is and what it is allowed to do:

Component What it controls
CLAUDE.md The agent’s system prompt — behavioral rules, response style, operator model
settings.overrides.json Permissions: deny lists, ask lists, permission mode
.mcp.json Which MCP tool servers are active
rules/, skills/, agents/, commands/ Domain-specific assets available in the session
profile.yml Model selection, turn limits, timeout, launch flags

Profiles live under profiles/<name>/ in the agentihooks repo or in a linked bundle. Switch one, change everything.

agentihooks init --profile coding     # feature branch agent: safe, git-guarded
agentihooks init --profile admin      # infra agent: full permissions, no guardrails
agentihooks init --profile anton       # operator-tuned persona with behavioral model

Profile structure

profiles/
├── _base/
│   └── settings.base.json          # Canonical hooks, permissions, MCP server list
├── coding/
│   ├── CLAUDE.md                   # Agent system prompt (at profile root)
│   ├── profile.yml                 # agentihooks metadata + Claude launch config
│   └── .claude/
│       ├── settings.overrides.json # Merged on top of _base at install time
│       ├── .mcp.json               # Profile MCP servers
│       ├── rules/                  # Behavioral rules for this profile
│       ├── skills/                 # Profile-specific skills
│       ├── agents/                 # Profile-specific agent definitions
│       └── commands/               # Profile-specific slash commands
└── admin/
    └── ...                         # Same structure

The _base/settings.base.json is the single source of truth for hook wiring. Profiles only declare what they override — the base is always preserved.


Built-in profiles

Three profiles ship with agentihooks, covering the most common permission postures:

Profile Mode Use case
default auto General use — autonomous but protected branches are sacred
coding acceptEdits Feature branch development — git-guarded, edit-confirm flow
admin bypassPermissions Infrastructure and admin tasks — full trust, no friction

These are settings profiles — they control permissions and tool access. Pair them with any persona profile using the two-axis model.


Profile chaining

Mix and match capabilities without building a monolithic profile. Comma-separate profile names to chain them:

agentihooks init --profile coding,anton

Profiles are applied left to right. The rightmost profile has highest priority for scalar values; everything else merges additively.

flowchart LR
    base["_base/\nsettings.base.json"]
    coding["coding/\nsettings.overrides.json"]
    anton["anton/\nsettings.overrides.json"]
    final["~/.claude/\nsettings.json"]

    base -->|"deep merge"| coding
    coding -->|"deep merge\nhooks append"| anton
    anton --> final

What each entity does in a chain

Entity Chain behavior
Settings Sequential deep merge — dicts combine, hook arrays append, scalars last-wins
Rules / Skills / Agents / Commands Additive — all profiles contribute; same filename = later profile wins
CLAUDE.md Concatenated into one file with --- separators and <!-- profile: name --> markers
MCP servers Additive — all profiles’ servers accumulate

CLAUDE.md concatenation

In chain mode, all personas are active simultaneously:

<!-- profile: coding -->
# Coding Agent
...

---

<!-- profile: anton -->
# Anton Profile
...

Claude Code loads the entire combined file as its system prompt.


The two-axis model

Sometimes you want to change permissions without changing who the AI is. The two-axis model gives you independent control:

graph TD
    subgraph "Axis 1 — Persona (--profile)"
        A["CLAUDE.md\n(system prompt)"]
        B["rules/\nskills/\nagents/\ncommands/"]
    end
    subgraph "Axis 2 — Settings (--settings-profile)"
        C["settings.overrides.json\n(permissions, env vars)"]
        D[".mcp.json\n(tool servers)"]
    end

    A --> merged["Active Session"]
    B --> merged
    C --> merged
    D --> merged
Axis Controls Changed by
Persona Rules, CLAUDE.md, skills, agents, commands --profile
Settings Permissions, env vars, tool allowlists, MCP servers --settings-profile

The settings overlay is applied after the persona’s settings overrides — it always wins on conflicts.

Usage

# Full install: Anton persona + admin permissions
agentihooks init --profile anton --settings-profile admin

# Quick switch: escalate permissions, keep persona intact
agentihooks settings-profile admin

# Revert settings to persona defaults
agentihooks settings-profile --clear

# Via environment variable
export AGENTIHOOKS_SETTINGS_PROFILE=admin
agentihooks init --profile anton   # admin overlay applied automatically

The agentihooks settings-profile command is the fastest way to escalate or de-escalate. No re-install, no persona disruption — just a settings layer swap.


Per-repo identity

Each project can pin its own profile, independent of the global install. Commit a .agentihooks.json to the repo root:

{
  "profile": "coding",
  "enabledMcpServers": ["gateway-core", "gateway-pm"]
}

Then generate the project-local config:

agentihooks init --local

This writes two gitignored files that Claude Code treats as highest priority:

File Purpose
.claude/settings.local.json Project-scoped permissions and env vars
.claude/CLAUDE.local.md Project-scoped system prompt from the resolved profile

Querying the active profile

agentihooks --query
coding (local)     # project has .agentihooks.json
anton (global)      # fallback to global install
chain: [coding, anton]  # chained profile

Monorepo example

Different agents, different identities, same repo:

my-monorepo/
├── .agentihooks.json          → {"profile": "anton"}
├── agents/
│   ├── publisher/
│   │   └── .agentihooks.json  → {"profile": "coding", "enabledMcpServers": ["gateway-publish"]}
│   └── reviewer/
│       └── .agentihooks.json  → {"profile": "coding", "enabledMcpServers": ["gateway-core"]}
└── infra/
    └── .agentihooks.json      → {"profile": "admin", "enabledMcpServers": ["gateway-infra"]}

The bundle system

Profiles are shareable. A bundle is an external directory of custom profiles linked into agentihooks once:

my-bundle/
├── .claude/                  # Assets shared by all bundle profiles
│   ├── rules/
│   └── .mcp.json             # Bundle-wide MCP servers
└── profiles/
    ├── infra-ops/            # Custom profile
    │   ├── CLAUDE.md
    │   ├── profile.yml
    │   └── .claude/
    └── reviewer/
        └── ...
# Link the bundle (once)
agentihooks bundle link ~/dev/my-bundle

# All bundle profiles are now discoverable
agentihooks --list-profiles

# Use a bundle profile like any built-in
agentihooks init --profile infra-ops

Bundle profiles merge through the same 3-layer system:

agentihooks built-in  →  bundle global .claude/  →  profile-specific .claude/

Later layers win on conflicts. The bundle is a clean separation point — your team customizations live there, personal overrides live in profile-specific files.


Environment variables

Variable Default Description
AGENTIHOOKS_PROFILE default Profile when --profile is not passed. Useful in CI/Docker.
AGENTIHOOKS_SETTINGS_PROFILE (none) Settings overlay profile applied automatically on every init.
# In a Dockerfile or CI environment
ENV AGENTIHOOKS_PROFILE=coding
RUN agentihooks init   # uses coding profile automatically

Reference: profile.yml fields

# agentihooks metadata
name: coding
description: "Autonomous coding agent"
mcp_categories: aws,utilities,observability   # MCP tool categories to enable

# Claude launch config (read by `agentihooks claude` / `agenti`)
claude:
  model: sonnet
  max_turns: 80
  timeout: 3600
  permission_mode: bypassPermissions   # maps to --dangerously-skip-permissions

The agentihooks claude command (alias: agenti) reads this file and translates it to Claude Code CLI flags — no manual flag management.


Creating a custom profile

# 1. Copy an existing profile as a starting point
cp -r profiles/default profiles/myprofile

# 2. Set identity metadata
# Edit profiles/myprofile/profile.yml

# 3. Write the system prompt
# Edit profiles/myprofile/CLAUDE.md

# 4. Add profile-specific assets (optional)
# profiles/myprofile/.claude/rules/
# profiles/myprofile/.claude/skills/
# profiles/myprofile/.claude/settings.overrides.json

# 5. Install it
agentihooks init --profile myprofile

Hooks are always wired from _base/settings.base.json. Profiles control persona, permissions, and assets — not the underlying hook infrastructure.



Runtime overlays — mid-session profile shifting

Profiles are static — installed once, read at session start. But what if your agent needs to shift behavior mid-session without restarting?

Runtime overlays solve this. An agent can layer a profile on top of its base identity, live, and peel it off when done — all without losing conversation context.

# Agent running on anton (general-purpose, full autonomy)
# A service breaks. Enter surgical mode:

agent → overlay_add("patch-mode")
# → Next turn: patch-mode rules injected into context
# → Agent investigates, applies fix, validates

operator → "good, integrate it"

agent → overlay_remove("patch-mode")
# → Back to anton. Auto-commits. Kicks off image rebuild.

Overlays are controlled by the base profile’s allowedOverlays whitelist in profile.yml:

allowedOverlays:
  - patch-mode
  - router

Agents can shift between approved modes but cannot escalate to unapproved profiles. The whitelist is the blast radius control.

Available as MCP tools (overlay_add, overlay_remove, overlay_refresh, profile_list, profile_current) inside any session via the hooks-utils server.

Full docs: Runtime Overlays


Next: Pillar 2 — Guardrails — What your agents are protected from.