Agent profiles: installable lines of work — "el perfil", "perfiles disponibles", "instalá un perfil" — secretary, project manager and others. Load when the user wants to install, activate, configure, diagnose or remove one, or asks why the agent behaves the way it does. Triggers: 'install a profile', 'apx profile', 'what profiles are there', 'activate the secretary', 'go back to vanilla', 'change my agent's schedule', 'why does it message me'.
Scanned 9/27/2026
npx -y skills add agentprojectcontext/apx --skill apx-profile --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Apx Profile?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/agentprojectcontext-apx-profile)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: apx-profile
description: Agent profiles: installable lines of work — "el perfil", "perfiles disponibles", "instalá un perfil" — secretary, project manager and others. Load when the user wants to install, activate, configure, diagnose or remove one, or asks why the agent behaves the way it does. Triggers: 'install a profile', 'apx profile', 'what profiles are there', 'activate the secretary', 'go back to vanilla', 'change my agent's schedule', 'why does it message me'.
---
# apx-profile
A **profile** is an installable package that gives the super-agent a line of work: a
prompt block, its own routines, and the white-label settings the owner fills in. With no
profile active APX is *vanilla* — the system prompt is byte-identical to a clean install.
Three words that are easy to confuse. Keep them apart:
| Term | What it is | Where it lives |
|---|---|---|
| **profile** | an installable line of work (this skill) | `~/.apx/profiles/`, `config.profile` |
| **persona** | the super-agent's visible NAME | `~/.apx/identity.json` → `agent_name` |
| project config | per-project overrides | `~/.apx/projects/<apx_id>/config.json` |
Installing and activating are **different operations**. `install` validates a package and
makes it reachable; `use` is the moment behaviour changes.
## Concrete CLI calls
```bash
# Discover
apx profile list # everything available, and which is active
apx profile show secretary # settings, token cost, where it came from
apx profile show secretary --preview # ...plus the rendered prompt block
# Install and activate
apx profile install secretary # a bundled id
apx profile install ./my-profile # a local package directory
apx profile use secretary # activates + installs its routines
apx profile use tutor --force # replace whatever is active
apx profile sync # re-read the active package from disk (after an APX update)
# Configure — this is where white-label happens
apx profile config # show current settings
apx profile config --set day_open_schedule="30 8 * * 1-5"
apx profile config --set nudge_budget_per_day=3 --set quiet_hours=22:00-07:30
apx profile config --set watch_schedule="0 */2 * * *" --set formality=vos
apx profile config --interactive # walk the whole schema
# Health and removal
apx profile doctor # what's missing for it to do its job
apx profile off # back to vanilla
apx profile uninstall secretary
```
## What each command actually does
- **`install`** validates the manifest, the schema and every template, then seeds the
settings with the schema defaults. It does **not** activate. A **local path** is copied
into `~/.apx/profiles/`; a **bundled** package is not — it is read in place so a later
`npm update` improves it instead of being shadowed by a stale copy.
- **`use`** writes `config.profile.active`, reloads the prompt, and installs the package's
routines (named `<profile-id>-<routine>`, marked `origin: "profile:<id>"`).
- **`off`** sets `active: null` and **disables** those routines. It deletes nothing —
settings, tasks, commitments and memory all survive, so `use` again restores everything.
- **`config`** validates against the schema and **really reschedules**: changing an opening
time moves the cron, it doesn't just edit JSON.
- **`uninstall`** removes the package and the routines it installed, but **keeps any routine
the user edited** and never touches one the user wrote. A bundled package can't be
deleted, so it gets a tombstone and can be reinstalled any time.
## Settings are per profile
`config.profile.configs[<id>]` holds each profile's own settings; `config.profile.config`
mirrors the active one. Switching A → B → A gives A its settings back rather than handing
it B's.
## When the user asks "why did it message me?"
Read the active profile's prompt block — `apx profile show <id> --preview` — and its
settings. Interruption budgets, quiet hours and staleness thresholds are all profile
settings, not core behaviour. If the answer is "it shouldn't have", the fix is usually
`apx profile config`, not a code change.
## Package layout
```
<id>/
profile.json # manifest: id, name, version, requires, prompt_budget_tokens
PROFILE.md # the always-on prompt block (template)
PROFILE.es.md # optional translations: PROFILE.<lang>.md
config.schema.json # the white-label settings, every one with a default
channels/<ch>.md # optional per-channel overlay, appended after the core file
routines/*.json # routines it installs
agents/*.md # specialists it adds to the vault
skills/<slug>/SKILL.md # its own operational procedures
```
**Template rules, enforced at install time** (installation fails, naming the variable):
- Only flat `{{single_word}}` names. `{{profile.name}}` cannot be substituted and is rejected.
- Every variable must resolve: a built-in (`owner_name`, `agent_name`, `owner_context`,
`profile_name`) or a schema property **with a default**. A property declared without a
default is rejected, because it would silently render as an empty string.
**In `routines/*.json`, settings render as VALUES, not as text.** The file is parsed first
and each string leaf rendered after, so a setting carrying quotes (a shell command with JSON
arguments, say) cannot break the document. Two consequences worth knowing:
- A `pre_commands` / `post_commands` entry that renders empty is dropped entirely, so an
optional command is just a setting defaulting to `""` — no empty shell step, no pre phase.
- `{{pre_output}}` is left alone by the renderer and filled by the routine runner at run
time. That is how a routine hands itself data without spending a tool call or a permission
on it — the secretary's `calendar_command` is the live example.
## A package updates, its installed routines do not
The prompt block is rendered every turn, so it improves the moment APX updates. Routines are
records in the super-agent's store, written at install time — nothing carries a better anchor
across. `apx profile sync` (and any settings save) re-renders them from the package on disk,
leaving settings, activation AND each routine's on/off alone — only `apx profile use` applies the
package's `enabled_by_default`. A package may ship routines OFF (company: only the weekly review
and monthly scorecard start on; the pulse, the decision brief and the councils are installed off —
`apx routine enable <name>` turns one on); `apx profile doctor` reports the drift so it is not silent. A routine the
owner edited is skipped forever, by design, which also means a profile SETTING that lands in
a routine stops taking effect on that routine once they have touched it.
## Channel overlays
`channels/<ch>.md` is rendered and appended after the core `channels/<ch>.md`, only on that
surface. Use it for judgement that must load deterministically where a decision is taken —
the rules for speaking unprompted belong in `channels/routine.md`, not in an on-demand
skill, because "should I interrupt?" is a decision the model may not know it is about to
take. Costs nothing on the channels that don't need it.
## The prompt budget is real
The block ships on **every turn of every channel**, on top of a ~2.5k-token base. A
package declares `prompt_budget_tokens`; exceeding it warns, exceeding 1.5× fails to
install. Check the real number with `apx profile show <id>` or
`node scripts/inspect-channel-prompts.js`.
## HTTP
`GET /api/profiles` · `GET /api/profiles/:id` (includes `preview`) · `GET /api/profiles/doctor` ·
`POST /api/profiles/install` · `POST /api/profiles/use` · `POST /api/profiles/off` ·
`POST /api/profiles/sync` (re-applies a package's routines after an update — `apx profile sync`) ·
`PATCH /api/profiles/config` · `DELETE /api/profiles/:id` ·
`POST /api/profiles/readopt` (force the active profile's routines back to the package, past the
user_modified/user_owned skips sync respects — `{ routine }` targets one, omit for all; the
web "Re-sync routines" button. It discards local edits to the affected routines.)
## Gotchas
- **`install` does not activate.** The most common confusion. Follow it with `use`.
- **One profile at a time.** Activating a second needs `--force`.
- **`off` is not `uninstall`.** `off` is reversible and keeps everything.
- **The vanilla invariant is load-bearing.** With no profile active the prompt must stay
byte-identical. If a change would alter that, it's a bug, not a feature.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!