Skip to main content

Pentest Code

A Claude Code–style agentic CLI for penetration testing. Same terminal UI, same tool-loop feel — but every command runs inside an isolated Docker sandbox, it talks to any model provider via LiteLLM, and it can spin up workflows and sub-agents just like Claude Code.

╭┄ Pentest Code  v1.0.3 ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮
┊                                                                       ┊
┊  Welcome to Pentest Code       ╭┄ Recent activity ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮  ┊
┊                                ┊ 2m ago    Probed sandbox (14 tools) ┊  ┊
┊     ▄█████▄                    ┊ just now  anon FTP on 10.0.0.5:21   ┊  ┊
┊    █████████                   ╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╯  ┊
┊    ██ ▄ ▄ ██                   ╭┄ Getting started ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╮  ┊
┊    █████████                   ┊ /workflow recon  run an engagement  ┊  ┊
┊    ███▄█▄███                   ┊ /auto · /manual  toggle approvals   ┊  ┊
┊    █▀█▀█▀█▀█                    ┊ Task             spin up sub-agents ┊  ┊
┊  anthropic/claude-sonnet-4     ╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╯  ┊
┊  manual mode · /root/engagement                                       ┊
╰┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄╯
──────────────────────────────────────────────────────────────────────────
  > Try "recon 10.0.0.0/24 and enumerate services"  ·  /help

⏺ Bash(nmap -sV 10.0.0.5)
  ⎿  22/tcp  open  ssh     OpenSSH 8.9
     80/tcp  open  http    nginx 1.18.0
     … +3 lines

The UI mirrors Claude Code's welcome dashboard — dashed panels, a title on the top edge, a neutral (braille) working spinner, and a > input with a rule above it. No Claude branding: a pixel skull stands in for the mascot.

⚠️ Authorised testing only. Use this exclusively against systems you own or have explicit written permission to test. You are responsible for staying in scope and complying with the law.


Highlights

Feature Details
Claude Code UI Welcome box, ⏺ tool bullets, ⎿ result branches, live spinner, todo checklist, bordered prompt, inline approval menu, clay accent.
Two modes only manual — approve every command; auto — nothing is asked. Toggle with shift+tab or /auto / /manual.
Docker-only sandbox All commands execute via docker exec in a Kali-based container. No local-execution fallback — your host is never touched.
Any provider (LiteLLM) Anthropic, OpenAI, Gemini, Groq, Mistral, DeepSeek, OpenRouter, Ollama/vLLM, or a LiteLLM proxy. Just set PENTESTCODE_MODEL.
Workflows Scripted multi-step engagements (/workflow recon) defined in YAML.
Sub-agents The Task tool spawns autonomous sub-agents that can recurse and fan out, sharing the sandbox + state.
Sandbox memory A persistent sandbox_state.json records OS, installed tools/libraries, wordlists, engagement facts and findings — so the model never starts from zero.

Requirements

  • Docker installed and running (the only execution backend).
  • Python 3.9+ on the host to run the CLI.
  • An API key for whichever model provider you choose.

Install

pip install pentestcode

That's it — you do not need to clone the repo or run docker build yourself. The sandbox image (Kali + common pentest tools) is defined by a Dockerfile bundled inside the package, and Pentest Code builds it automatically on first run. First launch takes a few minutes while the image builds.

Prefer to build it ahead of time, or inspect/customise the Dockerfile?

pentestcode build-sandbox           # build + start the sandbox now, then exit
pentestcode --print-dockerfile      # print the bundled Dockerfile
pentestcode --print-dockerfile > Dockerfile && docker build -t pentest-code-sandbox:latest .

From a clone (for development) the root Dockerfile is used automatically:

git clone https://github.com/Arpitpm23/pentestcode && cd pentestcode
pip install -e .

Set at minimum a model and its key (LiteLLM reads keys from the environment):

export PENTESTCODE_MODEL=anthropic/claude-sonnet-4-20250514
export ANTHROPIC_API_KEY=sk-ant-...
# …or OpenAI:
export PENTESTCODE_MODEL=openai/gpt-4o
export OPENAI_API_KEY=sk-...
# …or a local Ollama model (OpenAI-compatible):
export PENTESTCODE_MODEL=openai/llama3.1
export OPENAI_API_BASE=http://localhost:11434/v1
export OPENAI_API_KEY=ollama

Run

pentestcode          # or: python -m pentestcode  (aliases: ptc, pentest-code)

On first launch it will build/start the sandbox container and probe it once for installed tools (cached in the state file). Then you get the prompt.


Modes

  • manual (default): every Bash command, Write, and Edit shows an inline approval box — Yes / Yes, don't ask again for <tool> / No, tell it what to do instead. Reads and searches never prompt.
  • auto: tools execute immediately with no prompts.

Switch anytime with shift+tab, or /auto / /manual / /mode.

Commands

/help                 show help
/status               model, mode, sandbox and state summary
/mode [manual|auto]   show or set the mode
/auto  /manual        switch mode
/model <name>         switch model (LiteLLM format)
/state [refresh]      show persistent sandbox state (refresh re-probes)
/sandbox [restart]    sandbox status / recreate container
/workflows            list workflows
/workflow <name>      run a workflow (prompts for inputs)
/clear                fresh conversation (keeps sandbox + state)
/exit                 quit (container keeps running)

Workflows

Built-ins live in pentestcode/workflows/; drop your own YAML into .pentestcode/workflows/ and they show up automatically.

/workflows
/workflow recon         # asks for: scope  (e.g. 10.0.0.0/24)
/workflow web-audit     # asks for: url

A workflow is an ordered list of steps; each step feeds a prompt to the agent (steps share context, or set isolated: true to run as a dedicated sub-agent).

name: recon
description: External recon of a target scope.
inputs: [scope]
steps:
  - name: Host discovery
    prompt: "Discover live hosts in {scope}; save to loot/hosts.txt."
  - name: Port scan (parallel)
    isolated: false
    prompt: "Scan each host; delegate one 'recon' sub-agent per host via Task."

Sub-agents

The model can call the Task tool to delegate focused work to an autonomous sub-agent (e.g. one per host/service). Sub-agents:

  • run their own tool loop with a specialised prompt (recon / web / exploit / post / general),
  • share the same sandbox and the same sandbox_state.json,
  • can spawn their own sub-agents up to max_subagent_depth (default 3),
  • return only a final report to the parent (keeping context lean).

Limits live in .pentestcode/config.json (max_subagents, max_subagent_depth).

The sandbox-state file (memory)

./.pentestcode/sandbox_state.json is the agent's long-term memory of the sandbox. It stores:

  • OS + kernel, and a per-tool inventory (present/missing, path),
  • installed Python libraries and available wordlists,
  • engagement scope/targets/creds and durable findings + notes.

It is injected (compactly) at the top of every session, so the model doesn't re-check what it already knows. The model curates it with the UpdateState tool; you can view it with /state and force a re-probe with /state refresh. A full re-probe only happens automatically when the sandbox image changes.


Architecture

pentestcode/
├── cli.py            REPL: bootstrap sandbox, slash commands, prompt loop
├── agent.py          agent loop: stream → tool-calls → observe; sub-agent spawn
├── llm.py            LiteLLM client (streaming + tool-call reconstruction)
├── sandbox.py        Docker-only executor (exec, cwd persistence, file I/O)
├── state.py          persistent sandbox state + one-shot probe
├── prompts.py        system prompts (main + sub-agent specialisations)
├── workflow.py       YAML workflow engine
├── config.py         modes / model / sandbox settings (env + JSON)
├── tools/            Bash, Read, Write, Edit, Grep, Glob, TodoWrite,
│                     UpdateState, Task
├── ui/               theme + console (banner, tool render, spinner,
│                     approval menu, bordered input) — the Claude Code look
└── workflows/        built-in recon.yaml, web-audit.yaml

Flow: cli starts the Docker sandbox and probes it → Agent sends the conversation + tool schemas to the model via llm → tool calls are gated by the mode (manual approval) and executed in the sandbox → results feed back into the loop → durable knowledge is saved to the state file.

Extending

  • New tool: subclass Tool in pentestcode/tools/, set name, description, parameters (JSON schema), requires_approval, implement run(args, ctx), and register it in tools/__init__.py.
  • New workflow: add a YAML file to .pentestcode/workflows/.

Notes & limits

  • Multiple Task calls in one turn run sequentially (readable terminal output), but there is no low cap — a parent can fan out up to max_subagents.
  • The sandbox mounts ./loot → /root/engagement so scan output/loot persists.
  • SYN scans etc. need raw sockets — the container is started with NET_RAW/NET_ADMIN (configurable in config.py).

License

MIT — see LICENSE.

Metadata

Release files for pentestcode 1.0.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pentestcode 1.0.3
File Size Uploaded Provenance Actions
pentestcode-1.0.3.tar.gz 43.7 kB Without provenance Details for pentestcode-1.0.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pentestcode 1.0.3
File Interpreter ABI Platform Actions
pentestcode-1.0.3-py3-none-any.whl Python 3 none any Details for pentestcode-1.0.3-py3-none-any.whl

Total release size: 90.9 kB

Release files / pentestcode-1.0.3.tar.gz

Download URL pentestcode-1.0.3.tar.gz
Size 43.7 kB
Tags Source
SHA-256 checksum
How to use checksums
1ff83a7cb34748338bb38f40c9fdb8f24709121ba1c4f5dbf66d2145e6aaa7b4
BLAKE2b-256 checksum
How to use checksums
65a10a9cc50c61fa23ee96fd7821c469eff081e00b7a0190405d20c66327c100
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release files / pentestcode-1.0.3-py3-none-any.whl

Download URL pentestcode-1.0.3-py3-none-any.whl
Size 47.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
95144a45d467e4f597c31bc7964fd2ff24c5053d308f8b519032e2c8cc7676cb
BLAKE2b-256 checksum
How to use checksums
49b05ebe58b0ef87b47c93f92a3011532378634732eff1b547f7c4efc540e23f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Security for pentestcode 1.0.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page