CLAUDE.md
August 21, 2026 · View on GitHub
What This Is
PentestCode — AI pentesting agent, hard fork of OpenCode (dev branch, MIT). OpenCode — coding agent (183k stars). We stripped code-editing focus and rebuilt it for penetration testing.
Stack: TypeScript, Bun, Effect library, Turbo monorepo. TUI: React/Ink (via @opentui). LLM: ai-sdk (20+ providers). DB: SQLite (drizzle-orm).
Project Structure
opencode-fork/ # Will be renamed to pentestcode
├── packages/
│ ├── core/src/ # Domain logic, tools, sessions
│ │ ├── engagement/ # NEW: pentest state (schema, store, context)
│ │ ├── session/ # Session management (runner, compaction)
│ │ ├── tool/ # Tool registry + built-in tools
│ │ ├── system-context/ # Context sources injected into prompts
│ │ ├── skill/ # Skill discovery + loading
│ │ └── agent.ts # Agent schema, default ID = "pentest"
│ ├── opencode/src/ # Main application package
│ │ ├── agent/agent.ts # Agent definitions (pentest/recon/scanner/...)
│ │ ├── session/prompt/*.txt # System prompts per agent
│ │ ├── session/system.ts # Prompt assembly (uses pentest.txt)
│ │ ├── session/prompt.ts # Session runner loop
│ │ ├── tool/ # Tool implementations (registry.ts is master)
│ │ ├── skill/ # Skill discovery paths
│ │ └── cli/ # CLI commands (yargs)
│ ├── llm/ # LLM client abstraction (ai-sdk)
│ ├── tui/ # Terminal UI (React/Ink)
│ ├── server/ # HTTP server + SSE events
│ ├── schema/ # Shared type definitions
│ ├── protocol/ # HTTP API contracts
│ ├── plugin/ # Plugin system
│ └── client/ # Generated SDK client
├── skills/
│ ├── phases/ # Phase checklists (6 files)
│ ├── services/ # Service knowledge packs (9 files)
│ └── playbooks/ # Methodology playbooks (4 files)
└── ...
Multi-Agent Architecture
| Agent | Type | Description |
|---|---|---|
| pentest | primary (default) | Strategist-coordinator. Plans, spawns subagents, can execute directly. |
| recon | primary | Reconnaissance (passive/active by user choice). |
| scanner | subagent | Port/vuln scanning. Spawned for parallel host scanning. |
| enumerator | subagent | Deep service enumeration (SMB/LDAP/web/etc). |
| exploiter | subagent | Exploitation of specific vulnerabilities. |
| reporter | subagent | Report generation from engagement state. No bash. |
| identity | subagent | AD, LDAP, Kerberos, IAM, NTLM, certificate-based auth attacks. |
| infrastructure | subagent | Network services, SNMP, IPMI, RDP, SSH, FTP, databases, misconfigs. |
| post_exploit | subagent | Lateral movement, privesc, persistence, credential harvesting, pivoting. |
| exploit_dev | subagent | Custom exploits, payload generation, PoC development, bypass techniques. |
| critic | subagent | Finding validator. Checks false positives, validates evidence. Read-only. |
| webapp | subagent | Web application specialist. OWASP Top 10, API security, XSS, SQLi, SSRF. |
| reflector | subagent | Post-engagement reflection. Analyzes outcomes, generates learned skills, records knowledge. Read-only state. |
| compaction | hidden | Context compression (inherited from OpenCode). |
| title | hidden | Session title generation. |
| summary | hidden | Session summary. |
Agents defined in: packages/opencode/src/agent/agent.ts
Prompts in: packages/opencode/src/session/prompt/*.txt and packages/opencode/src/agent/prompt/*.txt
Key Files
- Agent loop:
packages/opencode/src/session/prompt.ts→runLoop()(line ~1081) - LLM call:
packages/core/src/session/runner/llm.ts - Tool registry:
packages/opencode/src/tool/registry.ts(master registry) - Tool definitions (core):
packages/core/src/tool/builtins.ts - System prompt assembly:
packages/opencode/src/session/system.ts - Agent definitions:
packages/opencode/src/agent/agent.ts - Engagement schema:
packages/core/src/engagement/schema.ts(Effect Schema, State/Host/Vuln/Cred types) - Engagement store:
packages/core/src/engagement/store.ts(global Ref + JSON persistence) - Engagement context (V2):
packages/core/src/engagement/context.ts(SystemContext source, V2 only) - Reflection schema:
packages/core/src/engagement/reflection.ts(TechniqueOutcome, FPPattern, LearnedTechnique, EngagementReflection) - Knowledge store:
packages/core/src/knowledge/store.ts(global cross-engagement memory,~/.pentestcode/knowledge/global.json) - Knowledge schema:
packages/core/src/knowledge/schema.ts(ToolEffectiveness, FPSignature, KnowledgeState) - Pentest tools:
packages/opencode/src/tool/state-query.ts,state-update.ts,nmap-parse.ts,nuclei-parse.ts,gobuster-parse.ts,cme-parse.ts,bloodhound-parse.ts,cred-spray.ts,scope-check.ts,phase-control.ts,report-gen.ts,sqlmap-parse.ts,xss-detect.ts,jwt-analyze.ts,tunnel-manage.ts,attack-path-suggest.ts,ensure-tools.ts,os-hook.ts,inject-probe.ts,knowledge.ts - App runtime (V1):
packages/opencode/src/effect/app-runtime.ts(LayerNode graph) - Location services (V2):
packages/core/src/location-services.ts(V2 layer graph) - Config:
.pentestcode/pentestcode.jsonc - Skills:
skills/directory, discovered via**/SKILL.mdglob
Commands
# Install dependencies
bun install
# Run (dev mode)
bun run dev
# Run TUI directly
bun run --cwd packages/opencode --conditions=browser src/index.ts
# Typecheck
bun turbo typecheck
What Was Done (Phase 1-3)
Phase 1: Fork & Strip
- Removed 12 packages: codemode, desktop, enterprise, storybook, docs, console, slack, stats, web, sdks, infra, artifacts
- Removed translated READMEs, SST config, Nix files
- Updated package.json: name→pentestcode, description→pentesting
- Removed edit/apply-patch/todowrite from core builtins
- Removed GitHub Copilot integration from core
- 178M → 109M
Phase 2: Pentest Domain + Wiring
- Agents rewritten: build/plan/general/explore → pentest/recon/scanner/enumerator/exploiter/reporter
- Default agent: "pentest" everywhere (was "build")
- Prompts created: pentest.txt, recon.txt, scanner.txt, enumerator.txt, exploiter.txt, reporter.txt + mode switching prompts
- system.ts: Always uses pentest.txt (bypasses model-specific coding prompts)
- Engagement state module: schema.ts (Effect Schema models), store.ts (file persistence), context.ts (SystemContext source)
- 19 skill files: 6 phases, 9 services, 4 playbooks
- Global engagement store:
~/.pentestcode/engagements/— NOT per-directory (security work isn't tied to a cwd) - EngagementStore.node registered in V1 app-runtime (
app-runtime.ts) and V2 location-services (location-services.ts) - Engagement context injected into V1 system prompt (
prompt.ts) — compact JSON with phase, mode, hosts, vulns - Auto-load: session start loads last engagement from
.lastfile - Skills config:
.pentestcode/pentestcode.jsonchasskills.paths: ["./skills"]. Relative skill paths resolve against the session cwd, each config-dir project root, and the global~/.pentestcode/skillshome — so bundled skills load regardless of cwd (seepackages/opencode/src/skill/index.tsdiscoverSkills)
Phase 3: Pentest Tools (6 tools, 12 files)
- state_query — query engagement state (11 query types: summary, hosts, vulns, creds, scope, phase, flags, tasks, host, full, engagements)
- state_update — structured mutations (20+ actions: CRUD for hosts/vulns/credentials/access, phases, modes, scope, flags, notes, attack steps, domain, objectives)
- nmap_parse — parse nmap XML/greppable output via htmlparser2 SAX, auto-updates engagement state
- nuclei_parse — parse Nuclei JSON output, auto-create vulns with severity
- gobuster_parse — parse gobuster/feroxbuster output, classify sensitive files/admin panels/backups
- cme_parse — parse CrackMapExec/NetExec output, auto-update creds/access/hosts
- bloodhound_parse — parse SharpHound JSON, populate AD domain model
- cred_spray — credential reuse planning (plan/suggest spray commands across discovered services)
- scope_check — CIDR containment, wildcard domain matching, excludes priority
- phase_control — status/next/set phase management
- report_gen — markdown/JSON reports with 6 sections (executive_summary, scope, findings, attack_path, credentials, recommendations)
- task_graph — Pentesting Task Tree (PTT) management
- All tools registered in
packages/opencode/src/tool/registry.ts - Agent permissions configured per-agent in
packages/opencode/src/agent/agent.ts
What Was Done (Phase 3 cleanup + Phase 4 partial + Phase 5)
Phase 3 Cleanup
- Deleted stale test files:
code-mode.test.ts,code-mode-integration.test.ts,apply_patch.test.ts,lsp.test.ts - Cleaned
parameters.test.ts— removed apply_patch/lsp/todo imports, schemas, and describe blocks - Deleted orphaned snapshot file
__snapshots__/parameters.test.ts.snap - Verified
@opencode-ai/codemodedependency already removed - Deleted orphaned description
todowrite.txt
Phase 4: Code-Editing Remnant Removal (partial)
- Removed
LspToolfrom registry init and builtin array (keptLSP.nodein deps — EditTool depends on LSP.Service) - Deleted
src/tool/lsp.tsandsrc/tool/lsp.txt(tool file + description) - Cleaned CLI tool rendering (
cmd/run/tool.ts) — removed ApplyPatchTool, LspTool, TodoWriteTool imports, types, render functions, TOOL_RULES entries (~300 lines) - Kept LSP/Format/Worktree service modules intact (deeply integrated, removal breaks types)
Phase 5: Flow System
- 8 slash commands:
/status,/targets,/vulns,/creds,/scope,/phase,/mode,/report- Template files in
packages/opencode/src/command/template/pentest-*.txt - Registered as built-in commands in
packages/opencode/src/command/index.ts
- Template files in
- Mode switching — mode directives injected into system prompt per engagement mode (auto/free/guided)
- Phase auto-transition hints —
phaseTransitionHint()inprompt.tssuggests next phase based on engagement state - TUI
/statusrenamed to/sysinfoto avoid conflict with pentest/status
What Was Done (Quality Plan — dapper-percolating-badger.md)
P1: Skill Auto-Loading
-
phase_control.ts— hints to load phase skill after phase change -
nmap-parse.ts— suggests relevant service skills after parsing -
pentest.txt— skill names listed, mapped to phases/services - Subagent prompts — added "Load relevant skills before starting" instructions
P2: Deepen Subagent Prompts
-
critic.txt— full rewrite (27→80+ lines) with validation methodology, false positive patterns - All subagents deepened with decision trees, failure handling, context management
P3: State Enforcement Reinforcement
-
state-update.txt— added urgency: "IMMEDIATELY after discovering" -
prompt.tsengagement context — added inline reminder -
orchestrator-mode.txt— added state_update mandate
P4: Tool Parsers
- nuclei_parse — parse Nuclei JSON output, auto-create vulns with severity mapping
- gobuster_parse — parse gobuster/feroxbuster output, classify sensitive files/admin panels/backups
- cme_parse — parse CrackMapExec/NetExec output, auto-update creds/access/hosts
- bloodhound_parse — parse SharpHound JSON, populate AD domain model
- All parsers registered in registry.ts with agent permissions
P5: Schema CRUD & Dedup
-
addVulndedup by (title, service_port) — updates existing on match -
addAccessdedup by (access_type, username) — updates existing on match -
addHostmerges services by port (not overwrite) viamergeServices() - Added
deleteHost,updateVuln,deleteVuln,deleteCredentialto store + state_update
P6: AD Domain Model
-
DomainStatetype in schema.ts (domain_name, forest, trusts, domain_admins, domain_controllers, gpo_names, password_policy) -
domain_infoon Host (domain, is_dc, computer_account, forest) - AD fields on Credential (domain, ticket_type, service_principal, ticket_expiry)
-
setDomain/updateDomainin store.ts and state_update tool
P7: Credential Reuse Tool
- cred_spray — plan/suggest actions, generates spray commands for discovered services
- Supports NTLM hash spraying, service filtering, existing-access dedup
- Registered with permissions on pentest, identity, infrastructure, post_exploit
P8: Prompt Realism
-
exploit-dev.txt— realistic capability claims (no ROP chains, honest about LLM limitations) - Host Exhaustion Protocol added to pentest.txt (ACCESS → EXHAUST → PIVOT)
- Anti-patterns explicitly documented (tunnel vision, skipping post-exploit)
Multi-Agent Improvements
- 6 new specialist subagents: identity, infrastructure, post_exploit, exploit_dev, critic, webapp
- Task graph tool for PTT (Pentesting Task Tree)
- Objectives system (add/update/complete objectives)
What Was Done (Architecture Roadmap — Waves 1-2)
Wave 1: Foundation
- Confidence Scoring —
confidence: number(0.0-1.0) on Vuln, Credential, Access. Parsers set base values (0.9-0.95). Displayed in state_query output and compact context. - Structured Evidence —
evidence_items: Array<{tool, command, output, timestamp, confidence}>on Vuln. Parsers populate with tool name and output. Summary inevidencestring field, full data inevidence_items. - Changelog — separate
changelog.json, every store mutation logged vialogChange().state_query changelogretrieves entries. Retention capped at 500 entries (CHANGELOG_MAX_ENTRIES). Loaded/saved alongside engagement state.
Wave 2: Intelligence
- State Diff Injection (#4) —
toDiffContext()in schema.ts computes delta from changelog entries.prompt.tstracks last injection timestamp viamarkInjected()/getLastInjectedTimestamp(). Each LLM turn sees "Changes since last turn:" before the full state dump, showing what's new.state_query diffalso available. - Auto-Critic (#5) —
criticHint()in schema.ts detects unvalidated vulns (status=suspected, confidence<0.8). Injected into prompt as<auto-critic>section with vuln list and instructions to spawn critic subagent. Parser outputs (nmap, nuclei, cme) include[Auto-critic]hints suggesting critic validation. Critic agent stays READ-ONLY, returns verdict → coordinator updates state. - Entity Relationships (#6) —
Relationshipschema with typed edges: EXPLOITED_VIA, CREDENTIAL_FROM, REACHABLE_FROM, TRUSTS, MEMBER_OF, ADMIN_OF, PIVOT_TO, AUTHENTICATES_TO, LATERAL_MOVE, CONTROLS.relationships[]on State. Store methods:addRelationship()(dedup by source+type+target),getRelationships()(filter by entity_id or rel_type),deleteRelationship(). Tools:state_update add_relationship/delete_relationship,state_query relationships. Auto-created by parsers: nmap→REACHABLE_FROM, cme→AUTHENTICATES_TO/ADMIN_OF, bloodhound→MEMBER_OF/ADMIN_OF/TRUSTS. Displayed in compact context. - Phase Quality Gates (#7) —
evaluateQualityGate()in phase-control.ts checks coverage metrics per phase before transition. Missing items block transition; warnings allow with notice.force:trueparameter skips all gates. Gates: recon (hosts+services), enumeration (version coverage), vuln_assess (confirmed vulns, unvalidated check), exploitation (compromised hosts), post_exploit (creds, lateral coverage, objectives).
Wave 3 Completion (2026-07-10)
Attack Path Derivation (#11)
-
attack_path_suggesttool (renamed frompivot_suggest): complete rewrite from 322→1140 lines - Cost model:
EDGE_BASE_COSTSmap for all 10 relationship types + default fallback (35) for unknown types - Modifiers: credential/vuln confidence, temporal penalty (expired→Infinity), live session bonus (×0.7), OPSEC noise (+0/+10/+20)
- Dijkstra + Yen's K-Shortest Paths (K=3) replaces BFS
- Entity projection: credential→host, user→DC, domain trust→DC-DC edges
- Segment-aware synthetic edges (not O(n²) complete graph anymore)
-
resolveObjectiveTargets(): "domain controller"/CIDR/IP/keyword → host IPs - Inline MinHeap, no external deps
Agent Context Carry (#12)
-
AgentContextSummaryschema in schema.ts (id, agent_type, timestamp, findings, failures, next steps) -
agent-contexts.jsonpersistence in store.ts (cap 10 per agent type) -
buildContextSummary()in task.ts: heuristic parser extracts findings/failures/next from subagent output -
formatPriorContext(): XML<prior-agent-context>block injected into fresh subagent prompts - Auto-save on completion (both background and foreground paths)
Inter-Agent Communication
-
AlertPriorityschema:"normal" | "interrupt"on Alert -
interruptQueueRefin store.ts: accumulates interrupt alerts,drainInterruptAlerts()to consume - Watcher fiber in task.ts: polls every 2s during background subagent, injects into coordinator
- prompt.ts: drains interrupt queue at top of engagement context injection
- state-update.ts: accepts
priorityfield inadd_alert - All 7 subagent prompts updated with interrupt alert instructions
Storage Layout (updated)
~/.pentestcode/engagements/<name>/
├── state.json # core (compact) — now includes relationships[]
├── changelog.json # deletable, retention 500
├── decisions.json # Wave 3 — deletable, retention 100
├── agent-contexts.json # Wave 3 — deletable, retention 10 per agent type
├── evidence/ # Wave 3 — deletable folder, files per vuln_id
├── wordlists.json # UX — deletable, retention 1000
└── findings.md # UX — deletable, auto-appended markdown
What Was Done (Competitive Gap Closure — 2026-07-09)
Gap 1: Decision Memory Context Injection
-
prompt.tsnow injects<decision-history>section into engagement context every turn - Shows last 5 decisions with outcomes (successful/failed/pending)
- Failure escalation: 3+ failures triggers warning to avoid repeating and spawn critic
-
decisionSummary()helper in schema.ts for aggregating decision stats
Gap 2: Evidence Chain Extension
-
EvidenceItemschema extended with:reasoning,source_agent,attempt_number,verification_status -
VerificationStatustype: "unverified"|"verified"|"false_positive" - Nuclei parser populates all new evidence fields (reasoning, source_agent, attempt, verification)
- CME parser populates evidence fields for SMB signing findings
- Report generator renders full evidence chain per finding (tool, agent, attempt#, status, reasoning)
- Compact context shows evidence_count + verified_by agents for each vuln
Gap 3: Web Application Tools (3 new tools)
- sqlmap_parse — parse sqlmap JSON/text output, extract injection points/params/techniques/databases, auto-create vulns
- xss_detect — analyze HTTP responses for reflected/stored XSS, check CSP/X-XSS-Protection headers, classify findings
- jwt_analyze — decode JWT, check alg:none/weak HMAC secrets/JKU injection/expiry/missing claims/admin escalation
- All 3 registered in registry.ts, permissions granted to pentest/webapp/exploiter agents
- Each tool auto-updates engagement state with findings + evidence chain
Gap 4: Network Pivoting & Tunnel Tools (2 new tools)
- tunnel_manage — plan tunnel commands (SSH/chisel/ligolo), register/list/remove live sessions in state
- attack_path_suggest (renamed from pivot_suggest) — cost-based Dijkstra + Yen's K-Shortest path-finding, all 10 relationship types, entity projection, objective targeting
- Both registered in registry.ts, permissions granted to pentest/post_exploit/infrastructure agents
Gap 5: Benchmark Infrastructure
-
bench/verify-claims.ts— validates tool availability (17/17), schema coverage (14/14), decision injection - 5 benchmark challenges: nmap-parse, nuclei-parse, cred-spray-plan, scope-check, cme-parse-ad
-
bench/challenges/directory with JSON challenge definitions -
bench/results/directory for benchmark run outputs - Exit code 0 = all claims verified, exit code 1 = gaps remain
NetExec Migration (crackmapexec → netexec)
-
cred_spraytool: all spray commands now usenetexecinstead ofcrackmapexec -
cme_parsetool: evidence references updated to "netexec" -
cred-spray.txtandcme-parse.txtdescriptions updated
Session Critique Fixes (from Standoff365 session analysis — 2026-07-09)
- Mandatory Parser Workflow — added MANDATORY section to pentest.txt + all 8 subagent prompts binding nmap→nmap_parse, netexec→cme_parse, nuclei→nuclei_parse, gobuster→gobuster_parse, sqlmap→sqlmap_parse, bloodhound→bloodhound_parse, creds→cred_spray. Anti-patterns documented.
- Batch state_update — new
batchaction accepts{operations: [{action,data},...]}array (max 100). Turns 40 sequential LLM steps into 1 for initial engagement setup. Prompt guidance added. - Context Size Reduction —
toCompactContext()now has caps: 10 vulns/host (by severity), 15 services/host, 30 relationships, 10 objectives. OODA fields (alerts/sessions/segments) excluded by default (already intoOODAContext()). Conditional injection: full state on step 1 + every 8th step, summary-only on other steps. ~75% token reduction. - Parallel Dispatch Strengthening — added CORRECT/WRONG examples with multi-tool-use blocks to orchestrator-mode.txt and pentest.txt. Explicit anti-pattern: "dispatch one per turn → WRONG".
What Was Done (Community Feedback UX — 2026-07-12)
Wordlist Usage Tracking
-
WordlistUsageschema:(host_ip, port, tool_type, wordlist_path)granularity — tracks what was tried where -
WordlistToolType: dir_fuzz, brute, vhost, subdomain, user_enum, param_fuzz, password_spray -
wordlists.jsonpersistence (deletable, retention 1000) — loaded/saved alongside engagement -
addWordlistUsage()dedup by full tuple,getWordlistUsages()with optional filter -
state_update record_wordlist/state_query wordlists— tools for agents to track usage -
wordlistSummary()helper groups by host:port → tool_type → paths -
<wordlist-usage>context injection in prompt.ts (capped at 50 entries) - "Wordlist Tracking — MANDATORY" sections in pentest.txt, enumerator.txt, webapp.txt, infrastructure.txt
Findings Journal (findings.md)
-
appendFinding()in store.ts — write-only append, no Ref, best-effort I/O - Auto-appended on
addVuln(severity icon, title, host, status, evidence chain) - Auto-appended on
addCredential(type, source, valid_for, domain) - Auto-appended on
addAccess(type, user, level, details) - Human-readable markdown with timestamps — reviewable during sessions
- Mentioned in pentest.txt so agent tells user about it
Pause on Finding
-
PauseBehaviortype: "never" | "always" | "checkpoint" — orthogonal to mode (auto/free/guided) -
pause_on_findingfield on State (optional, default "never") -
setPauseBehavior()in store,state_update set_pauseaction -
/pauseslash command (template + registration in command/index.ts) -
pauseDirectivesin prompt.ts — injected after engagement context when not "never" - Subagents do NOT pause individually — findings flow to coordinator via alerts
Output Overflow Prevention
- "Output Management — MANDATORY" section in pentest.txt with 15+ tool-specific patterns
- "Context Management — MANDATORY" sections in all subagent prompts (scanner, enumerator, exploiter, infrastructure, webapp, post-exploit)
- "Output Rules" reminders in 4 skill files (enumeration, exploitation, smb, web-server)
Slash Command Discoverability
- "Available Commands — Mention to Users" section in pentest.txt
- Contextual
<command-hints>injection in prompt.ts based on engagement state - 3 new tips in TUI tips-view.tsx (/creds, /mode, /pause)
Storage Layout (updated)
~/.pentestcode/
engagements/<name>/
├── state.json # core (compact)
├── changelog.json # deletable, retention 500
├── decisions.json # deletable, retention 100
├── agent-contexts.json # deletable, retention 10 per agent type
├── evidence/ # deletable folder, files per vuln_id
├── wordlists.json # deletable, retention 1000
├── findings.md # deletable, auto-appended markdown
└── reflection.json # deletable, per-engagement reflection
knowledge/
global.json # cross-engagement stats (tool effectiveness, FP patterns)
skills/user/learned/ # auto-generated skills from reflector
What Was Done (CyberStrike Competitive Analysis — 2026-08-15)
P3: Prompt Improvements (from CyberStrike analysis)
- ReAct discipline — Thought→Action→Observation +
[CONFIRMED]/[LIKELY]/[UNVERIFIED]confidence labels in kernel.txt (all agents) - Evidence quality gates — structural validation before add_vuln HIGH/CRITICAL: web=method+URL+param+response, network=service+version+CVE+proof, credential=source+tested-target
- Candidate→Confirmed — execution-dependent vulns (XSS/SSTI/cmdi/upload/deser) without execution evidence → suspected, confidence ≤0.7
- Long-running commands — script + background strategy for >30s operations in kernel.txt
- Delegation quality examples — good/bad side-by-side with concrete prompt text + error analysis in pentest.txt
- Chain detection — 8 patterns (credential_endpoint, info→SSRF, redirect→OAuth, IDOR+enum, XSS→CSRF, SSTI→RCE, race→business, cred_reuse→lateral) in pentest.txt + orchestrator-mode.txt ORIENT phase
- Confidence tagging — coordinator-level CONFIRMED/LIKELY/UNVERIFIED assessment of subagent results in pentest.txt
P2: New Tools (from CyberStrike analysis)
- ensure_tools — check/install 21 common pentest tools (nmap, nuclei, ffuf, httpx, sqlmap, netexec, hydra, hashcat, impacket, chisel, certipy, bloodhound-python, etc.) with platform-aware installers (apt/brew/pip/go). Registered for pentest, recon, scanner agents.
- os_hook — structured post-exploitation command generator for Windows (14 submodules) and Linux (12 submodules). Modules: recon, credential, privesc, lateral, persistence, evasion. Returns ready-to-run commands with descriptions, prerequisites, opsec notes, and alternatives. Registered for pentest, post_exploit, infrastructure, identity, exploit_dev agents.
- All subagent prompts updated with os_hook usage guidance (post-exploit.txt, infrastructure.txt, identity.txt)
- pentest.txt updated with ensure_tools + os_hook toolkit section
P1: High Impact (from CyberStrike analysis)
- inject_probe — structured HTTP injection probing tool. Fires up to 120 targeted payloads per call across 9 vuln classes (xss, ssti, cmdi, sqli, nosql, lfi, ssrf, ldap, xpath). Auto-enumerates injection points (query/body/cookie). Returns STRONG/WEAK leads with evidence (observations, not verdicts). WAF detection, boolean differential analysis for SQLi, math marker evaluation for SSTI. Auto-updates engagement state with suspected findings. Registered for pentest, webapp, exploiter agents. webapp.txt updated with inject_probe usage guidance.
- VRT coverage tracking — methodology_status tool, coverage % injection in prompt
What Was Done (Self-Improvement System — 2026-08-17)
Hermes-style Post-Engagement Reflection
- Reflection schema (
packages/core/src/engagement/reflection.ts) — EngagementReflection, TechniqueOutcome, FPPattern, LearnedTechnique, ReflectionStats - Knowledge schema (
packages/core/src/knowledge/schema.ts) — KnowledgeState, ToolEffectiveness (cap 500), FPSignature (cap 200) - KnowledgeStore (
packages/core/src/knowledge/store.ts) — global cross-engagement memory at~/.pentestcode/knowledge/global.json. Per-engagement reflections atengagements/<name>/reflection.json. Dedup by (tool,technique,service) for effectiveness, (vuln_pattern,reporting_tool) for FP.suggest()method for context injection. - knowledge tool (
packages/opencode/src/tool/knowledge.ts) — 6 actions: query, record_effectiveness, record_fp, save_reflection, list_reflections, suggest. Registered for pentest, reflector, critic agents. - Reflector agent — new subagent (steps:50, state_update:deny, bash:deny, write:allow, knowledge:allow). Analyzes engagement outcomes, generates SKILL.md files to
~/.pentestcode/skills/user/learned/, records tool stats and FP patterns. -
/reflectslash command — spawns reflector subagent on current or named engagement - Context injection —
SystemPrompt.knowledge()queries KnowledgeStore for relevant patterns matching current engagement services, injects<cross-engagement-knowledge>block into static prefix (~500 tok cap) - Skill auto-generation — reflector writes SKILL.md to
~/.pentestcode/skills/user/learned/<name>/SKILL.mdwith proper frontmatter. Existing skill discovery auto-discovers with zero code changes. - Wired into V1 app-runtime.ts + V2 location-services.ts + registry.ts + system.ts + prompt.ts
Storage Layout (updated)
~/.pentestcode/
engagements/<name>/
reflection.json # NEW — per-engagement reflection output
... (existing files)
knowledge/
global.json # NEW — aggregated cross-engagement stats
skills/user/
learned/ # NEW — auto-generated skills from reflector
<technique-name>/
SKILL.md
What Remains (TODO)
Wave 3: Strategy (remaining items)
- Decision Memory (#8) — decisions.json fully implemented (schema, store, CRUD, state_update/state_query). Context injection into prompt added.
- Alert Queue (#9) — fully implemented (schema, store, TTL, max 50, OODA display, state_update/state_query).
- OODA Structured Reasoning (#10) —
toOODAContext()fully implemented (changes, coverage, gaps, alerts, sessions, segments, tasks, objectives). - Attack Path Derivation (#11) —
attack_path_suggesttool: Dijkstra + Yen's K-Shortest (K=3), cost model with 10 relationship types, credential/vuln confidence, temporal validity, OPSEC scoring, entity projection (cred→host, user→DC, domain trust→DC-DC), segment-aware synthetic edges, objective targeting. Renamed frompivot_suggest. - Parallel Subagent Improvements (#12) — parallel dispatch examples + anti-patterns in orchestrator-mode.txt and pentest.txt. Agent context carry implemented:
agent-contexts.jsonpersists per-agent-type summaries (findings, failures, next steps), auto-injected into fresh subagent instances.
Agent Quality (from real Standoff365 testing)
-
Scope guard on bash tool— CANCELLED per Zhangir's decision - Tool knowledge in prompts — mandatory parser workflow added to all agent prompts. Parser tools now MUST be used after their corresponding bash commands. Additional tool-specific knowledge can be added as issues surface.
- Inter-agent communication — interrupt alerts (
priority: "interrupt"on alerts). Subagents raise interrupt for critical findings (DC found, admin creds, RCE). Watcher fiber in task.ts polls every 2s, injects into coordinator viainject(). Prompt.ts drains interrupt queue on every turn. All subagent prompts updated with interrupt alert instructions. - Session/shell tracking —
LiveSessionschema +tunnel_managetool +live_sessionsin OODA context. Agents can now register/track/remove tunnels and shells. - Network segmentation model —
NetworkSegmentschema +attack_path_suggesttool. VLANs, reachable networks, pivot hosts tracked in state and used for path suggestions.
Slash Commands
-
/pause— set pause behavior on findings (never/always/checkpoint) -
/reflect— post-engagement reflection, generates learned skills + knowledge -
/playbook— load and follow a playbook interactively -
/export— export engagement state to external formats
TUI & Branding
- Rebrand TUI (banner, logo, colors)
- Add engagement status bar (phase, hosts, vulns, creds counts)
- Add vulnerability/host/credential table rendering in TUI
- Rename config dir from
.opencode/to.pentestcode/ - Rename
@opencode-ai/*package scopes to@pentestcode/*(or keep as fork)
Code Cleanup (deferred — not blocking)
- Remove or stub LSP service module (
packages/opencode/src/lsp/) — EditTool depends on LSP.Service - Remove or stub Format integration (
packages/opencode/src/format/) - Remove or repurpose git-specific logic (
packages/opencode/src/git.ts) - Remove worktree support (
packages/opencode/src/worktree/) — needs httpapi + test cleanup - Clean up
packages/opencode/src/session/reminders.ts— may still reference coding concepts
Build & Release
- Cross-compile binaries (`bun run build --skip-embed-web-ui$) — \text{linux}/\text{darwin} \times \text{x64}/\text{arm64} + \text{baseline} + \text{musl} (\text{no} \text{Windows} \text{targets})
- \text{Smoke} \text{test} \text{binary} \text{on} \text{current} \text{platform} ($bun run build --single --skip-embed-web-ui`)
- Set up GitHub Release workflow (
OPENCODE_RELEASE=1 GH_REPO=s0ld13rr/pentestcode bun run build) - Verify install.sh works against published release
Testing
- End-to-end test on CTF target with new build
- Verify engagement state persistence across sessions
- Test multi-agent coordination (coordinator spawns 3+ subagents in parallel)
- Test parser tools with real tool output (nmap, nuclei, netexec, gobuster, bloodhound, sqlmap)
Design Decisions
- Hard fork, no upstream tracking — deep domain changes make merging impractical
- Multi-agent strategist-operator split — pentest agent coordinates, subagents execute (4.3x improvement per HPTSA research)
- Pentesting Task Tree (PTT) — hierarchical attack tree with difficulty scoring, strategic abandonment, credential propagation
- Selective context injection — full state every 8 turns, summary+diff on other turns; OODA and compact contexts deduplicated
- 4-layer prompt system — identity (always) → engagement state (dynamic) → phase skill (per-phase) → service knowledge (on-demand)
- File-based engagement store — single JSON at
~/.pentestcode/engagements/<name>/state.json, not relational; simpler and portable - Global storage — engagements at
~/.pentestcode/engagements/, not per-directory. Security work isn't tied to cwd. Supports parallel activities (bounty + CTF + work pentest). - Universal tools — tools work for pentesting, bug bounty, vuln research, CTF, infra security. Not narrowly scoped.
- Skills as SKILL.md files — no code changes needed, just add markdown files
- edit tool kept — useful for modifying exploit scripts, payloads, configs
- recon agent has full tool access — passive/active controlled by prompt and user choice, not permissions
- Multi-session on same engagement — two terminals can load the same engagement. Each has its own Ref. Last-write-wins on disk.
state_update reload_engagementto pick up changes from other session.
Architecture Notes (gotchas)
Two Prompt Systems: V1 and V2
- V1 (
packages/opencode/) — active for interactive TUI sessions. Usesprompt.ts→runLoop(). Does NOT useSystemContextRegistry. - V2 (
packages/core/) — durable runner path. UsesSystemContextRegistry,LocationServiceMap, etc. - EngagementStore.node is
makeGlobalNode(no deps) — works in both V1 and V2 graphs. - EngagementContext.node is
makeLocationNode(depends on SystemContextRegistry) — V2 only. V1 injects engagement context directly inprompt.ts.
Effect Layer System
makeGlobalNode: no scope dependencies, goes inAppLayerand any graphmakeLocationNode: depends on Location.Service (scoped), only works in location-scoped graphs- Rule: a global node CANNOT depend on a location-scoped node. Reverse is fine.
LayerNode.make(used in V1app-runtime.ts): can go in either graph
Effect Schema (v4 beta)
Schema.Literal("a")— single literal (1 arg only)Schema.Literals(["a", "b", "c"])— literal union (takes array)Schema.optional(Schema.X)— optional field (noSchema.optionalWith, no defaults in schema)Schema.Record(Schema.String, ValueSchema)— positional args, NOTSchema.Record({ key, value })- No
Schema.withDefaultin this version. Handle defaults in application code (store.create, tool constructors).
Tool Pattern (V1)
export const MyTool = Tool.define("tool_id", Effect.gen(function* () {
const store = yield* SomeService
return {
description: DESCRIPTION_FROM_TXT,
parameters: Schema.Struct({ ... }),
execute: (params, ctx) => Effect.gen(function* () {
// ...
return { title: "...", metadata: {}, output: "..." }
}).pipe(Effect.orDie),
}
}))
Multi-Agent State Sharing
- All agents in same session share the same EngagementStore.Service Ref (cooperative fibers, no race conditions in single-thread Bun).
- Subagent spawned via
tasktool gets fresh prompt context but shares same Ref. - State updates by subagent are immediately visible to parent agent.