Mapache Docs
The full technical reference for Mapache, mirrored from the project repository.
Overview
Mapache is an autonomous offensive-security agent. You give it an objective in plain language ("pentest 10.0.0.5", "find the IDOR in the app at http://target/") and it works the engagement one tool call at a time: it enumerates, exploits, escalates, and hands back a report of proven findings with remediation.
This directory is the full reference. Start with the overview, then dive into the area you care about.
First run
git clone https://github.com/slider-labs0/Mapache.git && cd Mapache
python3 -m venv .venv && source .venv/bin/activate
pip install -e . # installs the `mapache` command
mapache setup # interactive: pick a provider and a model
mapache serve # launch the agent
Requires Python 3.10 or newer. Kali or ParrotOS is the recommended platform because the offensive toolchain is packaged there. For local models install Ollama; for cloud models set the provider key and pass --allow-cloud.
Safety
Mapache is for authorized security testing only: engagements you own or have written permission to test. It enforces a rules-of-engagement scope, but scope is a guardrail, not a guarantee. You are responsible for staying in bounds and for complying with applicable law. See Execution and OPSEC for the guardrails.
Architecture
Mapache runs one execution path: a ReAct (reason and act) loop. There is no hidden planner pipeline and no separate executor. The agent observes, acts with one tool, reads the real result, and decides the next step. This page explains the moving parts.
The agent loop
core/agent_controller.py holds AgentController, the orchestrator. Its _agent_loop is the heart of Mapache:
- Build the prompt (system prompt, attack state, task list, relevant playbooks, recent history) with the context builder.
- Ask the model for the next action. Native tool-calling models return a structured tool call; models without native tool-calling return JSON that the loop parses.
- Dispatch the chosen tool, enforce the rules-of-engagement scope first, and capture the real output.
- Fold the result back into the attack state and the conversation, then loop.
The loop is bounded by MAX_ITERATIONS so it can never run away, and it stops early when the model produces a final answer, when a loop policy halts it, or when a budget is exhausted.
One tool per step
Reading each real result before choosing the next step is what keeps Mapache grounded. It does not invent endpoints or assume a scan result. It acts, observes, and adapts. The model can still batch several independent tool calls in a single turn (for example, scanning two hosts at once); those dispatch concurrently and fold back in the order the model stated.
Attack state and the conversation chain
core/conversation_chain.py holds ConversationChain, which tracks the attack state across turns: the target, open ports, services, the current phase, discovered vulnerabilities, captured credentials, and flags. Key behaviors:
- A freshly typed IP that differs from the current target overrides it and clears stale findings. This handles a lab machine getting a new IP mid-session.
- Rescan keywords clear cached ports so a fresh scan is not skipped.
- Tool outputs are compressed before they are re-injected, which prevents the context from overflowing on a long engagement.
- A persistent task list (todos) survives across turns. The model seeds it with a plan, updates item status, and the loop re-injects a
=== TASK LIST ===block every iteration so the model always sees mid-turn progress.
Phases and tool subsetting
Mapache models an engagement as phases: recon, enumeration, exploitation, post, and report. ConversationChain.active_tool_names exposes only the tools relevant to the current phase. This keeps the function-calling payload small enough for local models, which otherwise choke on a large tool schema. Certain tools (delegation, memory, generated tools, MCP tools) are pinned so subsetting never hides them.
The attack system prompt encodes a default workflow: recon, then enumerate, then exploit, then post, then report. It blocks exploitation before a scan has returned open ports, so the agent does not fire an exploit at a host it has not looked at yet.
The context builder
core/context_builder.py assembles the prompt and enforces a token budget (max_context_tokens, default 16384). It injects the system prompt, the live attack state, the task list, any relevant playbooks, and recent history. When native tool-calling is available, tool schemas go in the dedicated tools field; otherwise the tools are described in the prompt and the model is asked for JSON output.
Context compaction
When raw history outgrows its token budget, the controller summarizes the oldest turns into a running summary with a model call and drops those messages, instead of silently trimming them. The summary is prepended to the system prompt as "CONVERSATION SO FAR". Durable facts (targets, ports, versions, credentials, vulnerabilities, flags, paths, and what is pending) are kept verbatim. Compaction only fires when actually over budget and keeps a recent window, and it fails open to a plain trim if anything goes wrong.
Robust tool-call parsing
Local models mangle output in predictable ways. _parse_model_response tolerates JSON fenced in code blocks, JSON embedded in prose (a balanced, string-aware brace scan), and a missing type tag (inferred from the keys present). Output that clearly intended the protocol but is unusable is flagged as malformed; the loop feeds the error back and asks for a clean retry, bounded by MAX_REASKS. Incidental braces in a normal answer are not reasked.
Loop safety rails
- No-progress and duplicate-call guard: within a turn, an identical tool call (same name and args) runs once; later repeats are short-circuited with the cached result and a nudge to change approach. This fixes the "fetch the same URL five times" loop.
- Stall and loop detection aborts a turn early when the model spams duplicates or makes no progress, so a weak model does not burn the whole iteration budget going in circles.
- Answer general knowledge directly: definitions and facts the model already knows are answered in plain text without tools, and a blocked lookup falls back to the model's own knowledge rather than being reported as the final answer.
The event bus
core/event_bus.py is the pub/sub backbone. The loop emits events (tool calls, findings, delegations, scope refusals, steering, duplicate calls). Observers subscribe without driving the loop. The audit log and the TUI dashboard are both event consumers, which is why they never slow the agent down.
Mid-run steering
A frontend can call AgentController.steer(text) to redirect a turn already in progress. Queued messages are drained at the top of each loop iteration and injected as operator steering. A freshly typed target or a rescan updates the attack state without disturbing the in-progress turn. This lets you correct the agent live without restarting the session.
Middleware
core/middleware.py provides composable loop middleware. Shipped middleware includes budget enforcement (stop gracefully at a token or time cap), a human-in-the-loop checkpoint slot, an offensive-vaccine loop (turn each confirmed vulnerability into a detection and remediation note), and a reflection and tactical-staging step. Middleware is opt-in and inert unless configured.
Model routing and multi-model agents
Mapache can run on a single model or orchestrate several models inside one engagement, each owning a role. This page explains the routing strategies, how to configure a multi-model team, and exactly how a sub-agent decides which model controls it.
The mental model
Configuring several providers in mapache setup does not run them all at once. Nothing runs until you start a session and give it a prompt, and each session runs one engagement. Which model does the work is decided by three things:
- The model you pin at launch (
--model) or thedefault_modelin config. - The routing strategy (
--strategyordefault_strategy). - The optional per-role model map (
model_roles) and per-operator routing.
Strategies
A strategy decides how roles map to models. Roles are planner (strategy and decomposition), executor (runs the tools each turn, drives the loop), and verifier (checks the final answer). The ReAct loop itself runs as the executor role.
| Strategy | Behavior |
|---|---|
single (alias solo) | One model for every role: the model you pass with --model. No mixing. |
auto | Best-scoring model per role, drawn from the registry of available models. |
pipeline | Dedicated model per role: quality-weighted planner and verifier, speed-weighted executor. |
hybrid | Cloud planner and verifier plus a local executor. Requires --allow-cloud. |
swarm | Auto routing plus the multi-agent supervisor. Activates operator fan-out at launch. |
With a single model installed, every strategy collapses to that one model, so there is no behavior change until you actually have more than one model available.
For a clean model-versus-model comparison, pin --strategy solo with each --model so one model does the whole engagement. For a collaborative team, use per-role routing or swarm as described below.
Running one model per demo
mapache serve --model deepseek-chat --strategy solo --allow-cloud
mapache serve --model kimi-k2-0711-preview --strategy solo --allow-cloud
mapache serve --model glm-4.6 --strategy solo --allow-cloud
Run them one after another. solo forces every role to the pinned model, so each run is purely that model.
Running several models as one team
Assign models to roles with model_roles in the config. The setup wizard offers this as its "customize per role" option, or you can write it directly. A compelling split for a cloud team:
{
"allow_cloud": true,
"default_model": "kimi-k2-0711-preview",
"default_strategy": "pipeline",
"model_roles": {
"planner": "deepseek-reasoner",
"executor": "kimi-k2-0711-preview",
"verifier": "glm-4.6"
},
"providers": {
"deepseek": { "kind": "openai_compatible", "base_url": "https://api.deepseek.com", "api_key": "${DEEPSEEK_API_KEY}", "models": ["deepseek-chat","deepseek-reasoner"], "enabled": true },
"moonshot": { "kind": "openai_compatible", "base_url": "https://api.moonshot.ai/v1", "api_key": "${MOONSHOT_API_KEY}", "models": ["kimi-k2-0711-preview"], "enabled": true },
"zhipu": { "kind": "openai_compatible", "base_url": "https://open.bigmodel.cn/api/paas/v4", "api_key": "${ZHIPU_API_KEY}", "models": ["glm-4.6"], "enabled": true }
}
}
The ${...} placeholders read from the environment, so no secret is written to disk:
export DEEPSEEK_API_KEY=sk-... MOONSHOT_API_KEY=sk-... ZHIPU_API_KEY=...
mapache serve --allow-cloud --verify
--verify is important for a three-model team, because that is what fires the verifier role. Without it, only the planner and executor participate. Explicit model_roles overrides win regardless of strategy, because the router checks overrides before it consults the strategy.
The TUI dashboard shows the live role-to-model map in a "Models" panel, which is a clean on-screen proof that several models are working the same case.
How a sub-agent chooses its model
When the lead delegates a subtask or the supervisor deploys a specialist, the child agent's model is decided by a four-layer pipeline in _spawn_and_run, applied in order.
1. Inherit the lead's model
The child starts on the lead's routed model. By default it is on the same routed brain as the lead.
2. OPSEC pin (sensitivity can force local)
OpsecPolicy.decide inspects the operator and the shared attack state. If the work is sensitive, either because the operator prefers local (loot, credentials, post-exploit) or because the shared state already holds captured credentials, the sub-agent is pinned to a local model even when the lead is allowed cloud. This keeps loot and credentials on the host. It is a no-op when cloud is disabled (everything is local anyway), and it falls back to the current model with a warning if no local model is installed.
3. Per-operator role routing (the important layer)
Each operator declares a model role, and the child routes to that role's model through the routing engine, which honors your model_roles map. Reasoning-heavy specialists declare planner; action specialists default to executor:
| Operator | Declared role | Example model from the team above |
|---|---|---|
| recon, web, exploit, post, cloud, mobile, wireless, iot, ics, general | executor | Kimi |
| osint, exploit_dev, contract_auditor, reverser, analyst, coder | planner | DeepSeek-Reasoner |
verifier checkpoints (with --verify) | verifier | GLM |
Reasoning specialists get the reasoning model; action specialists get the fast tool-caller. This happens automatically from the operator's declared role.
4. Cost and quality tier
Finally, for_tier(operator.tier) routes broad-discovery operators (recon, osint) to a cheaper model and the rest to a strong model. This only takes effect if you have configured a tiered provider; otherwise it is a no-op.
The key point
Mapache does not assign models by operator name. There is no table that says "recon always uses model X". It assigns by the role each operator declares, funneled through your model_roles and routing. That is why setting the three roles is all you need to orchestrate the whole swarm across three models.
Commands
/modelsshows the live routing table plus a per-model call count./pipeline <strategy>switches the strategy mid-session./swarm [on|off]toggles the multi-agent supervisor./opsecshows which operations are pinned local.
Multi-agent orchestration
Mapache can split an engagement into specialists that share one attack state. There are two ways this happens: the lead agent delegates a bounded subtask, or an autonomous supervisor routes the whole engagement across operators. This page covers both, the operator roster, and how work is coordinated.
Delegation
A built-in delegate(task, operator=...) tool lets the model spawn a focused child AgentController for one bounded subtask and get back only its conclusion. The child runs the named operator's focused system prompt and a small curated tool subset instead of the lead's generalist prompt and full toolset. On a local model this is a real win: a smaller payload and narrower decisions.
Recursion is bounded by MAX_DELEGATION_DEPTH (default 1), so a sub-agent is not offered the delegate tool and cannot spawn its own children endlessly. Delegation events fire on the event bus with the operator label, so the audit log and the dashboard both see them.
The shared blackboard
The child references the lead's attack state by reference, so its findings are live in the lead's state with no merge-back step. A guard stops a child's task wording from reassigning the target or wiping the shared findings. The child also shares the lead's event bus, so its tool calls, findings, and scope refusals land in the same engagement log. State mutations are safe for concurrent children.
Parallel fan-out
delegate_parallel(tasks=[{task, operator}, ...]) runs several operators concurrently over the shared blackboard, capped by MAX_FANOUT. This gives you several angles on the current host at once. On a single GPU the model calls serialize at the provider, so it is a correctness and orchestration win; once cloud routing serves the calls concurrently it becomes a wall-clock win as well.
The operator roster
Operators live in core/operators.py. Each carries a focused prompt, a curated tool subset, a declared model role, a cost tier, and role constraints (read-only, gated by rules of engagement, needs hardware, deconflict first). Naming one in delegate or letting the supervisor pick runs the child as that specialist.
| Operator | Title | Focus |
|---|---|---|
| general | General Agent | General, non-offensive tasks and questions (not a kill chain) |
| coder | Coder | Write, run, and fix general code, scripts, and tooling |
| recon_operator | Recon Operator | Broad host and service discovery |
| osint_operator | OSINT Operator | Passive research and correlation |
| web_operator | Web Operator | Web application attack surface |
| exploit_operator | Exploit Operator | Service and application exploitation |
| post_operator | Post-Exploit Operator | Privilege escalation, loot, pivoting |
| cloud_hunter | Cloud Hunter | Cloud metadata, IAM, storage |
| contract_auditor | Contract Auditor | Smart-contract and Web3 review |
| exploit_dev | Exploit Developer | Writing and running exploit code |
| reverser | Reverser | Binary and firmware reversing |
| analyst | Analyst | Vulnerability research, exploit-chain construction |
| phisher | Phisher | Social engineering, requires deconfliction |
| mobile_operator | Mobile Operator | Android and iOS app testing |
| wireless_operator | Wireless Operator | Wi-Fi and radio |
| iot_operator | IoT Operator | Device and firmware attacks |
| ics_operator | ICS Operator | Industrial control and OT, gated by scope |
| forensicator | Forensicator | DFIR and purple-team analysis |
| supply_chain_operator | Supply Chain Operator | Dependency and CI/CD compromise |
There is also a vulnerability-research pipeline (scanner, detector, verifier, patcher, exploiter) and an engagement planner (soundwave) used by the supervisor.
Role constraints render into the prompt and reinforce the scope gate. /operators lists the roster, and a next-step suggester nudges the right specialist based on the open ports and services in the attack state.
The autonomous supervisor (swarm)
core/orchestrator.py holds the supervisor. With /swarm on (or default_strategy set to swarm), the supervisor autonomously routes the engagement across operators driven by the attack state, instead of relying on a single generalist agent to do everything.
The supervisor decides which specialist to deploy next from the current state, hands off, collects the specialist's conclusions into the shared knowledge, and continues. This is the mode to use when you want the most visible multi-agent action, and it is where the sub-agent model-selection pipeline in Model routing comes into play: each specialist can run on a different model based on the role it declares.
Success is evidence, not a flag
Mapache is a full-spectrum agent, not a capture-the-flag bot, so the supervisor's success signal is evidence-based: a captured flag, a confirmed vulnerability, or captured credentials all count as a solved objective. The engagement summary reports the number of findings, not a bare solved or unsolved flag.
The generalist fallback
The swarm is built for offensive engagements. If you hand it a general or coding objective, the offensive operators have no real job, so rather than flailing and reporting a failure, the swarm falls back to the lead agent once when it surfaces no evidence, so the task actually gets done. For a plain coding request, prefer running it without swarm (solo strategy with a coding model, or delegate to the coder operator); the fallback is a safety net, not the intended path.
Knowledge graph and the operation plan
The supervisor and the operators write into a disk-persisted knowledge graph (a findings store) so a freshly spawned specialist can query prior findings with a fresh context. There is also an operation plan (OPPLAN) that the model reads and updates (opplan_show, opplan_add, opplan_update) to keep long engagements coherent.
Trace streaming
Sub-agent activity streams through a scoped event bus, so the operator sees the child's tool calls and findings live rather than waiting for a summary at the end. In the CLI the transcript is colored by the active specialist so you can tell which operator is working.
Skills and playbooks
A skill is a compact playbook injected into the model's context at the right moment, so a weak model is grounded on the right technique without bloating every call. Mapache ships built-in playbooks for every domain and lets you author or import your own as SKILL.md files.
Built-in playbooks
Fifteen just-in-time playbooks cover the full spectrum: web, network service, credential, Active Directory, cloud, binary exploitation, mobile, social engineering, smart contracts and Web3, supply chain, ICS and OT, IoT and firmware, wireless, OSINT, and DFIR and purple team. Each one is a concrete, imperative body of guidance (tools, endpoints, payloads, proof) that is injected only while it is relevant.
The result is that Mapache is not web-only. Every domain operator has injected method.
How activation works (hybrid)
Mapache uses a hybrid of two activation mechanisms, chosen so the fast path stays free and offline while foreign skills still activate.
Predicate matching (the fast path)
Each built-in playbook carries a deterministic predicate over the attack state and the request: open ports, the target scheme, and keywords. When the predicate fires, the body is injected. This path is instant, offline, and free, and it is what the built-in domain playbooks use.
Model-based selection (for description-only skills)
For skills that carry a description but whose predicate does not fire, which is the case for trigger-less skills imported from other agents, a model reads a compact catalog of those skills and selects which apply to the current objective and attack state. The selection is cached by a signature of the engagement state, so the extra model call fires only when the situation materially changes, and any failure falls back to selecting nothing. This lets a foreign skill activate without hand-adding triggers, while the built-in playbooks keep their zero-cost predicate path.
Authoring a SKILL.md
A skill is a Markdown file with YAML frontmatter and a body. All trigger fields are optional; a skill with none never auto-injects on the fast path, and instead relies on model-based selection through its description.
---
name: lfi_ssrf
description: Local file inclusion and SSRF playbook
when_to_use: When a parameter takes a path or a URL
ports: [80, 443, 8080]
keywords: [lfi, ssrf, file=, url=]
target_scheme: [http, https]
phase: exploitation
tools: [http_request]
---
ACTIVE PLAYBOOK: describe the technique here. This body is injected into the model's
context verbatim whenever the skill matches, so write it as concrete, imperative
guidance: tools, endpoints, payloads, and how to prove the finding.
Fields:
name(required) anddescription(used for model-based selection).when_to_useis a human-readable hint.ports,keywords, andtarget_schemeare the fast-path triggers.phaseandtoolsare advisory.allowed-toolsis accepted for compatibility with skills authored for other agents.
The YAML parser handles inline lists, block-style lists, and multi-line scalars, so richer skills authored for other agents parse faithfully. It uses PyYAML when installed and a dependency-free parser otherwise.
Loading skills
Drop skills into ~/.mapache/skills/ (global) or <workspace>/skills/ (per project). Both layouts load:
- Flat single files:
skills/my_skill.md. - Nested packages:
skills/my-skill/SKILL.md, discovered recursively.
A nested package can ship bundled resource files (scripts and reference documents) alongside its SKILL.md. When the skill activates, the injected text lists those files with their paths, so the agent can read a reference with its file tools or run a bundled script with code_run or shell. This is progressive disclosure: the playbook prose is always available, and the heavier resources are opened on demand.
Compatibility with skills authored for other agents
The container format (SKILL.md with YAML frontmatter and a Markdown body) matches the common convention, so the prose of another agent's skill is reusable and its name and description parse cleanly. Unknown frontmatter keys are ignored rather than causing errors. The differences to keep in mind:
- Activation in Mapache is by trigger or by model-based selection over the description, not purely by the model reading the description at will.
- Bundled scripts are surfaced for the agent to run with its existing tools rather than executed automatically.
To reuse a foreign skill, copy its SKILL.md into a skills directory, add trigger frontmatter if you want the fast path, and re-home any bundled scripts.
Skill synthesis
Mapache can also write a new skill from a proven chain. The synthesize_skill tool saves the current winning sequence of actions as a reusable, signed skill, so a technique that worked once can be replayed and shared.
Tools
Mapache drives roughly fifty registered tools plus a set of meta-tools. Tools are structured: the model calls them with typed arguments, the result comes back as structured output, and schema validation catches a malformed call so the model can self-correct. This page groups the toolchain by area.
Execution and files
shellruns a command on the active execution backend (local, Docker, or SSH).code_runis a compile, run, and fix loop. It writes code (Python, C, C++, Go, Rust, Bash, and more), compiles it, runs it, and iteratively fixes it, staging into the active target and returning a structured verdict (compile failed, exit code, or ok). This is the exploit-writing primitive.file_read,file_write,file_edit,file_list, andfile_searchoperate on files.
Recon and network
nmap_scanruns structured port and service scans with schema validation. If the model omits the target, it is backfilled from the attack state.kali_runandkali_listdrive the packaged Kali tooling;searchsploitlooks up ExploitDB.- Operators drive domain CLIs (aws, kubectl, frida, ghidra, jadx, gophish, and others) through
shellandkali_run.
Web
http_requestsends a structured HTTP request. Because it is structured JSON, payloads with quotes survive intact, unlike a shell curl. This is the primitive for API testing.http_repeaterrecords, replays, tampers, and diffs requests. It is the primitive behind broken-access-control and IDOR testing.web_fetchandweb_searchread the surface web;tor_fetchroutes through Tor.browseris a real headless browser (Playwright) that renders JavaScript and single-page apps, so the agent sees what a user sees.sqlmapandfuzz(ffuf) are disciplined wrappers around those classic tools.- Response-grounded acting nudges the agent off blind endpoint spraying and toward the target's real forms and endpoints.
Exploitation and cracking
msf_searchand the Metasploit integration drive MSFRPC.- The Burp Suite integration uses the REST API and proxy.
johnidentifies and cracks hashes; hashcat and hydra are available through the Kali interface.
Grounding and research
cve_lookupcorrelates discovered services and versions to known CVEs with severity and exploit availability, from an offline catalog.vuln_researchstarts the vulnerability-research pipeline (scanner, detector, verifier, patcher, exploiter).- A payload corpus with a search tool provides known-good payloads instead of guesses.
Memory and planning meta-tools
kg_queryandkg_addread and write the knowledge graph (the findings store).opplan_show,opplan_add, andopplan_updatemanage the operation plan.- The persistent task list is seeded by a plan response and updated with a todo update.
Delegation meta-tools
delegate(task, operator=...)spawns a focused specialist child for one subtask.delegate_parallel(tasks=[...])fans several operators out over the shared blackboard.
See Multi-agent orchestration for how these behave.
Self-authored tools
The create_tool meta-tool lets the model author a brand-new reusable tool at runtime. It writes the body of an async run function, which is compiled (errors are handed back for self-correction) and persisted as a hub-installable package under plugins/generated/<name>/ with a manifest carrying origin, usage, lifecycle state, phase, and a sha256 checksum. The tool registers into the tool registry and becomes callable on the next loop iteration, never in the same response that created it.
Trust model: an agent-written tool (origin self) loads freely; a downloaded tool (origin hub) is sha256-verified before it compiles and refuses to load if it has been tampered with. The startup loader is fail-soft, so a bad tool never breaks startup.
Model-facing tools: create_tool, tool_list_generated, tool_delete.
The curator (tool-library garbage collection)
Self-authored tools move through a reversible lifecycle: active, then stale, then archived, so the create-tools loop cannot pile up. A usage rule auto-demotes an unused tool to stale (a non-destructive label; using it promotes it back to active). The only permissioned step is stale to archived: /curate proposes stale tools one at a time and, on your per-tool approval, unregisters them and moves their folder out of the load path. /restore <name> reverses it, and /purge <name> hard-deletes an already-archived tool as a deliberate two-step.
MCP tools
Tools exposed by a connected Model Context Protocol server appear as ordinary Mapache tools named mcp__<server>__<tool>. See MCP and the skill hub.
Providers
A provider is where a model runs. Mapache talks to local models, cloud providers, and local gateways through one abstraction, so per-role routing can address local and cloud models interchangeably. This page lists the providers, how to configure them, and their model ids.
How providers work
Each provider entry in the config carries a kind, a base URL, an API key, a list of model ids it serves, and an enabled flag. A model id is routed to the provider that lists it; a model that no cloud provider claims falls back to the local Ollama provider. Cloud calls require --allow-cloud (or allow_cloud: true in config), and Mapache warns when a call sends target, scan, or credential context to a cloud model.
You can set keys three ways: type them in mapache setup, put them in the config file, or reference an environment variable with a ${VAR} placeholder so nothing secret is written to disk.
Local models: Ollama
The default provider. Install Ollama, run ollama serve, and pull a model:
ollama pull qwen2.5:32b
mapache serve --model qwen2.5:32b
Any locally installed model works without listing it. Ollama is the recommended primary test model source; qwen2.5:32b is a reliable tool-calling local model.
Context window
Ollama defaults a model's context window to a small value (often 4096 tokens), so a full Mapache prompt (system prompt plus tools plus attack state, roughly 12000 to 16000 tokens) overflows it and Ollama returns HTTP 400 "exceeds the available context size". Mapache requests a larger window automatically via options.num_ctx (default 16384), so any model can hold a real engagement prompt. Override it with the OLLAMA_NUM_CTX environment variable. A larger window uses more memory, so if a big model runs out of memory, lower OLLAMA_NUM_CTX, but keep it above your typical prompt size (around 13000) or large prompts will overflow again.
Cloud providers
| Provider | Kind | Base URL | Key env var |
|---|---|---|---|
| OpenRouter | openai-compatible | https://openrouter.ai/api/v1 | OPENROUTER_API_KEY |
| Anthropic | anthropic | https://api.anthropic.com | ANTHROPIC_API_KEY |
| OpenAI | openai-compatible | https://api.openai.com/v1 | OPENAI_API_KEY |
| Grok (xAI) | openai-compatible | https://api.x.ai/v1 | XAI_API_KEY |
| Nous | openai-compatible | (Nous endpoint) | NOUS_API_KEY |
| NVIDIA NIM | openai-compatible | (NIM endpoint) | NVIDIA_API_KEY |
OpenRouter is convenient because one key reaches many frontier models (for example anthropic/claude-sonnet-4.6, openai/gpt-4.1, x-ai/grok-4).
Native Chinese providers
DeepSeek, Moonshot (Kimi), and Zhipu (GLM) are first-class providers, so you can paste a key straight from the vendor console without routing through an aggregator.
| Provider | Base URL | Key env vars | Model ids |
|---|---|---|---|
| DeepSeek | https://api.deepseek.com | DEEPSEEK_API_KEY | deepseek-chat, deepseek-reasoner |
| Moonshot (Kimi) | https://api.moonshot.ai/v1 | MOONSHOT_API_KEY or KIMI_API_KEY | kimi-k2-0711-preview, moonshot-v1-128k, moonshot-v1-32k, moonshot-v1-8k |
| Zhipu (GLM) | https://open.bigmodel.cn/api/paas/v4 | ZHIPU_API_KEY or GLM_API_KEY | glm-4.6, glm-4.5, glm-4-plus, glm-4-air, glm-4-flash |
All three are OpenAI-compatible, so Mapache speaks to them natively with no extra dependency. They support native tool-calling, which the agent loop needs.
Local gateways: OmniRoute
OmniRoute is a local OpenAI-compatible gateway that aggregates many providers, including free tiers. Configure it as a provider with kind openai-compatible, base URL http://localhost:20128/v1, and a dummy non-empty key (the gateway ignores auth on localhost). Pin a fixed model id to avoid the gateway rotating the backend per request.
Free-tier models routed this way have two practical limits: some forbid native tool-calling and some throttle aggressively. They are fine for light use but not for driving the full agent loop at speed. A capable local model or a paid cloud model is the right choice for real engagements.
Tool-calling versus JSON mode
Native tool-calling models receive tool schemas in the dedicated tools field. A model without native tool-calling (or a tier that forbids it) runs in JSON mode: the tools are described in the prompt and the model is asked for JSON that the loop parses into tool calls. Mapache selects the mode automatically per provider.
Choosing a model
- For real engagements, use a capable local model (for example
qwen2.5:32b) or a frontier cloud model. - Small or free-tier models struggle to drive the loop reliably.
- For a multi-model team, see Model routing.
Execution and OPSEC
This page covers where Mapache runs its commands, how it anonymizes its traffic, how it stays inside an authorized scope, how it records what it did, and how it defends itself.
Execution backends
Every shell and tool command runs on an execution backend. The backend is selected in config (execution.backend) or with /backend.
- Local: commands run on the host that runs Mapache. The default.
- Docker: commands run inside a container through docker exec. This is how Mapache runs a Linux toolchain on a Windows host, and how it isolates an engagement from the host.
- SSH: commands run on a remote host over SSH.
A backend returns a structured result (stdout, stderr, exit code) so tools behave the same regardless of where they run. Sub-agents can be given their own backend, so a specialist's shell and scans run in an isolated container while the lead coordinates.
Egress and anonymity
Mapache can route its attack traffic to hide the operator's origin. The egress mode is set in config (egress.mode) or with /egress:
- direct: no anonymization.
- proxy: route through an HTTP or SOCKS proxy.
- tor: route through Tor. Mapache detects Tor and guides setup.
When egress is active the CLI shows it at startup, and web and fetch tools honor it.
Rules of engagement (scope)
An authorized test has a scope: the targets you are allowed to touch. Mapache enforces it with an optional scope.json in the working directory (or --scope <path>).
{
"name": "ACME external pentest",
"targets": ["10.10.10.0/24", "acme.example.com"],
"forbidden_tools": ["msf_run"],
"forbidden_patterns": ["rm -rf", "shutdown", "mkfs"],
"allow_loopback": true
}
targetsis an allowlist of IPs, CIDRs, and hostnames. Hostnames match subdomains.forbidden_toolsblocks named tools entirely.forbidden_patternsblocks any argument matching a pattern (destructive commands).allow_loopbackpermits local utility calls (default true).
The gate runs in the dispatch path, after the target is backfilled from the attack state and before the tool runs. An out-of-scope or forbidden call is refused, never dispatched, and the refusal is fed back to the model, which then changes approach. A defense-in-depth re-check covers generated-tool shell calls that bypass the controller, and sub-agents inherit the scope so delegation stays bounded.
Scope is inactive when no scope.json is present, so the default behavior is unchanged. Host extraction favors precision (IPs from any argument, bare hostnames only from target-shaped keys and URLs) so a wordlist path is not mistaken for a target. The CLI shows a startup banner, a /scope command, and a live refused line when a call is blocked.
The audit log
Mapache keeps an append-only JSONL trail of the whole session, fed purely by the event bus. It records every tool call with arguments and outcome, every finding (flag, credential, vulnerability, open port), every scope refusal, and the delegate and verify events, one flushed line per record so it survives a crash and is frozen after the session closes.
It is on by default (writes to engagements/, which is gitignored; disable with --no-engagement-log). /log shows it and /log export renders a Markdown findings list and timeline, which is the seed for the report.
Self-defense and containment
Mapache defends itself and contains the target side.
- Prompt-injection shield: the agent is hardened against instructions embedded in a target's responses (a page, a banner, a file) trying to hijack the agent. Injected content is treated as data, not as operator instructions.
- Isolated-lab containment: running the engagement through the Docker or SSH backend keeps the target's shell and tools off the host. The scope gate guards the target side; the injection shield guards the agent side.
OPSEC routing
When cloud is allowed, sensitive work can still be pinned to a local model so loot and credentials never leave the host. This is decided per sub-agent based on the operator and whether credentials have already been captured. See Model routing for the full pipeline, and /opsec to see which operations are pinned local.
Memory
Mapache remembers within an engagement, across engagements, and semantically. This page covers the memory subsystems and the cross-engagement learning that biases future runs.
Session memory
memory/session_memory.py holds the turn-by-turn history of the current session. It works with the conversation chain and context compaction so a long engagement stays coherent without overflowing the context window.
Notes
memory/note_store.py is a place for the agent to jot durable observations during an engagement. The model can record a note and recall it later. /memory shows the current memory state and /user records durable facts about the operator.
Knowledge store and semantic recall
memory/knowledge_store.py and memory/vector_store.py store findings and support semantic recall: the agent can retrieve a prior finding by meaning, not just by exact match. This is what lets a finding persist across sessions and surface again when it becomes relevant.
The knowledge graph (findings store)
A disk-persisted knowledge graph records findings as structured nodes so a freshly spawned specialist can query prior findings with a fresh context. This is the shared memory behind the multi-agent supervisor: the lead and every operator read and write the same graph. Model-facing tools are kg_query and kg_add.
The operation plan
The operation plan (OPPLAN) is a living plan the model reads and updates over a long engagement (opplan_show, opplan_add, opplan_update). It keeps the objective and the outstanding steps coherent when the engagement spans many turns and several operators.
Cross-engagement learning
Mapache keeps a cross-engagement learning store that records what worked on similar targets before and biases routing toward those approaches on a new but similar target. A target fingerprint is used to match, so a technique that won against a similar stack is surfaced as a prior-win hint. This is how Mapache gets better with use rather than starting cold every time.
What is stored where
- Session history and the running summary live with the session.
- Notes and knowledge live in the note and knowledge stores.
- Findings live in the knowledge graph, which is shared across agents.
- The engagement audit trail lives in
engagements/(see Execution and OPSEC). - Cross-engagement learning lives in its own store and persists between runs.
Middleware
Cross-cutting concerns (budget, human approval, defensive follow-up, reflection, route enumeration) are not hand-wired into the loop. They are composable middleware that hook well-defined slots, so they can be added or removed without touching the controller.
The framework
core/middleware.py defines the contract:
AgentMiddleware- a base class with three optional async hooks:on_turn_start(ctx)- once, before the first model call of a turn.on_iteration_start(ctx)- the top of every loop step.on_turn_end(ctx, response)- once, after the turn produces its answer.LoopContext- the mutable per-turn state passed to every hook. A middleware influences the loop by setting:ctx.stop = True(withctx.stop_reason) to end the turn now, orctx.inject.append("...")to add a user message before the next model call (steering, nudges, approvals). It also exposesctx.controller,ctx.session_id,ctx.iteration, and ascratchdict middlewares can share within a turn.MiddlewareChain- runs the registered middlewares at each slot, in order. A hook that raises is logged and swallowed, so one bad middleware cannot break the engagement. Actx.stopshort-circuits the remaining middlewares at that slot.
The default chain is empty; middleware is inert until registered (usually from a CLI flag). Register with controller.add_middleware(...).
Built-in middlewares
All live in core/agent_middlewares.py.
BudgetMiddleware
Stops the engagement once it exceeds a token or wall-clock budget. Checks the controller's cumulative token usage and elapsed time at each iteration and sets a graceful ctx.stop/ctx.stop_reason with a budget.exceeded event. Wired by --budget-tokens N / --budget-seconds S.
HITLMiddleware
A human-in-the-loop checkpoint gate. Fires on an every-N iterations cadence and/or on a phase change; a callback returns approve, deny (stop), or steer (inject a new instruction). Fail-open on a callback error, and the first iteration never gates. Distinct from per-tool dangerous-action confirmation. Wired by --hitl / --hitl-every N.
VaccineMiddleware
Defensive follow-up. On each newly confirmed vulnerability it generates a detection plus remediation note (a "vaccine"), records it to the knowledge graph as mitigating the vulnerability, and writes it to the workspace. Vaccinated once per vulnerability; a per-step cap bounds bursts. Wired by --vaccine.
ReflectionMiddleware
Every N steps it injects a structured self-critique: confirmed facts, current hypothesis, and the highest-value next action, so the agent reasons about what it has learned instead of drifting. Wired by --reflect / --reflect-every N.
RouteEnumMiddleware
Active route enumeration. Once, when a web target has few discovered endpoints, it probes a curated list of common routes through the tool dispatcher and folds the real hits (non-404) into the shared endpoints, then injects them so the agent uses real paths instead of guessing. Wired by --route-enum; the swarm runs the equivalent enumeration in the supervisor before routing.
Where the supervisor fits
The multi-agent supervisor is not a loop middleware; it is a control loop that drives sub-agent turns. Its anti-loop, fan-out, and route enumeration are described in multi-agent. A sub-agent is itself an AgentController, so any middleware registered on it hooks that sub-agent's loop.
Reporting
Mapache is evidence-first: success is a proven finding with severity, evidence, impact, and remediation, not a captured flag. This page covers how it turns an engagement into a report and what formats it exports.
The report builder
reporting/report_builder.py turns the audit-log records and the attack-state blackboard into a structured pentest report:
- Findings for vulnerabilities, captured credentials, notable exposed services (telnet, SMB, RDP, Redis, and others), and flags, each with a severity and concrete remediation.
- First-seen timestamps taken from the audit log.
- An executive summary with a severity tally.
- A methodology timeline.
- A tool-activity appendix.
The builder is deterministic and offline. It makes no LLM call, so it is reproducible, testable, and never sends findings to a third party. This keeps the local-first OPSEC story intact from end to end.
Export formats
- Markdown for readability and version control.
- Self-contained HTML (print it to get a PDF).
- SARIF for ingestion into code-scanning and security dashboards.
- A bug-bounty draft for submission.
Optional secret redaction removes captured credentials from the exported copy.
Generate a report with /report [md|html|both], which writes to engagements/.
Grounding and scoring
Findings can be correlated to known CVEs with severity and exploit availability from an offline catalog (cve_lookup). An optional LLM narrative pass and precise CVSS scoring are layered enhancements on top of the deterministic core, so you can add polish without giving up reproducibility.
Why evidence-first matters
Most agents invent endpoints, field names, and payloads and then declare victory. Mapache reads a target's real forms, endpoints, and disclosed credentials into state, looks up payloads from an offline corpus, and detects dead attack vectors so it changes approach instead of spinning. A finding in the report is backed by the exact request or command that proved it, recorded in the audit log with a timestamp.
MCP and the skill hub
Mapache is extensible in two directions: it consumes tools from Model Context Protocol servers, and it installs and publishes community skills and tools through a hub.
MCP client
Mapache connects out to Model Context Protocol servers and exposes their tools as ordinary Mapache tools. It is a client: Mapache consumes MCP servers, it does not act as one.
How it works
Each server is launched as a subprocess and spoken to over the stdio transport: newline-delimited JSON-RPC 2.0 (initialize, then tools/list, then tools/call). A remote tool is wrapped as a normal tool, registered into the same tool registry and dispatcher as the built-ins, and namespaced mcp__<server>__<tool> to avoid collisions. Their names are pinned so phase-based subsetting keeps them exposed. Connection is fail-soft: a bad server never breaks startup, and clients are closed on exit.
Configuration
Servers are listed in a Claude-Desktop-style mcp.json (--mcp-config, default mcp.json; absent means MCP is off):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
"env": {}
},
"fetch": {
"command": "uvx",
"args": ["mcp-server-fetch"],
"env": {}
}
}
}
The launcher is resolved through PATH, honoring PATHEXT, so a bare command like npx or uvx finds its real executable. This is what makes the canonical configuration work on Windows as well as Linux and macOS.
Note that a third-party MCP server can be broken upstream, independent of Mapache. When that happens Mapache logs the server as unavailable and continues, rather than failing to start.
Driving a browser like a user (Playwright MCP)
The Playwright MCP server lets Mapache drive a real browser the way a person does: it can navigate, click, type, fill forms, select options, upload files, take screenshots, inspect network requests, and capture an accessibility snapshot of the page that the model acts on by element. This is a richer, interactive complement to Mapache's built-in headless browser tool (which renders a page for reading).
Add it to your mcp.json:
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["-y", "@playwright/mcp@latest", "--headless"],
"env": {}
}
}
}
Its tools appear as mcp__playwright__browser_navigate, mcp__playwright__browser_click, mcp__playwright__browser_snapshot, mcp__playwright__browser_type, and so on (around two dozen). Notes:
- The first run downloads the package and a browser, so give it a moment.
- Drop
--headlessto watch the browser act (useful for a demo). browser_run_code_unsafeexecutes arbitrary JavaScript on the page; only enable this server against targets you are authorized to test.- Mapache looks for
mcp.jsonin the working directory you launch from (or the path you pass to--mcp-config), so put it where you runmapache serve.
The skill hub
The hub lets you browse, install, and publish reusable extensions. Three manifest types are supported:
- A generated tool: a self-authored tool packaged for reuse.
- An MCP server: an entry added to your
mcp.json. - An external tool: a bring-your-own HTTP or command tool.
Installing
A hub is configured by pointing at a registry (a local path or an http(s) URL). Installing a generated tool writes a package to your generated-tools directory and re-verifies its sha256 before it loads. Installing an MCP server writes an entry into your mcp.json. A tampered package is refused before anything is written. /hub and the skill tools drive this from inside a session, and they degrade gracefully when no hub is configured.
Publishing
You can publish your own generated tool, MCP server entry, or external tool to a registry, so a technique that worked for you can be shared with a checksum as the integrity gate.
Which extension mechanism to use
- Use MCP when you want to reuse an existing tool server that already speaks the protocol.
- Use a self-authored tool when you want the agent to build a small tool on the fly (see Tools).
- Use a skill when you want to teach the agent a technique rather than give it a new tool (see Skills and playbooks).
- Use the hub to distribute any of these.
User interface
Mapache has three faces: the line-based CLI, an opt-in full-screen TUI with a live agent dashboard, and the setup wizard. It can also be operated remotely over Telegram and Discord. This page covers each, plus every slash command.
Launching
mapache serve # classic CLI
mapache serve --tui # full-screen TUI with the dashboard
mapache serve --model qwen2.5:32b # pin a model
mapache setup # the setup wizard
mapache config show # print the effective config
mapache version # print the version
The startup banner shows a large ANSI wordmark and the mascot, then a compact box of session facts (model, tool count, confirm and verifier state, memory counts, the rules of engagement, and the working directory).
The classic CLI
You type an objective at the prompt and the agent works it, streaming its reasoning and tool activity. A single background reader handles input, so you can type to steer a running turn (or answer a confirmation) without a second reader competing for the keyboard. The transcript is colored by the active specialist during delegation, so you can see which operator is working. In the classic CLI the strategy and per-role model routing print inline at startup.
The full-screen TUI dashboard
--tui opens a two-column layout:
- Left column: the ANSI mascot and the scrolling transcript, over a bordered input box.
- Right column: a live agent dashboard, a fixed-width stack of panels.
The dashboard panels:
- Agent: the active operator and its accent color, the current phase, the most recent tool or command it called, and the team size. Sub-agent tool calls feed the HUD too, so in swarm mode you see the operators' actual commands live.
- Models: the routing strategy and the per-role model map (planner, executor, verifier). This is where the model details live in the TUI, rather than front and center.
- Target: the target, the open ports, and the vulnerability count.
- Budget: elapsed time and tokens against any configured caps, and the tool-call count.
- Running shells: any in-flight shell commands, with a spinner.
- Recent tools: the last handful of tool calls.
The dashboard is fed by the same events the transcript uses, plus the status clock, so it updates live as the agent works without slowing it down. The full-screen view needs a real console; if the terminal cannot start a full-screen app, Mapache falls back to the classic CLI automatically.
The setup wizard
mapache setup walks you through configuration, with every question in its own titled panel:
- Model provider: pick from local Ollama or a cloud provider.
- API key: paste a key for a cloud provider, or leave it to an environment variable.
- Model: pick a model id (a suggested list, or type your own).
- Roles: use one model for everything, or customize per role (lead, executor, verifier), which writes the per-role model map.
- Strategy: Auto (smart routing), Solo (one model), or Swarm (a multi-agent team).
- Toolchain, Ollama, and a smoke test are shown as compact panels.
The wizard is idempotent: every prompt shows the current value as its default, and pressing Enter keeps it. Secrets are preserved: a key kept as an environment placeholder is never rewritten as a literal.
Remote operation
Mapache can run over Telegram and Discord with the full toolset. A single command launches both bots, and the async frontends can steer a running turn the same way the CLI can. Configure the bot tokens in the wizard or the config file.
Voice
Optional voice input and output are available behind a null default (--voice, --say, and the voice config section). Text-to-speech and speech-to-text are opt-in and require their optional packages.
Slash commands
Type these at the prompt during a session.
Session and help
/helpshows the command list./clearclears the screen./exit,/quitend the session./historyshows the conversation history./contextshows what is in the current prompt context./debugtoggles debug output.
Models and routing
/modelsshows the live routing table and per-model call counts./pipeline <strategy>switches the strategy (single, pipeline, auto, hybrid)./swarm [on|off]toggles the multi-agent supervisor./opsecshows which operations are pinned to a local model./operatorslists the operator roster.
State and memory
/chainshows the attack-state chain./hostslists discovered hosts./memoryshows memory state./userrecords a durable fact about you./cvelooks up CVEs for a discovered service./synthesizesaves the current proven chain as a skill.
Scope, logging, and reporting
/scopeshows the active rules of engagement./log,/log exportshow and export the audit log./report [md|html|both]generates a report.
Execution and egress
/backendshows or sets the execution backend./egressshows or sets traffic anonymization./cwdshows the working directory.
Extensions and tools
/toolslists registered tools./integrationslists configured external tools./hubbrowses and installs from the skill hub./curatereviews stale self-authored tools for archiving./restore <name>restores an archived tool./purge <name>hard-deletes an archived tool.
Confirmation and voice
/confirmtoggles per-action confirmation for dangerous operations./voice,/saycontrol voice output./soulshows the agent persona.
Useful flags
--allow-cloudpermits routing to cloud models.--strategy <name>sets the routing strategy.--verifyenables the opt-in verifier step.--scope <path>sets a rules-of-engagement file.--mcp-config <path>sets the MCP server list.--budget-tokens N,--budget-seconds Scap the engagement.--attempts Nenables multi-attempt self-consistency solving.--tuiopens the full-screen dashboard.
Configuration
Mapache reads a layered configuration: built-in defaults, then a global config file, then a project-level file, then environment variables, then command-line flags. Later layers win. This page documents the config file and the options.
Where config lives
- Global:
~/.mapache/config.json, written bymapache setup. - Project: a config file in the working directory overrides the global one.
- View the effective config with
mapache config show, and the path withmapache config path. Secrets are redacted in the printed output.
Secrets
A value can be a literal, or an environment placeholder like ${DEEPSEEK_API_KEY}. The placeholder is resolved at load time, so a key supplied only by the environment is never written to disk as plaintext. The setup wizard preserves an existing placeholder when you press Enter.
Options
{
"default_model": "qwen2.5:32b",
"default_strategy": "single",
"model_roles": {
"planner": "deepseek-reasoner",
"executor": "kimi-k2-0711-preview",
"verifier": "glm-4.6"
},
"allow_cloud": false,
"max_vram_gb": 12.0,
"providers": {
"ollama": { "kind": "ollama", "base_url": "http://127.0.0.1:11434", "enabled": true },
"deepseek": { "kind": "openai_compatible", "base_url": "https://api.deepseek.com", "api_key": "${DEEPSEEK_API_KEY}", "models": ["deepseek-chat","deepseek-reasoner"], "enabled": true }
},
"messaging": { "telegram_token": "", "discord_token": "" },
"execution": { "backend": "local" },
"egress": { "mode": "direct" },
"integrations": [],
"hub": { "registry": "" },
"voice": { "enabled": false },
"budget": { "max_tokens": 0, "max_seconds": 0 },
"hitl": { "enabled": false, "every": 0, "on_phase_change": true },
"vaccine": { "enabled": false, "per_step_cap": 0 },
"reflection":{ "enabled": false, "every": 0 },
"flag_format": ""
}
Core
default_model: the model used when you do not pass--model.default_strategy: single (alias solo), auto, pipeline, hybrid, or swarm. See Model routing.model_roles: optional per-role model map (planner, executor, verifier), applied to the router at startup. Empty means every role uses the default model.allow_cloud: permit routing to cloud models. Also set by--allow-cloud.max_vram_gb: a hint for local routing.
Providers
Each entry has a kind (ollama, openai_compatible, or anthropic), a base URL, an optional API key, a list of model ids it serves, and an enabled flag. See Providers for the full list and the environment variables.
Messaging
telegram_token and discord_token enable the remote bots.
Execution and egress
execution.backend: local, docker, or ssh (plus backend-specific fields).egress.mode: direct, proxy, or tor.
See Execution and OPSEC.
Middleware
budget: stop the loop gracefully at a token or wall-clock cap.hitl: human-in-the-loop checkpoints (every N steps, or on a phase change).vaccine: turn each confirmed vulnerability into a detection and remediation note.reflection: inject a reflect-and-refocus checkpoint every N steps.
Extensions and other
hub.registry: a local path or an http(s) URL for the skill hub.integrations: bring-your-own HTTP or command tool specs.voice: text-to-speech and speech-to-text settings.flag_format: an optional regex the candidate-flag verifier uses to recognize custom flags.
Environment variables
- Provider keys:
DEEPSEEK_API_KEY,MOONSHOT_API_KEY(orKIMI_API_KEY),ZHIPU_API_KEY(orGLM_API_KEY),OPENROUTER_API_KEY,ANTHROPIC_API_KEY,OPENAI_API_KEY,XAI_API_KEY,NOUS_API_KEY,NVIDIA_API_KEY. - Base URL overrides where supported, for example
MOONSHOT_BASE_URL,ZHIPU_BASE_URL. MAPACHE_STRATEGYmaps todefault_strategy.OLLAMA_NUM_CTXsets the context window Mapache requests from Ollama (default 16384). See Providers.NO_COLORdisables colored output.
Flags that override config
--model, --strategy, --allow-cloud, --scope, --mcp-config, --budget-tokens, --budget-seconds, --verify, --attempts, and --tui. Flags win over the config file.
Use cases
This page walks through end-to-end engagements across disciplines. Each one shows a target to practice against, the prompt to give Mapache, what the agent does, and what you get back. All targets here are ones you run yourself or are authorized to test.
A reminder: Mapache is for authorized testing only. Put a scope.json in your working directory so the rules-of-engagement gate is active (see Execution and OPSEC).
Web application pentest
Target: OWASP Juice Shop, a modern deliberately-vulnerable web app.
docker run --rm -p 3000:3000 bkimminich/juice-shop
Prompt:
You're authorized to test the web app at http://localhost:3000, which I own. Get
administrator access, prove it with concrete evidence, and give me a finding with
severity, impact, and remediation.
What happens: the web playbook activates because the target is a URL. Mapache reads the real login form and its endpoint with http_request (not a guessed path), tests the email field for SQL injection, uses the injection to log in as the administrator, confirms the admin token against an admin-only endpoint, and records an evidence-backed finding. Use /report both to export Markdown and HTML.
What you get: a report with the exact request that proved the finding, its severity, its impact, and how to remediate it.
Network and host pentest
Target: a lab host you own (for example a vulnerable VM on your own network).
Prompt:
Target is 10.0.0.5. Enumerate it, exploit any vulnerable service, escalate to root, and
report proven findings. Use -Pn on the scan.
What happens: the recon phase runs a structured nmap_scan (the target is backfilled if omitted), the attack state fills with open ports and services, the network-service or credential playbook activates from the ports, and the agent moves to exploitation only after the scan returns. Post-exploitation escalates and loots. If credentials are captured and a local model is installed, sensitive post-exploit work is pinned local.
What you get: findings for each vulnerable or exposed service, with remediation, plus a methodology timeline.
Cloud assessment
Target: a cloud account or a cloud-simulation lab you are authorized to test.
Prompt:
Assess the cloud posture reachable from this host. Check instance metadata, look for
over-permissive IAM and exposed storage, and report anything exploitable with evidence.
What happens: delegate to the Cloud Hunter operator (or let the supervisor pick it). It checks instance metadata, IAM, and storage through the cloud CLIs driven by shell. The cloud playbook grounds the technique.
Active Directory
Target: an AD lab you own.
Prompt:
Domain target is 10.0.0.10. Find a path to Domain Admin: enumerate the domain, hunt for
weak credentials and kerberoastable accounts, and report the path with evidence.
What happens: the Active Directory playbook activates. The agent enumerates the domain, looks for weak and reused credentials and kerberoastable accounts, and constructs a path to Domain Admin, recording each step.
Binary exploitation and exploit development
Target: a vulnerable binary you are analyzing.
Prompt:
Analyze ./vuln (attached in the working dir). Find the memory-corruption bug, then write
and run a working exploit with code_run that proves control of execution.
What happens: delegate to the Reverser and Exploit Developer operators, which declare the planner role so they run on the reasoning model. code_run writes the exploit, compiles it, runs it, and iterates on failures until it works, staging into the active backend.
Mobile application testing
Target: an Android APK you are authorized to test.
Prompt:
Test this Android app (apk in the working dir). Decompile it, look for hardcoded secrets
and insecure endpoints, and report findings.
What happens: the Mobile Operator drives the mobile toolchain (for example jadx and frida) through shell and kali_run, grounded by the mobile playbook.
A multi-model team demo
Goal: show three models collaborating on one engagement.
Set up per-role routing (see Model routing) with planner deepseek-reasoner, executor kimi, verifier glm, then:
mapache serve --allow-cloud --verify
Give it the web-app prompt above. The executor model drives the loop, the planner model does the reasoning-heavy analysis, and the verifier model validates the finding at the checkpoint. The TUI Models panel shows the role-to-model map live. Turn on /swarm for more visible specialist hand-off.
Capture the flag
Target: a CTF challenge you are solving.
Prompt:
Solve this challenge at http://localhost:8080. The flag format is CTF{...}.
What happens: pass --flag-format 'CTF\{.*\}' so the candidate-flag verifier recognizes a captured token in the right format. Use --attempts 3 for multi-attempt self-consistency on a hard challenge.
Bug bounty triage
Target: an asset in a program you are authorized to test.
Prompt:
Assess https://app.example.com within this scope. Focus on access-control and injection
flaws, and give me a bug-bounty draft for anything you can prove.
What happens: put the program scope in scope.json so the agent stays in bounds. The http_repeater tool is the primitive for the access-control testing. Export a bounty draft with the report tools.
DFIR and purple team
Target: logs or artifacts from an incident you are investigating.
Prompt:
Here are the logs in ./artifacts. Build a timeline of the intrusion and write detection
rules for what you find.
What happens: the Forensicator operator and the DFIR playbook drive the analysis. The offensive-vaccine middleware, if enabled, turns each confirmed issue into a detection and remediation note.
Tips that apply to every engagement
- Put a
scope.jsonin the working directory to keep the agent in bounds. - Add
--budget-seconds 300so a stuck weak model cannot run forever. - Use
--verifyto make success evidence-backed. - Use the
--tuidashboard to watch the target, budget, tools, and running shells live. - Use a capable model. Small or free-tier models struggle to drive a full engagement.