A multi-user pentest workbench that pairs each operator with a private AI conversation while maintaining a shared, engagement-scoped knowledge graph β local-first, human-in-the-loop, and extensible through MCP.
β¨ Features β’ π§© Architecture β’ π€ How it's built β’ π Getting started β’ π§ Roadmap β’ π Security
Adeptus is built for small red teams (2β5 people) doing web application engagements, with an architecture that leaves the door open for internal network mapping later. Everything below is designed around three rules: engagement isolation is sacrosanct, human-in-the-loop where it matters, and the AI shows its work.
| π§ AI you can trust | Local-first chat via Ollama; optional, privacy-gated Claude API. The AI keeps a visible running plan, flags low-confidence claims with a stated certainty %, and asks clarifying questions instead of guessing. |
| π‘οΈ Human-in-the-loop safety | Two-tier autonomy: recon runs free, dangerous actions are approval-gated inline in chat. Any member can approve/reject β attribution and a self_approved flag are always recorded. Soft scope enforcement + global kill switch. |
| πΈοΈ Shared knowledge graph | One single-writer process per engagement (NetworkX β PostgreSQL) serializes every write, eliminating races. Force-directed Cytoscape view, soft-delete history, a personal 20-step undo stack, pins, notes, and manual attack paths. |
| π Extensible tooling (MCP) | One MCP server per tool category over stdio. Weighted concurrency (light/heavy) with a per-target lock, Docker-isolated execution, a manual tool runner, and an embedded xterm.js terminal. Ships with nmap Β· httpx Β· gobuster Β· shell-exec. |
| π― Findings & attack paths | Simple severity by default (CriticalβInfo), optional CVSS 3.1/4.0 & OWASP Risk, MITRE ATT&CK tags. Verification + remediation lifecycle, AI-proposed dedup merges, and AI-proposed attack chains. |
| π RAG & retest | Curated KB (OWASP / CVE / ATT&CK) + per-engagement uploads, strictly isolated per engagement via pgvector (hnsw, WHERE engagement_id). Archived engagements can seed a retest as background context only. |
| π Privacy & audit | Strict local-only by default with a persistent privacy banner. Cloud egress passes a secret-pattern friction check. A hash-chained, tamper-evident audit log is the single source of truth for provenance. Credentials encrypted at rest. |
| π₯ Collaboration & ops | Presence, typing indicators, @-mentions into a shared channel, an in-app notifications panel, a session-replay timeline scrubber, on-demand Markdown reports, an admin dashboard, and token/cost tracking. |
A single Docker Compose stack: a React SPA over a FastAPI backend, PostgreSQL + pgvector for state and vectors, Ollama for local inference, and MCP subprocesses driving Docker-isolated pentest tools.
flowchart TD
subgraph Browser["π₯οΈ React SPA β one route per engagement"]
Chat["π¬ Chat pane<br/>private AI conversation"]
GraphPane["πΈοΈ Graph pane<br/>force-directed (Cytoscape)"]
Console["π Console pane<br/>tool output + xterm.js"]
end
API{{"π‘οΈ API gateway<br/>/api/v1 + WebSocket"}}
Browser <-->|"REST + WebSocket"| API
subgraph Backend["βοΈ FastAPI backend (async, one folder per feature)"]
Features["auth Β· engagements Β· chat Β· graph<br/>findings Β· approvals Β· autonomy Β· mcp Β· audit"]
Writer["βοΈ Single-writer process<br/>per engagement (NetworkX)"]
Egress["π¦ Egress pattern-friction<br/>likely-secret scan"]
Audit["π Hash-chained audit log"]
end
API --> Features
Features --> Writer
Features --> Audit
subgraph Data["ποΈ PostgreSQL 16 + pgvector"]
DB[("Graph Β· chats Β· findings<br/>sessions Β· audit chain")]
Vec[("RAG vectors<br/>hnsw Β· engagement-scoped")]
end
Writer --> DB
Features --> Vec
subgraph LLM["π§ LLM backends"]
Ollama["π¦ Ollama (local-first)<br/>chat + nomic-embed-text"]
Claude["βοΈ Claude API<br/>optional, privacy-gated"]
end
Features --> Ollama
Features --> Egress
Egress -.->|"strict-local default<br/>blocks cloud"| Claude
subgraph MCP["π MCP servers (stdio subprocess)"]
Nmap["nmap"]
Httpx["httpx"]
Gobuster["gobuster"]
Shell["shell-exec"]
end
Features -->|"weighted concurrency<br/>+ per-target lock"| MCP
MCP --> Containers["π³ Docker tool containers<br/>per-engagement networking"]
Containers --> Target["π― In-scope target<br/>(dev sandbox: Juice Shop)"]
classDef box fill:#06210f,stroke:#16a34a,stroke-width:1.5px,color:#dcfce7;
classDef data fill:#0a1722,stroke:#47bfff,stroke-width:1.5px,color:#dff1ff;
class API,Containers,Target box;
class DB,Vec,Ollama,Claude data;
style Browser fill:#06210f,stroke:#16a34a,color:#dcfce7;
style Backend fill:#06210f,stroke:#16a34a,color:#dcfce7;
style MCP fill:#06210f,stroke:#16a34a,color:#dcfce7;
style Data fill:#0a1722,stroke:#47bfff,color:#dff1ff;
style LLM fill:#0a1722,stroke:#47bfff,color:#dff1ff;
Why single-writer? Every graph mutation β from users, the AI, and tool-result ingestion β is serialized through one process per engagement. Write races are impossible by construction, so the AI only ever mediates semantic conflicts (e.g. "Apache" vs "nginx"), never write ordering. See
docs/decisions/0001-*andbackend/app/features/graph/writer.py.
Adeptus is built with Claude Code, under strict vertical-slice discipline: every feature
ships end-to-end (UI + API + DB + tests) as exactly one PR. Subagents do investigation and review in
isolated context windows, skills automate the repeatable workflow, and hooks enforce non-negotiables
deterministically. The full operational architecture lives in
CLAUDE_CODE_ARCHITECTURE.md.
flowchart LR
A["π§ pick-next-slice"] --> B["π slice-planner"]
B --> C{"π€ Human<br/>approves plan"}
C --> D["π± start-slice<br/>+ branch"]
D --> E["π contract-first<br/>OpenAPI delta"]
E --> F["βοΈ implementer<br/>one task at a time"]
F --> G["π§ͺ test-writer<br/>to coverage gate"]
G --> H["π code-reviewer"]
H --> I["π‘οΈ security-reviewer<br/>(risky slices)"]
I --> J["π finish-slice<br/>β PR"]
J --> K{"π€ Human<br/>merges PR"}
K --> A
classDef step fill:#06210f,stroke:#16a34a,stroke-width:1.5px,color:#dcfce7;
classDef gate fill:#2a1206,stroke:#d97757,stroke-width:1.5px,color:#ffe6d8;
class A,B,D,E,F,G,H,I,J step;
class C,K gate;
| Layer | Choice |
|---|---|
| Packaging | Docker Compose (API + DB + frontend + Ollama in one stack), Linux (Kali / Parrot / Ubuntu) |
| Backend | Python 3.12 Β· FastAPI (async) Β· SQLAlchemy 2.x + Alembic Β· Pydantic v2 Β· argon2 |
| Frontend | Vite Β· React 18 Β· TypeScript (strict) Β· TanStack Query Β· Zustand Β· Tailwind + shadcn/ui Β· Cytoscape Β· xterm.js |
| Database | PostgreSQL 16 + pgvector (hnsw ANN) |
| Graph | NetworkX in-memory, single-writer process per engagement, persisted to Postgres |
| LLM | Ollama (local-first, default small quantized model) Β· Claude API (optional, per-engagement) |
| Embeddings | nomic-embed-text via Ollama |
| Tools / MCP | stdio MCP subprocess per tool category Β· Docker tool containers Β· per-engagement networking |
| Transport | REST + WebSockets |
Warning
Adeptus runs offensive tooling. Only point it at systems you are explicitly authorized to test. In dev/test, pentest tools are hook-blocked against anything other than the bundled sandbox.
# Bring up the full stack (API + DB + frontend + Ollama), hot-reload
make dev
# Bring up the intentionally-vulnerable sandbox to test tooling safely
make sandbox # Juice Shop on http://localhost:3000
# Run everything CI runs: lint + typecheck + tests + coverage gate
make testOther essentials: make migrate (Alembic upgrade), make generate-api (regenerate the typed
OpenAPI client after backend contract changes), make format. See make help or
CLAUDE.md for the full list.
Day-0 setup for building with Claude Code
# 1. Install pre-commit hooks
pre-commit install
pre-commit install --hook-type commit-msg
# 2. Make Claude Code hooks executable
chmod +x .claude/hooks/*.sh
# 3. Start Claude Code in this directory
claude
# 4. Install plugins (one-time, user scope)
> /plugin install feature-dev@claude-plugins-official
> /plugin install code-review@claude-plugins-official
> /plugin install frontend-design@claude-plugins-official
> /plugin install commit-commands@claude-plugins-official
# 5. Add MCP servers (one-time)
> /mcp add context7
> /mcp add postgres
> /mcp add playwright
> /mcp add github
# 6. Drive the per-slice loop
> use pick-next-slice # picks the next todo slice, delegates to slice-planner
> use start-slice NN # plan-gated execution β waits for your approval before code.claude/ β Claude Code config: agents, skills, hooks, settings.json
backend/ β FastAPI; one folder per feature in app/features/
frontend/ β Vite + React + TS; mirrors backend feature folders
mcp-servers/ β Internal MCP servers (one per tool category)
sandbox/ β Juice Shop sandbox compose for safe pentest-tool testing
docs/
requirements.md β locked spec (authoritative)
architecture.md β living architecture
decisions/ β ADRs
slices/ β vertical slice specs + PROJECT_PLAN.md
runbooks/ β operational how-tos
.github/workflows/ β CI (lint, typecheck, test, secret-scan)
Vertical slices are tracked in docs/slices/PROJECT_PLAN.md (the
source of truth) and mirrored to GitHub Issues. 21 of 42 slices are merged.
| Phase | Theme | Status |
|---|---|---|
| A | Foundation β auth, engagements, privacy mode | β done |
| B | Core mechanics β MCP tools, concurrency, graph, audit hash-chain | β done |
| C | AI integration β local/cloud LLM, autonomy, approvals, personas | β done |
| D | Findings & attack paths β lifecycle, dedup, ATT&CK | π§ in progress |
| E | RAG & retest β curated KB, uploads, retest workflow | β¬ planned |
| F | Collaboration & polish β presence, mentions, replay, terminal | β¬ planned |
| G | Reporting & ops β reports, admin dashboard, backups, TLS | β¬ planned |
- Authorized use only. Adeptus is for engagements you are contracted and authorized to perform.
- Sandbox-only in dev/test. A pre-bash hook blocks pentest tools against any non-sandbox target; the only authorized real target in development is the bundled Juice Shop sandbox.
- Legal gate. A one-time terms-of-use acceptance is required on first login.
- Privacy is safe-by-default. New engagements are strict local-only; cloud egress requires an explicit admin opt-in and passes the secret-pattern friction check.
- Tamper-evident audit. Every tool run, AI call, graph edit, login, and approval is recorded in a hash-chained audit log.
Apache-2.0 β see docs/decisions/0005-license-apache-2.md.
Built with Claude Code Β· one vertical slice at a time.