TRENCHWORK
Install Portal
Operator reference

Control

How the profile + capability system works, and the full CLI control surface — flags, env vars, config files, slash commands.

How it works

Erosolar is a single binary with a profile selection at startup. The profile picks the system prompt, the default model, and — most importantly — the tool inventory the agent sees. There are three profiles:

erosolar-code

Default coding agent. Tool inventory: filesystem (Read / Write / Edit), Bash, Glob/Grep, Web (fetch + search), HITL, TodoWrite, Memory, Skills, Notebook, Worktree, PlanMode, Monitor, Schedule, Trigger, AskUserQuestion / PushNotification, MCP. Same shape as Claude Code with a few additions.

variant-research

Authorized variant-discovery / exploit-research. Adds Kali wrappers (sqlmap, gobuster, ffuf, hydra, john, hashcat, masscan, etc.), AFL++ fuzzing, gdb / pwndbg triage, pwntools, binary analysis (objdump, readelf, radare2, checksec), Ghidra headless. Terminal phase is coordinated disclosure.

engagement-delivery

Same offsec capability surface as variant-research. Differs in the terminal phase: requires an active engagement record (USG contract / task-order / defense-prime engagement / published bug-bounty program) at phase.intake; refuses to advance without one.

Capability gating is enforced in code. The default coding profile cannot load offsec tools — even if a configured MCP server tries to surface them. The hardening tests at test/v1.5-capability-gating.test.ts + test/capability-separation.test.ts fail CI on any regression.

Selecting a profile

Two ways, in priority order:

erosolar --profile variant-research            # explicit flag
EROSOLAR_PROFILE=variant-research erosolar     # env var
erosolar                                       # default → erosolar-code

Per-profile env overrides

Each profile has its own env namespace formed by uppercasing the profile name. Override the model, provider, or system prompt without recompiling:

VariableEffect
EROSOLAR_CODE_MODELOverride default model for the coding profile.
EROSOLAR_CODE_PROVIDEROverride default provider (anthropic / openai / deepseek / google / xai / ollama / qwen).
EROSOLAR_CODE_SYSTEM_PROMPTReplace the system prompt entirely (rulebook still loads).
VARIANT_RESEARCH_MODELSame, for the offsec variant-research profile.
ENGAGEMENT_DELIVERY_MODELSame, for the engagement-delivery profile.

If the model env hints at a different provider than the explicit provider env, the model wins. The CLI emits a "modelLocked" / "providerLocked" status badge so it's visible in /status.

Slash commands

In-session control. Top of the inventory:

CommandUse
/modelPick model + reasoning effort.
/approvalsConfigure what runs without confirmation (per-tool).
/toolsToggle individual tool suites on / off.
/mcpInspect / reconnect configured MCP servers.
/skillsBrowse skills loaded from .erosolar/skills/.
/secretsSet / unset API keys (DeepSeek, Anthropic, Tavily, etc.) in the OS keychain.
/thinkingSet extended-thinking depth.
/statusShow profile, model, provider, balance, locked state.
/doctorRun startup health checks (auth, model, balance, hooks, MCP).
/checksRun validation suite against the current workspace.
/reviewReview staged changes / current branch.
/diffShow pending diff.
/initGenerate AGENTS.md / CLAUDE.md-equivalent for this repo.
/compactSummarize the conversation to free context.
/newStart a fresh session in the same shell.
/undoRoll back the last agent-applied change.
/refresh-modelsRe-discover available models from each provider.
/featuresList active feature flags.
/evolveRun the self-improvement / regression-watch loop.
/testRun the project's test command.
/helpFull slash-command list (44 commands).
/logout · /quit · /exitSession controls.

Config files (project-local under .erosolar/)

PathPurpose
.erosolar/settings.jsonHooks (PreToolUse / PostToolUse / SessionStart / Stop / UserPromptSubmit) + tool toggles. Same shape as Claude Code's settings.json.
.erosolar/mcp.jsonMCP servers. Each server can declare a profiles: [...] allow-list — server tools surface only for matching profiles.
.erosolar/skills/<name>/SKILL.mdReusable playbook the agent can invoke.
.erosolar/memory/Persistent memory across sessions.
.erosolar/cron.jsonLocal cron entries. Mirrored to Firestore via Lambda cliCronUpsert when authenticated; the EventBridge tick fires matching entries server-side.
.erosolar/triggers/<id>.jsonRemoteTrigger drop files. The webhook relay (POST /api/cliWebhook) writes here via Firestore.
.erosolar/plans/<id>.jsonEnterPlanMode persistence.
.erosolar/worktrees/<id>/Live worktrees created by EnterWorktree.
~/.erosolar/auth.jsonFirebase ID token + refresh token. Mode 0600. Used by all Lambda calls.

MCP server tenant-mount example

An offsec MCP server that should only mount for the variant-research / engagement-delivery profiles:

{
  "mcpServers": {
    "kali-server": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-mcp-kali-server"],
      "profiles": ["variant-research", "engagement-delivery"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"]
    }
  }
}

The github server has no profiles field — it mounts for all profiles (back-compat default). The kali-server only surfaces for the offsec profiles, so a default coding session never sees its tools even if the config is present.

Hooks

Shell-command hooks fire around tool execution and session lifecycle. Same contract as Claude Code: the command receives a JSON envelope on stdin, can pass through, block, or shape the result via JSON on stdout. Configured in .erosolar/settings.json:

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "/path/to/audit-bash.sh" }] }
    ],
    "PostToolUse": [
      { "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "/path/to/lint-after-edit.sh" }] }
    ],
    "SessionStart": [
      { "hooks": [{ "type": "command", "command": "/path/to/session-banner.sh" }] }
    ]
  }
}

Hooks are best-effort: timeout / error / malformed JSON is logged and skipped, never crashes the agent.

Diagnostic env vars

VariableEffect
EROSOLAR_DEBUG=1Verbose debug logging.
EROSOLAR_INK_DEBUG=1Ink (terminal UI) trace logging.
EROSOLAR_PLAIN_OUTPUT=1Force plain output mode (no colour, no Ink). Useful for CI / pipes.
EROSOLAR_DISABLE_PORTAL_HITL=1Skip the portal HITL bridge for AskUserQuestion in non-TTY runs (returns "cancelled" instantly).
EROSOLAR_AGENT_RUN_TIMEOUT_MS=<ms>Per-turn agent timeout (default unbounded).
EROSOLAR_PRESERVE_HOME=1Don't sandbox $HOME for Bash tool invocations.
EROSOLAR_INK=0Disable Ink renderer (force readline shell).
EROSOLAR_DISABLE_PROJECT_REGISTRATION=1Skip the projects-rendezvous fire-and-forget call at session start.
EROSOLAR_ENABLE_PROJECT_REGISTRATION=1Opt-in: register offsec-profile sessions to the portal projects list (with host + owner masked).
Capability gating is non-negotiable. The default coding profile (erosolar-code) will not load offsec tools at runtime, will not surface offsec MCP servers, and will not load the offsec system-prompt addendum — by design. If you need both surfaces in one session, switch profiles; don't try to merge them. See the rationale in CLAUDE.md "Capability separation" + the v1.5 hardening test.

Read next