Pick a way to install.
All four give you the same pwner binary. Nothing phones home, and nothing leaves your machine until you point it at a model endpoint.
curl -fsSL https://pwner.example/install | sh
Examples, not live. The install URL, module path and registry are placeholders.
- PlatformsLinux (amd64, arm64) is the primary target. macOS and Windows build from the same source. The Docker image is Linux only.
- Check the installRun
pwner version, thenpwner doctor. Doctor checks your config, your model endpoint if you set one, and that audit logging can write. - Verify the downloadRelease checksums and signatures are planned. Until the repository is public, treat every URL here as a stand-in.
- Network useNone at install time beyond the download itself. No telemetry, no update pings.
From install to your first report.
Five steps against a lab range. Every address below is fictional. Swap in a network you own or have written permission to test.
Create an engagement
This writes a starter
scope.yamlandplaybook.yamlinto a new folder. The starter scope allows nothing, so nothing can run until you fill it in.pwner init acme-demoWrite the scope, then check it
Open
scope.yaml, add your allowed ranges and the hosts to leave alone, and set the time window. The format is below. The check prints what the scope engine will allow and refuse.pwner scope check scope.yamlDry run the playbook
A dry run prints every action the playbook would take and sends nothing. Read it once before the first live run.
pwner run playbook.yaml --dry-run~/engagements/acme-demosample output, fictional lab$ pwner run playbook.yaml --dry-run scope acme-demo-internal, window open scope allow 10.0.0.0/24, corp.acme-demo.example scope deny 10.0.0.1, 10.0.0.13 plan 6 steps, approval before each would discover 10.0.0.0/24, 252 addresses would enumerate, passive first refuse 10.0.0.13 is on the deny list, never touched audit dry run logged, 0 packets sentsample data, fictional lab. Output format is illustrative.Run it with approvals on
The default autonomy level asks before every action. Say yes or no at each prompt. Everything you approve or refuse goes to the audit log.
pwner run playbook.yamlWrite the report
Turn the run into a Markdown report or SARIF for your tracker. Each finding links back to the audit entries that support it.
pwner report --format md
Want the agent to choose steps for you? See how the agent loop works and the three autonomy levels before you raise the setting.
Two files control every run.
A scope file says what you may touch. A playbook says what to do with it. Both are plain YAML and both belong in version control.
engagement: acme-demo-internal roe_ref: LAB-0042 window: start: 2026-10-06T09:00Z end: 2026-10-13T17:00Z allow: - 10.0.0.0/24 - corp.acme-demo.example deny: - 10.0.0.1 # gateway, not ours - 10.0.0.13 # dc02, not ours limits: rate_pps: 50 active_checks: read-only audit: ./pwner-audit.jsonl
allow / denyAnything not inallowis refused. Deny wins when both match.windowOutside the start and end, every action is refused.roe_refYour rules-of-engagement reference, copied into every audit entry.limitsPacket rate cap and the class of checks allowed.
name: internal-baseline scope: ./scope.yaml autonomy: approve-each-step steps: - run: discover - run: enumerate with: { mode: passive-first } - run: hygiene with: { checks: [identity, ad] } - run: paths with: { to: "Domain Admins" } - run: validate with: { top: 3, safe: true } - run: report with: { format: [sarif, md] }
scopeRequired. A playbook without a scope file will not start.autonomysuggest, approve-each-step or autonomous-within-scope.stepsRun in order. Each step is a module name with options, and each action is still checked against the scope.validate.safeKeeps validation read-only.
Browse what each step does on the modules page. For how the scope engine enforces the file, see architecture.
Command reference.
Every command reads the scope file and logs to the audit file. Run pwner help <command> for details.
| Command | What it does | Common flags |
|---|---|---|
| pwner init [dir] | Create a starter engagement folder with an empty scope and a sample playbook. | --template |
| pwner scope check | Load a scope file and print what it allows, denies and when the window closes. | --target, --at |
| pwner run <playbook> | Run playbook steps in order, asking for approval at the level you set. | --dry-run, --autonomy |
| pwner agent run <playbook> | Let the planner choose next steps inside the playbook's step and token budget. | --budget, --planner |
| pwner discover | Find live hosts and services inside the allowed ranges. | --rate, --passive |
| pwner paths | Build the graph and rank routes to a target such as a privileged group. | --to, --max-hops |
| pwner validate | Re-check the top routes with read-only tests. | --top, --safe |
| pwner report | Write findings from a finished run. | --format md|sarif|json |
| pwner audit show | Print the audit log, one entry per decision, refusals included. | --refused, --since |
| pwner audit verify | Check that the audit log has not been edited since it was written. | --file |
| pwner doctor | Check config, model endpoint and audit write access. | --offline |
| pwner version | Print the version and build info. | --json |
placeholder Command and flag names are illustrative until the first tagged release.
Config reference.
Defaults are cautious. Settings live in ~/.config/pwner/config.yaml (placeholder path) and any of them can be overridden in a playbook or with a flag.
- autonomy
- How much the agent does without asking. The playbook can set it per run.
- default: approve-each-step
- planner
- Which planner picks steps. deterministic ranks routes by hop count and works offline. model uses your endpoint.
- default: deterministic
- model.endpoint
- URL of a local or hosted model you control. Leave empty and nothing is sent anywhere.
- default: unset
- budget.max_steps
- Stop the agent after this many actions in one run.
- default: 40
- budget.max_tokens
- Stop the agent when model usage reaches this total.
- default: 200000
- limits.rate_pps
- Packets per second cap. A scope file can lower this value but never raise it above the default.
- default: 100
- audit.path
- Where the append-only audit log is written. Every action and refusal is recorded.
- default: ./pwner-audit.jsonl
- audit.sign
- Chain entries with hashes so
pwner audit verifycan detect edits. - default: true
- report.formats
- Formats written at the end of a run.
- default: [md]
placeholder Keys and defaults are examples for a pre-release build.
Common questions.
Use and safety
What license is it?
Apache-2.0 is a placeholder until the repository is public. It permits commercial use, forks and bundling. See the license section.
Is it safe to run?
Only with written authorization. A scope file is required, anything not allowed is denied, the agent asks before each step, validation is read-only and rates are limited. It is still a network testing tool, so try it on a lab range first.
Can the agent go out of scope?
Not through the model. The scope engine sits in the core, outside the model and every module, checks each action before it runs, and refuses and logs anything not allowed, whatever the planner or a prompt says. Writing a scope file that covers a network you do not own is still on you.
Does it need an LLM?
No. Bring a local or hosted model, or use the deterministic planner, which works offline. Nothing is sent anywhere until you configure a model endpoint.
How it works
What makes it agentic?
pwner runs a loop. It observes the graph, plans next steps, acts through allowed tools, validates read-only and reports, then feeds new findings back in, within a step and token budget and with every decision logged. The agent page walks through it.
Which platforms are supported?
Linux (amd64, arm64) is the primary target, macOS and Windows build as static binaries, and the Docker image is Linux only.
Compared with other tools
How is it different from Metasploit?
Metasploit is an exploitation framework, while pwner ships no exploits and instead maps attack paths, validates them read-only and writes the report.
How is it different from Sliver?
Sliver is a command-and-control framework for post-exploitation, while pwner has no implants and stops at discovery and path analysis.
How is it different from BloodHound?
BloodHound graphs Active Directory relationships, while pwner does its own network discovery and builds one graph across hosts and identities, with a Neo4j export planned for people who want BloodHound's UI.