Skip to content

Latest commit

 

History

History
463 lines (391 loc) · 32 KB

File metadata and controls

463 lines (391 loc) · 32 KB

CLAUDE.md

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.
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.tsrunLoop() (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)
  • 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
  • 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.md glob

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 .last file
  • Skills config: .pentestcode/pentestcode.jsonc has skills.paths: ["./skills"]. Relative skill paths resolve against the session cwd, each config-dir project root, and the global ~/.pentestcode/skills home — so bundled skills load regardless of cwd (see packages/opencode/src/skill/index.ts discoverSkills)

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/codemode dependency already removed
  • Deleted orphaned description todowrite.txt

Phase 4: Code-Editing Remnant Removal (partial)

  • Removed LspTool from registry init and builtin array (kept LSP.node in deps — EditTool depends on LSP.Service)
  • Deleted src/tool/lsp.ts and src/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
  • Mode switching — mode directives injected into system prompt per engagement mode (auto/free/guided)
  • Phase auto-transition hints — phaseTransitionHint() in prompt.ts suggests next phase based on engagement state
  • TUI /status renamed to /sysinfo to 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.ts engagement 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

  • addVuln dedup by (title, service_port) — updates existing on match
  • addAccess dedup by (access_type, username) — updates existing on match
  • addHost merges services by port (not overwrite) via mergeServices()
  • Added deleteHost, updateVuln, deleteVuln, deleteCredential to store + state_update

P6: AD Domain Model

  • DomainState type in schema.ts (domain_name, forest, trusts, domain_admins, domain_controllers, gpo_names, password_policy)
  • domain_info on Host (domain, is_dc, computer_account, forest)
  • AD fields on Credential (domain, ticket_type, service_principal, ticket_expiry)
  • setDomain/updateDomain in 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 Scoringconfidence: 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 Evidenceevidence_items: Array<{tool, command, output, timestamp, confidence}> on Vuln. Parsers populate with tool name and output. Summary in evidence string field, full data in evidence_items.
  • Changelog — separate changelog.json, every store mutation logged via logChange(). state_query changelog retrieves 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.ts tracks last injection timestamp via markInjected()/getLastInjectedTimestamp(). Each LLM turn sees "Changes since last turn:" before the full state dump, showing what's new. state_query diff also 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) — Relationship schema 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:true parameter 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_suggest tool (renamed from pivot_suggest): complete rewrite from 322→1140 lines
  • Cost model: EDGE_BASE_COSTS map 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)

  • AgentContextSummary schema in schema.ts (id, agent_type, timestamp, findings, failures, next steps)
  • agent-contexts.json persistence 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

  • AlertPriority schema: "normal" | "interrupt" on Alert
  • interruptQueueRef in 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 priority field in add_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.ts now 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

  • EvidenceItem schema extended with: reasoning, source_agent, attempt_number, verification_status
  • VerificationStatus type: "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_spray tool: all spray commands now use netexec instead of crackmapexec
  • cme_parse tool: evidence references updated to "netexec"
  • cred-spray.txt and cme-parse.txt descriptions 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 batch action accepts {operations: [{action,data},...]} array (max 100). Turns 40 sequential LLM steps into 1 for initial engagement setup. Prompt guidance added.
  • Context Size ReductiontoCompactContext() now has caps: 10 vulns/host (by severity), 15 services/host, 30 relationships, 10 objectives. OODA fields (alerts/sessions/segments) excluded by default (already in toOODAContext()). 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

  • WordlistUsage schema: (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.json persistence (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

  • PauseBehavior type: "never" | "always" | "checkpoint" — orthogonal to mode (auto/free/guided)
  • pause_on_finding field on State (optional, default "never")
  • setPauseBehavior() in store, state_update set_pause action
  • /pause slash command (template + registration in command/index.ts)
  • pauseDirectives in 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      # NEW — deletable, retention 1000
└── findings.md         # NEW — deletable, auto-appended markdown

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_suggest tool: 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 from pivot_suggest.
  • Parallel Subagent Improvements (#12) — parallel dispatch examples + anti-patterns in orchestrator-mode.txt and pentest.txt. Agent context carry implemented: agent-contexts.json persists 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 via inject(). Prompt.ts drains interrupt queue on every turn. All subagent prompts updated with interrupt alert instructions.
  • Session/shell tracking — LiveSession schema + tunnel_manage tool + live_sessions in OODA context. Agents can now register/track/remove tunnels and shells.
  • Network segmentation model — NetworkSegment schema + attack_path_suggest tool. VLANs, reachable networks, pivot hosts tracked in state and used for path suggestions.

Slash Commands

  • /pause — set pause behavior on findings (never/always/checkpoint)
  • /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) — linux/darwin × x64/arm64 + baseline + musl (no Windows targets)
  • Smoke test binary on current 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_engagement to pick up changes from other session.

Architecture Notes (gotchas)

Two Prompt Systems: V1 and V2

  • V1 (packages/opencode/) — active for interactive TUI sessions. Uses prompt.tsrunLoop(). Does NOT use SystemContextRegistry.
  • V2 (packages/core/) — durable runner path. Uses SystemContextRegistry, 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 in prompt.ts.

Effect Layer System

  • makeGlobalNode: no scope dependencies, goes in AppLayer and any graph
  • makeLocationNode: 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 V1 app-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 (no Schema.optionalWith, no defaults in schema)
  • Schema.Record(Schema.String, ValueSchema) — positional args, NOT Schema.Record({ key, value })
  • No Schema.withDefault in 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 task tool gets fresh prompt context but shares same Ref.
  • State updates by subagent are immediately visible to parent agent.