Core Concepts

Context Personas

One runtime, many verticals. A persona reshapes the whole context surface — tool set, read mode, compressor, chunker, intent taxonomy and sensitivity floor — for a domain in a single switch, while the coding default stays exactly as it was.

LeanCTX ships tuned for software work: the full Power tool surface, a code-oriented intent taxonomy, identity compression. A persona reshapes that whole context surface for a different domain (prospecting, research, support, data) in one switch, and leaves the coding default untouched.

Built-in personas

Each persona is a real, shipped bundle. The tool surface, read mode, compressor, chunker, intent taxonomy and sensitivity floor all move together:

PersonaTool surfaceRead modeCompressor · chunkerSensitivity floor
coding (default)Power profile — full surfaceautoidentity · linespublic
researchStandard profilemapmarkdown · paragraphpublic
supportStandard profileautoprose · paragraphinternal
data-analysisStandard profilemapidentity · linesinternal
lead-gen (alias sales)Custom 6-tool surfacemapprose · paragraphconfidential

The lead-gen surface is genuinely narrowed to six prospecting tools (the refactor/code tools are gone):

ctx_read · ctx_search · ctx_url_read · ctx_knowledge · ctx_semantic_search · ctx_session

Selecting a persona

Set it via environment variable (or config.persona):

export LEAN_CTX_PERSONA=lead-gen     # or: research · support · data-analysis · coding

Persona::resolve reads LEAN_CTX_PERSONAconfig.persona › default coding. An unknown name falls back to coding, never an error. An explicit tool profile (set with lean-ctx tools) always wins, so existing coding installs are never disturbed.

Ship your own vertical — no fork

Not one of the built-ins? Drop a declarative persona file in your personas directory (default <OS-config-dir>/lean-ctx/personas, override with LEAN_CTX_PERSONAS_DIR) and select it by name:

# <personas_dir>/compliance.toml
name = "compliance"
tool_profile = "custom"
tools = ["ctx_read", "ctx_search", "ctx_semantic_search", "ctx_knowledge"]
default_read_mode = "map"
compressor = "prose"
chunker = "paragraph"
intent_taxonomy = ["scan", "flag", "cite", "report"]
sensitivity_floor = "confidential"
export LEAN_CTX_PERSONA=compliance

Under the hood runtime-wired since v3.9.2

Persona resolution lives in rust/src/core/persona.rs. Since v3.9.2, every field is wired into the runtime — none of this is a prompt hint:

  • Tool surface — the resolved profile drives list_tools, so the advertised tool set genuinely shrinks or grows per persona. An explicit profile (lean-ctx tools) still wins.
  • Read modectx_read resolves its mode as: explicit mode argument > policy pack > persona > profile default. auto means the persona has no opinion.
  • Compressor & chunkerctx_url_read runs flowing-text modes (auto/markdown/text/transcript) through the persona compressor, and token-budget cuts land on the persona chunker's boundaries (paragraphs, line windows) instead of mid-sentence. Extractive modes (facts/quotes/links) stay verbatim to protect citations.
  • Intent taxonomy — non-coding personas append a PERSONA/INTENTS/DEFAULTS block to the MCP session instructions, so the agent speaks the domain's vocabulary. The coding default leaves the prompt byte-identical to a persona-less install.
  • Sensitivity floor — folded into [sensitivity] enforcement: a floor above public switches enforcement on and can only tighten the configured floor, never loosen it. Same governance layer as roles and budgets.

The active persona is reported at GET /v1/capabilities under server.persona, so orchestrators can branch on it instead of guessing.

Where to go next