Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Profiles

A profile is a directory under ~/.veyyon/profiles/<name>/ holding that identity’s settings, sessions, MCP, skills, hooks, logs, plugins, and caches. One binary; multiple profile trees.

Roles and profile layout: Roles and profiles.

Layout

Every profile, including default, lives under the same tree:

~/.veyyon/
  config.yml            # GLOBAL settings (defaultProfile, ...), not a profile's settings
  install-id            # per-install UUID, shared by all profiles
  profiles/
    default/            # the default profile, a real profile like any other
      agent/            # settings, sessions, skills, MCP, keybindings, ...
      logs/  plugins/  cache/  wt/  ...
    work/
      agent/
      ...

See File locations for the full per-profile tree and the one-time migration from the legacy bare-root layout.

Which profile launches

Resolution order for every veyyon / vey invocation:

  1. --profile <name>.
  2. VEYYON_PROFILE. An explicitly empty VEYYON_PROFILE= forces default, bypassing step 3.
  3. defaultProfile in the global ~/.veyyon/config.yml: set or show it with veyyon profile default [name], or edit it on the Global tab of /settings.
  4. default.

What a profile owns (shipped)

When a profile <name> is active, native Veyyon paths resolve under:

~/.veyyon/profiles/<name>/agent/

That resolution is uniform across settings, sessions, blobs, slash commands, sticky rules, prompts, hooks, tools, extensions, skills, MCP, keybindings, theme, the profile AGENTS.md, RULES.md, and PROMPT_SECTIONS/. Operational state (logs, plugins, caches, worktrees) resolves under the profile root ~/.veyyon/profiles/<name>/ the same way. A profile never reads another profile’s tree at runtime.

Provider credentials are the one exception: by default they live in a machine-wide store (~/.veyyon/shared-auth/agent.db) that every profile reads, so you sign in once. Set profileSharing: false in the global ~/.veyyon/config.yml (or toggle it on the Global tab of /settings) to give each profile its own private credential store instead. See Signing in › Credentials are shared across profiles.

Keybindings: each profile owns agent/keybindings.*. New profiles seeded with veyyon profile new --from default copy the default profile’s keybindings once. On first launch of an older named profile that has no keybindings file, Veyyon performs the same one-time seed and logs it. There is no live merge from the default profile after that.

Project-level dirs (<cwd>/.veyyon, .claude, etc.) are not profile-scoped; they follow the working directory.

Other tools’ config (skills and CLAUDE.md/AGENTS.md written for Claude, Codex, and similar) is off by default and controlled per profile by discovery.importForeignConfig, so each profile decides on its own whether to ambiently read foreign files or run native-only. Another tool’s own global dir (~/.claude/skills, …) cannot be relocated into a profile, see Skills › Profiles isolate skills.

Activating a profile

  • CLI: veyyon --profile <name> (no short form; -p is --print).
  • Env: VEYYON_PROFILE=<name>.
  • TUI: /profile <name> ends the current conversation and relaunches Veyyon on that profile (a fresh session: profiles are chosen at process start, so there is no hot-swap). Bare /profile (or /profiles) opens the profile picker described below.
  • Shell alias: veyyon --profile work --alias mywork installs a managed block in your shell rc (see cli/profile-alias.ts).

TUI profile commands

/profiles and /profile are the same command. Run it with no arguments to open the profile picker, an interactive dialog that lists every profile (the active one marked) plus a Create new profile row. Select a profile to open its action menu: Switch to it, Rename it, or Delete it (switch and delete are hidden for the active profile, and the default profile is never offered for deletion). The picker is the fastest way to manage profiles without remembering the verb syntax.

You can also type any verb directly:

CommandEffect
/profiles, /profileOpen the profile picker.
/profile listPrint the profile list as text (active marked with *).
/profile <name>Switch to <name> (relaunches as a fresh session).
/profile switch <name>Same as /profile <name>.
/profile new <name>, /profile create <name>Create <name>, then open the copy-items picker.
/profile rename <old> to <new>Set the display name of <old> to <new>.
/profile rename to <new>Rename the active profile.
/profile rm <name>, /profile delete <name>Delete <name> after a confirmation. Rejects the active and default profiles.

Choosing Create new profile or Rename in the picker prefills the composer with the matching command (/profile new or /profile <name> rename to ) so you finish by typing the name and pressing Enter. Name entry always flows through the same typed command, so there is one place that creates and renames.

Profile names and renaming

A profile’s directory name (~/.veyyon/profiles/<name>) is its stable identity and never changes. Each profile can additionally carry a display name, the profile.displayName setting, stored in that profile’s own config.yml:

  • Settings: /settings › Interaction › Profile › Profile Name.
  • TUI: /profile rename to <new> renames the active profile; /profile <name> rename to <new> (or /profile rename <name> to <new>) renames another one. The default profile is renamable too. The profile picker’s Rename action prefills this command for you.

/profile list shows name (Display Name) when they differ, and /profile <input> resolves a directory name first, then a unique display name. A copied settings file never contains the source’s display name, profile new clears it so two profiles cannot answer to one name.

Because directory names resolve first, a rename warns you when the display name you chose will not switch back to this profile: when it matches another profile’s directory name (that directory wins), or when it duplicates another profile’s display name (the switch becomes ambiguous). The rename still applies, so use a distinct name if you want to switch by it.

Creating and managing profiles

$ veyyon profile list
$ veyyon profile new work
$ veyyon profile new dev --from dev
$ veyyon profile new bounty --from blank
$ veyyon profile rm work --yes
$ veyyon profile default work
  • new creates ~/.veyyon/profiles/<name>/agent/ with the expected identity dirs (skills/, commands/, …).
  • --from default (default) seeds config.yml, keybindings, MCP, skills, and other identity files from the default profile. Sessions, blobs, and databases are not copied.
  • --from blank creates an empty agent tree.
  • --from dev seeds a blank tree, then enables the study features. It sets session.instrumentation to ultra and enables Argot, the experimental token-shorthand codec. Use this profile when you want to run veyyon session stats or backtest a stored session. Instrumentation records structured, redacted session data: lifecycle and checkpoints, task transitions, tool and model timing, context attribution, agent-message delivery, and analysis rollups. basic keeps the elementary timing and state record; rich adds context and communication detail; ultra adds fingerprints, abort state, links, routes, cache and reasoning detail, and upstream-provider details.
  • rm rejects the default profile, the active profile, and destructive deletes without --yes. If you remove the profile that is set as the launch default, its defaultProfile pointer is cleared at the same time, so the next launch falls back to the default profile instead of a directory that no longer exists.
  • default [name] shows or sets the global defaultProfile (which profile a bare vey launches); default --clear removes it.

Reading the size in profile list --json

veyyon profile list --json prints one object per profile. Two of its fields describe disk usage:

$ veyyon profile list --json
[
  {
    "name": "work",
    "rootDir": "/home/you/.veyyon/profiles/work",
    "bytes": 41238904,
    "bytesComplete": true
  }
]

bytes is the total size of every file under rootDir. bytesComplete reports whether that total is the whole story. The walk skips anything it cannot read rather than failing the listing, so a directory with no read permission would otherwise make a large profile look small. When a path is skipped, bytesComplete is false, bytes becomes a lower bound, and the skipped paths are written to the profile’s log with the message Profile size is incomplete; some paths could not be read. Check that log when you need to know which path to fix.

A profile whose directory does not exist yet reports "bytes": 0 with "bytesComplete": true: there is nothing there, which is a measurement rather than a failure.

In the TUI, /profile new <name> (or /profile create <name>) opens a picker listing every carry-over item (AGENTS.md, settings, MCP servers, SSH targets, skills, commands, tools, prompts, themes, extensions, keybindings), each individually toggleable (all selected by default). The new profile is seeded from the active profile with exactly the chosen items. Deleting is available too: /profile rm <name> (or the picker’s Delete action) removes a profile after a confirmation, and rejects the active and default profiles. See TUI profile commands for the full verb list.

The instruction row copies only AGENTS.md. A profile switch never carries RULES.md; change it through settings or copy it manually when that is your intent.

You can still create a profile implicitly by running veyyon --profile <name> once; use profile new when you want seeding without launching the TUI.

Onboarding import

On the first interactive run of a profile that has not completed setup, the setup wizard scans the machine for user-level config written for other tools (skills and CLAUDE.md/AGENTS.md from Claude Code, Codex, Cursor, and similar) and offers each item for import into the active profile. Imports copy: skills land in the profile’s skills/, instruction files append to the profile’s AGENTS.md under a source marker (re-imports are idempotent). The scan runs no matter how discovery.importForeignConfig is set, because importing is how foreign config comes in by default: ambient loading of the originals stays off unless you turn that setting on.

Do not document inline [profiles.<name>] tables or standalone <name>.config.yml files as shipped; settings use config.yml under the active agent dir.

Model policies and roles (per profile)

Each profile’s config.yml defines its interactive default, optional roles, subagent policy, and compaction policy:

modelRoles:
  default: openai/gpt-5             # interactive (also set live with /model)
  plan: openai/o3
  smol: deepseek/deepseek-chat
subagent:
  model: deepseek/deepseek-chat     # blanket model chain for subagents
  thinkingLevel: high
  agents:
    scout:
      enabled: false
    reviewer:
      thinkingLevel: auto
compaction:
  model: openai/gpt-5-mini
  strategy: summary
  threshold: "80%"

Unset roles and model chains inherit the live main model at use time, so switching with /model changes them immediately. Per-agent subagent settings override the blanket subagent model and effort; an unset per-agent value falls back to that blanket policy. Only an explicit assignment pins a different model. Switching profiles switches all of these assignments with the profile.

See also