Metadata-Version: 2.4
Name: pentestcode
Version: 0.3.0
Summary: An agentic, workflow-driven pentesting CLI. Claude Code-style architecture for authorized offensive security.
Author: PentestCode Contributors
Maintainer: Arpitpm23
License: Apache-2.0
Project-URL: Homepage, https://github.com/Arpitpm23/pentestcode
Project-URL: Repository, https://github.com/Arpitpm23/pentestcode
Project-URL: Issues, https://github.com/Arpitpm23/pentestcode/issues
Keywords: pentesting,security,agents,llm,cli
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Security
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: litellm>=1.40
Requires-Dist: typer>=0.12
Requires-Dist: rich>=13.0
Requires-Dist: pydantic>=2.0
Requires-Dist: docker>=7.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: filelock>=3.12
Requires-Dist: prompt-toolkit>=3.0
Requires-Dist: tiktoken>=0.5
Provides-Extra: tui
Requires-Dist: textual>=0.60; extra == "tui"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Dynamic: license-file

# PentestCode

[![PyPI](https://img.shields.io/pypi/v/pentestcode)](https://pypi.org/project/pentestcode/)
[![Python](https://img.shields.io/pypi/pyversions/pentestcode)](https://pypi.org/project/pentestcode/)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)

An agentic, workflow-driven pentesting CLI. Claude Code-style architecture —
tool modules, permission modes, subagents, **dynamic workflows**, conversation
compaction, and agent teams — rebuilt from scratch for **authorized** offensive
security, on top of a Docker sandbox and a LiteLLM brain that talks to any model.

> **Authorized testing only.** PentestCode is built for security professionals
> testing systems they own or have explicit written permission to test. Like
> Metasploit or nuclei, the tool does not police your targets — **you** are
> responsible for having authorization for anything you point it at.

---

## Why not just Kali + scripts?

Kali gives you tools; PentestCode gives you an *operator*. It:

- **Remembers the environment.** All engagement state lives in plain markdown
  (`.pentestcode/`), so it never re-runs recon it already did and any session can
  resume mid-engagement — even after the conversation is compacted.
- **Fans out work as workflows.** Describe a task and it writes an orchestration
  script that spawns dozens of focused subagents in parallel (recon per host,
  enum per service, a scanner per target) — then an **adversarial verifier**
  re-tests every candidate finding before it's allowed into the report.
- **Runs everything in a sandbox.** Every command executes inside a Kali Docker
  container, never on your host.
- **Streams like Claude Code.** Assistant text streams token-by-token into the
  TUI, tool calls render as live rows with elapsed time, long scans run on a
  worker thread so the interface never freezes, and **Esc interrupts** a run
  mid-turn. Commands are wrapped in the container's `timeout` binary so a hung
  scan can't stall the session.
- **Compacts long engagements.** Auto-summarizes the conversation as it nears
  the context window, anchored to the memory files so nothing real is lost.
- **Zero setup.** No init, no scope ceremony — `pentestcode chat`, type a
  target, go. Just like Claude Code.

## The architecture

```
you ──> CLI (Typer) ──> Agent loop ──> LiteLLM ──> any model (Claude/GPT/local)
              │              │
              │              ├─> Tools ──> PermissionGate ──> Docker sandbox (Kali)
              │              │
              │              ├─> MemoryStore  (.pentestcode/*.md — env memory)
              │              ├─> CompactionManager (auto /compact)
              │              ├─> Subagents (isolated contexts)
              │              ├─> WorkflowRuntime (agent()/pipeline(), checkpoints)
              │              │      └─> Adversarial Verifier
              │              └─> TeamManager (shared tasks + mailboxes)
              │
              └─> ReportGenerator ──> report.md + report.html
```

## Install

Requires Python 3.9+, Docker running, and one model key (`ANTHROPIC_API_KEY`,
`OPENAI_API_KEY`, or an Ollama/LM Studio endpoint).

**From PyPI (one command):**
```bash
pip install "pentestcode[tui]"     # [tui] = the terminal UI
```

**Straight from GitHub (no clone):**
```bash
pip install "pentestcode[tui] @ git+https://github.com/Arpitpm23/pentestcode.git"
```

**From a local clone (recommended if you'll edit the code):**
```bash
git clone https://github.com/Arpitpm23/pentestcode.git
cd pentestcode
pip install -e ".[tui]"     # -e = editable, .[tui] = this repo + the TUI
```

> Use **either** `pip install` **or** `pipx install` — not both. `pipx` is just
> pip in an isolated venv (nice for CLI tools); swap `pip install` →
> `pipx install` in any command above if you prefer it.

Then verify:
```bash
pentestcode doctor        # checks docker + API keys
```

## Quickstart

No init, no scope file required. Just open the chat and go:

```bash
pentestcode chat
# (optional, once: build the Kali sandbox image)
pentestcode init
```

Inside `chat` — targets come straight from your messages:

```
> recon scanme.nmap.org                          # just say what to hit
> ultracode: audit dvwa.local end to end         # model writes its own workflow
> /workflow vuln_audit 10.0.0.5                  # scan + adversarially verify
> /context                                       # token usage before compaction
> /compact                                       # fold the conversation now
> /report                                        # md + html report
```

Want to *constrain* it to a scope? Write `.pentestcode/SCOPE.md` (or run
`pentestcode init --targets a.com,b.com`) and commands are checked against it.
No SCOPE.md → runs unrestricted, like any CLI tool.

## Dynamic workflows

The centerpiece. Say `ultracode: <task>` (or `/workflow <name>`) and the model
writes a Python orchestration script using two primitives:

```python
result  = await agent(prompt, schema=None, label=None, tools=None, model=None)
results = await pipeline(items, fn, concurrency=None)
```

The script runs in a **restricted** runtime — no filesystem/shell/imports; only
its subagents can act. The plan lives in script variables, not the model's
context; intermediate results never touch the main conversation; every agent is
**checkpointed** to `.pentestcode/workflows/<run_id>/` so an interrupted run resumes
from cache. Scripts you like can be saved to `.pentestcode/workflows/` and re-run as
`/workflow <name>`.

Bundled workflows: `recon_sweep`, `service_enum`, `vuln_audit`,
`exploit_verify`, `full_engagement`.

## Adversarial verification

Scanners lie. Every candidate finding a workflow produces is handed to a
separate verifier subagent whose job is to **refute** it — re-test the target,
hunt for false positives. Only `confirmed` findings are written to
`FINDINGS.md` and into the report. This is the difference between a 40-item
nuclei dump and a 6-item report you can defend.

## Environment memory

`.pentestcode/` is the agent's long-term memory, in human-editable markdown:

| File | What it holds |
|------|---------------|
| `SCOPE.md` | authorized targets, constraints, authorization |
| `STATE.md` | hosts, services, credentials, current phase, done-list, open threads |
| `FINDINGS.md` | **verified** findings only |
| `WORKLOG.md` | append-only log of every command + outcome |

Read at session start, injected again after compaction, updated the moment the
agent learns anything. Diff it in git, edit it by hand, the agent adapts.

## Agent teams

For work that needs parallel *collaboration* (not just fan-out):

```bash
pentestcode teams "full audit of the web tier" --members recon,web,network
```

A lead session spawns independent teammates — own context, own compaction —
coordinating through a shared, file-locked task list and JSON mailboxes, with
plan-approval gates before risky stages.

## Safety model

PentestCode takes the same posture as Metasploit, nuclei, or sqlmap: **the
tool doesn't police your targets — you do.** It runs unrestricted by default and
acts on whatever you give it in chat. Two things are on you:

- **Have authorization** for every target. This is an authorized-testing tool.
- The Docker sandbox isolates commands from *your host* — it does not make an
  unauthorized target authorized.

Optional friction you can turn on:

- **Scope guidance:** write `.pentestcode/SCOPE.md` (or
  `pentestcode init --targets a.com,b.com`) and the agent is told to stay inside
  it (the list is injected into its instructions and read back on demand). This
  is guidance, not a hard network boundary — the sandbox doesn't block egress.
  Delete the file to run unrestricted.

## The TUI

The default interface is a full-screen terminal UI (built on prompt_toolkit,
the same class of framework Claude Code's Ink renderer is). It streams the
model's text token-by-token, renders each tool call as a live row with elapsed
time, keeps the interface responsive during long scans (docker exec runs on a
worker thread), and lets you **Esc** to interrupt a run mid-turn. Commands are
wrapped in the container's `timeout` binary so a hung scan can't stall the
session. Input typed while the agent is busy is queued, not dropped.

## Permission modes

Every command runs **inside the Docker sandbox** — nothing ever executes on your
host (not even `ls`). The container is the only execution path and can only
reach the engagement workspace volume. So permissions are about *friction*, not
*isolation*. Five modes, cycled with **shift+tab**:

| Mode | Behavior |
|------|----------|
| `default` | Ask before any command not covered by an allow rule. Approval dialog: **↑/↓** navigate, **enter/y** allow, **a** always, **n/esc** deny. |
| `acceptEdits` | Auto-approve file edits in the engagement workspace; still ask for `bash`. |
| `plan` | Read-only research mode. `bash`/writes are denied outright; grep/glob/read run free. |
| `bypassPermissions` | Run everything without asking. Safe because the command is confined to the container. |
| `dontAsk` | Every prompt becomes a denial (headless-safe). |

Switch with `/mode <name>` or cycle with **shift+tab**. Persistent rules live in
`settings.yaml` under `permissions.rules` (`allow`/`ask`/`deny` lists, e.g.
`"bash"`, `"bash:nmap *"`, `"file_write"`); a session-scoped *always* choice
remembers a base command until you exit.

## Hooks

Run your own shell commands on agent lifecycle events, from `settings.yaml`:

```yaml
hooks:
  PreToolUse:
    - matcher: "bash"
      hooks:
        - type: command
          command: "echo \"about to run: $TOOL_NAME\" >> /tmp/audit.log"
  PostToolUse:
    - matcher: "bash|file_write"
      hooks:
        - type: command
          command: "./scripts/notify.sh"
          timeout: 10
```

Events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `UserPromptSubmit`,
`SessionStart`, `SessionEnd`, `Stop`, `PreCompact`, `PostCompact`,
`SubagentStart`, `SubagentStop`. A hook gets JSON on stdin; exit code **2**
blocks the tool (stderr goes back to the model), JSON stdout can rewrite input
or inject context. Matchers are exact, pipe-lists (`bash|file_write`), or regex.

## Configuration

`~/.pentestcode/settings.yaml` (user) and `.pentestcode/settings.yaml` (project).
Every `Config` field is settable there; env override: `PENTESTCODE_MODEL`.

```yaml
model:
  provider_model: claude-sonnet-4-6     # any LiteLLM model string
  subagent_model: gpt-5-mini            # cheaper model for workers
  effort: high                          # low|medium|high|ultracode
permissions:
  mode: default                         # default|acceptEdits|plan|bypassPermissions|dontAsk
  rules:
    allow: ["bash:nmap *", "file_read"]
    deny: []
workflows:
  max_concurrent_agents: 16
  size_guideline: medium                # unrestricted|small|medium|large
```

## Sessions

Conversations persist to `.pentestcode/sessions/<id>.jsonl`. Resume with
`pentestcode chat --continue` (latest), `pentestcode chat --resume <id>`, or
`/sessions` + `/resume <id>` inside chat.

## Community plugins

Drop your own workflows in `.pentestcode/workflows/<name>.py` — same `agent()` /
`pipeline()` primitives — and they appear next to the bundled ones. Custom slash
commands go in `.pentestcode/commands/<name>.md` (with YAML frontmatter for
description/argument-hint/allowed-tools); skills in `.pentestcode/skills/<name>/SKILL.md`.
See [docs/plugins.md](docs/plugins.md).

## Development

```bash
pip install -e ".[dev]"
pytest tests/    # memory, gate (5 modes), workflow runtime, streaming, interrupt
```

Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).

## License

Apache 2.0 — see [LICENSE](LICENSE).

---

*Architecture inspired by Anthropic's Claude Code (tool modules, permission
modes, subagents, hooks, dynamic workflows, compaction). Written from scratch;
no Claude Code source is used or distributed.*
