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:
--profile <name>.VEYYON_PROFILE. An explicitly emptyVEYYON_PROFILE=forcesdefault, bypassing step 3.defaultProfilein the global~/.veyyon/config.yml: set or show it withveyyon profile default [name], or edit it on the Global tab of/settings.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;-pis--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 myworkinstalls a managed block in your shell rc (seecli/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:
| Command | Effect |
|---|---|
/profiles, /profile | Open the profile picker. |
/profile list | Print 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
newcreates~/.veyyon/profiles/<name>/agent/with the expected identity dirs (skills/,commands/, …).--from default(default) seedsconfig.yml, keybindings, MCP, skills, and other identity files from the default profile. Sessions, blobs, and databases are not copied.--from blankcreates an empty agent tree.--from devseeds a blank tree, then enables the study features. It setssession.instrumentationtoultraand enables Argot, the experimental token-shorthand codec. Use this profile when you want to runveyyon session statsor 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.basickeeps the elementary timing and state record;richadds context and communication detail;ultraadds fingerprints, abort state, links, routes, cache and reasoning detail, and upstream-provider details.rmrejects the default profile, the active profile, and destructive deletes without--yes. If you remove the profile that is set as the launch default, itsdefaultProfilepointer 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 globaldefaultProfile(which profile a bareveylaunches);default --clearremoves 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.