Vibestrate
Vibestrate
docs

Profile

A saved preset that says how strong and expensive a role runs - a provider, its model, and the effort level.

In simple words

A Profile decides how strong and expensive a role runs. It is a saved preset bundling three things: where the work happens, which model, and how hard that model thinks.

Think of the drive modes on a car: Eco and Sport change how hard the engine works, not who is driving.

Profiles in the dashboard sidebar holds them, one card each, grouped under the provider they run on. The page header counts them and flags any that have gone unusable:

Tip

A role points at a profile, never at a model. That indirection is the point: swap the model for six workers by editing one card.

The claude-balanced profile card, filed under a claude heading. It is marked used by 6 roles. Three tiles read claude provider, default model, medium effort. Below them are Provider, Label, Model, Max tokens and Timeout fields, and an Effort scale from Faster to Smarter offering low, medium, high, xhigh and max, with medium selected.

The tiles say what it resolves to today and the fields under them are where you change it. Edit this one card and all six roles run on the new setting from the next run.

Did you know

The effort scale is the provider’s own, not one Vibestrate invented. claude offers low, medium, high, xhigh and max; codex offers a different five; the Gemini CLI exposes none at all and its cards say so. A provider whose reasoning is a numeric budget rather than a level gets no effort knob, instead of a fake one.

When you would make another

New profile in the page header opens the create form; Duplicate on a card copies an existing one under a new id, and Delete warns you first if a role still points at it.

A cheap one and a strong one Keep claude-balanced and a claude-cheap, and point the mechanical roles at the cheap one.

Cross-vendor review Make a profile on a second provider and point only the reviewer at it. Now the diff is read by something that did not write it.

A slower, deeper planner Same provider, effort set to max, pointed only at the planner.

A local one A profile on an Ollama provider, for work that must not leave the machine.

A role card on the Crew page can also mint one: New profile there creates the profile and assigns it to that role in a single step.

Where a profile sits

Flow step Seat Role Profile Provider review -> reviewer -> reviewer -> claude-balanced -> claude-code

Two roles can share one profile, and a single role can run on a stronger profile for one step through a step override.

The knobs reach the real provider

A profile’s settings take effect on both CLI and HTTP providers: a CLI provider gets a real flag, an HTTP-API provider the equivalent request-body field. It changes what gets spawned or sent, not only what gets written down.

Each knob appears only where it is wired to something real:

claude: low/medium/high/xhigh/maxcodex: minimal/low/medium/high/xhighOpenAI HTTP: minimal/low/medium/high
effort honoreda level the provider supports, applied as a real flag or request field
effort_ignoreda level outside the provider's real ones: the run warns rather than dropping it quietly

The same rule is why there is no per-profile spend dial. An earlier version had a budget field that nothing read at runtime, so it was removed, and a leftover budget: key in an old project.yml is ignored on load. Spend is controlled where it bites: the per-turn output cap in Max tokens, and a project-level daily cap (vibe budget) that stops or downgrades runs.

What a profile carries

Eight fields, five of which default to null, meaning whatever the provider does by default. That is why a fresh project runs with almost nothing set.

FieldWhat it is
providerThe provider entry this profile runs on. The one required field.
labelWhat the dashboard shows. Defaults to the profile id.
modelThe provider’s own model id. null = its default.
powerThe effort level, provider-specific on purpose. null = the provider exposes none.
maxTokensCap on output tokens for a turn, where the provider supports one.
timeoutMsWall-clock cap for a turn. Unset means no cap.
disallowedToolsProvider tool names this profile may not use.
providerOptionsRaw provider-specific options, for what the fields above do not reach.
Crew Role Profile Provider provider -> Provider model string | null power string | null maxTokens number | null timeoutMs number | null disallowedTools string[] | null The profile is the join: the only place a model, an effort level, a token cap and a timeout are named together. Five of the six default to null: whatever the provider does by default. timeoutMs unset is what an unattended run has to bound another way.

The profile is the join. It is the only place a model, an effort level, a token cap and a timeout are named together.

timeoutMs being unset is why an unattended run needs the inactivity watchdog: with no cap and no watchdog, a provider CLI that wedges holds the run open forever. See Safety.

Write capability is deliberately absent. It is resolved per turn from the run’s permission mode, never stored here, so the same role is write-capable in one run and read-only in the next without editing anything. The shape is profileConfigSchema in src/agents/profile-schema.ts.

The model must exist at the provider

A profile naming a model its provider does not offer is a run that fails the moment it spawns, so Vibestrate checks the pair on write and keeps checking it, because a model can stop existing without anyone touching the config.

How strict depends on where the list came from:

  • From the provider itself. At the start of every run Vibestrate probes the providers that can report their own bundled catalog, which today means codex debug models --bundled, and caches what comes back. It is an offline read with no network. For a provider on that list the Model field becomes a picker, and saving a model outside it is refused, with the available ids named.
  • From the built-in list. The curated fallback, which is what every other provider gets. That list goes stale the day a provider ships a model, so a value outside it is allowed and reported as unverified rather than wrong. Refusing here would block every new model on release day.
model existsin a list the provider itself produced
unknown modelabsent from the provider's own list: the write is refused, and an existing one is flagged
unverifiedonly a curated list to check against: allowed, reported as unproven

Such a profile is surfaced, not carried in silence. Its card turns amber and states the fault; the page header counts it and offers Pick a model for that profile, which puts your cursor in the Model field. The Dashboard raises an amber banner naming it too, because the run that would fail has not started yet.

Fencing off a role’s tools

A profile can name provider tools a role may not use, with disallowedTools. The main use is ["Task"] on the write seats of a strict flow: it stops a seat’s agent spinning up nested sub-agents that would schedule work outside the flow’s plan, so what actually ran stays legible.

Neither the page nor vibe profile set writes this one, so add it by hand:

profiles:
  strict-writer:
    provider: claude
    model: opus
    # no nested sub-agent orchestration
    disallowedTools: ["Task"]
When it goes wrong

This is about legibility, not a write guard. disallowedTools keeps the flow the single scheduler; it is not what stops a read-only seat from writing (that is the seat’s permission mode). It is also best-effort - it blocks the default sub-agent path, not every possible fan-out. Off by default: with no list, nothing is disallowed.

From the terminal

vibe shell manages the same presets on its [4] Profiles page: e/E cycle effort, m/M the model, n new, d duplicate, x delete, and r re-probes the provider catalog.

The command line is the automation path:

vibe profile list
vibe profile add claude-max --provider claude --model opus --power max
vibe profile set claude-max --power high
vibe profile duplicate claude-max claude-cheap
vibe profile remove claude-cheap

vibe run "task" --profile claude-max
vibe run "task" --step-profile implement=claude-max

--profile applies to every seated step in that run; --step-profile swaps one step and leaves the rest alone.

Over HTTP the page’s own routes are GET/POST /api/profiles, POST /api/profiles/:id/duplicate, PATCH and DELETE /api/profiles/:id, plus GET /api/providers/catalog. Each profile in that list carries usedBy, providerConfigured, and a modelStatus / modelIssue verdict. The catalog feeds the model and effort options, and its sources map says whether each provider’s list came from the provider or from the built-in fallback.

A profile is a block under profiles: in .vibestrate/project.yml, and a role points at one by its id. The annotated crew config lists every field with a comment on what it does.

Next: provider is the tool a profile actually runs on.

© 2026 Vibestrate
v0.4.3 Shonshon - Evolving Technologies