PROFILES

Switchable agent personalities: personal / coder / ops / research. How to define your own.

03 / 14·guide·v0.2.81

A profile is alpi's core isolation primitive: one directory on disk, one identity, one set of credentials, one memory, one set of skills, one peer list, one model choice. Everything else — the TUI, the gateway, ALP, the scheduler — operates inside a profile.

If you only ever use alpi for yourself on one machine, you can ignore this doc: you have a profile (it's called default) and things just work. This doc is for everyone else.

Where a profile lives

The active profile is resolved in this order:

  1. ALPI_HOME env var — absolute override, bypasses everything.
  2. -p <name> / --profile <name> CLI flag (propagates via ALPI_PROFILE env var to every subprocess).
  3. ALPI_PROFILE env var.
  4. Default (~/.alpi/).

alpi profile list shows all profiles with their model, size on disk, and active marker.

What's isolated per profile

Everything that represents state, identity, or cost:

Under {home}/Isolated per profileWhy it matters
config.yamlModel, fallbacks, tool limits, gateway config, MCP servers.
.envAPI keys. A leak in one profile doesn't touch the other.
memories/ (USER.md, MEMORY.md, AGENT.md)Your identity and what alpi remembers.
sessions/<id>.jsonTurn-by-turn chat log.
sessions/_gateway_map.jsonPer-chat session threading.
skills/Installed skills (live under this profile's allowlist).
alp/ (peers.yaml, socket, keypair)ALP identity + pinned peers. Two profiles on the same machine are two distinct peers.
schedule/jobs.jsonCron + one-shot jobs.
logs/gateway.log, schedule.log, alp.log, agent.log, approval.log.
cache/ (tts, stt, inbound voice)Audio cache.

Not isolated (shared globally by design):

Creating and removing profiles

alpi profile create work       # bootstraps the tree with defaults
alpi profile list              # shows all profiles, active one flagged
alpi profile remove work       # deletes after safety checks + confirm

profile remove is the happy-path CLI — works when the profile has no system services installed. When it does, it redirects to alpi -p <name> setup → Delete profile, which is the canonical one-shot flow: uninstalls every registered service (gateway / schedule / alp), rmtree's the profile home, and exits. CLI is kept for scripting and empty-profile cleanup; the wizard is the path most users want.

Every command in alpi's CLI accepts -p <name> to scope to a profile:

alpi -p work                   # launch TUI for the work profile
alpi -p work setup             # configure the work profile
alpi -p work gateway start     # run the work profile's gateway
alpi -p work peers list        # list peers pinned by the work profile

Profile identity in ALP

Each profile has its own Ed25519 keypair at {home}/alp/secrets/alp_key.{pem,pub}. The base64-encoded public key is the profile's cryptographic identity on the ALP network — it's what other profiles (on this or other machines) pin when they add you to their peers.yaml.

Consequence: two profiles on the same machine (default and work) are not the same peer. They have distinct pubkeys and distinct socket paths. They can talk to each other over ALP.1 exactly like they'd talk to a profile on a different machine over ALP.2.

Rotation is deliberate: delete alp/secrets/ and the next alpi alp start generates a fresh pair. Every peer who pinned the old pubkey must update their entry — rotation is an outage for the peer mesh, not a silent operation. Treat it the way you'd treat rotating an SSH key.

When to create a new profile

The axis is identity + stakes, not "I want different chats". Create a new profile when:

Not a reason:

Cost of a profile

On disk: a fresh profile is ~10 KB (config + memory seeds + empty directory tree). After a few weeks of use, expect 5–50 MB depending on voice-cache and session-history retention. The TUI top bar surfaces the live size next to the profile name; the cleanup wizard (alpi setup → Cleanup) reclaims audio cache, old sessions, rotated logs, and schedule output on demand.

On CPU / memory: a profile not in active use costs nothing. Each running surface — TUI instance, gateway daemon, schedule daemon, ALP listener — is its own process, and each of those can be stopped, installed as a service, or run ad-hoc.

Common patterns

Personal + work on one machine

~/.alpi/                     → personal (default)
~/.alpi/profiles/work/       → work

Both profiles' gateways can run simultaneously (each with its own launchd / systemd unit). Both can be ALP peers of each other if you want cross-profile handoffs (@work ... from personal).

Per-employee in an organisation

~/.alpi/profiles/jane/
~/.alpi/profiles/raj/
~/.alpi/profiles/mia/

Each user's profile holds their own identity, their own API key (or the org's shared one via .env), their own memory. Discovery happens via peers.yaml at onboarding — the IT admin seeds each new profile with the pinned pubkeys of the shared services (home-server, tools-bot). See DEPLOYMENTS.md for the enterprise topology in full.

One machine, many service identities

~/.alpi/profiles/assistant/   → personal daily driver
~/.alpi/profiles/researcher/  → read-only research agent for the family
~/.alpi/profiles/cron/        → runs scheduled jobs, no gateway

Each profile can have a completely different model, a different sandbox posture, a different memory, and expose a different capability surface in ALP. This is how "an army of alpis" gets built: granular identity per role, ALP as the coordination layer.