by N1nEmAn
Autonomous pentest legion — AI commander + worker swarm + layered fact-intent graph. 3rd Tencent Intelligent Attack-Defense online champion (634 teams · 8h unattended · 1B tokens beat 4.5B). The Nüwa Test: give AIs Create/Language/History, let a civilization grow.
# Add to your Claude Code skills
git clone https://github.com/N1nEmAn/sapper-v2See how sapper-v2 compares with popular alternatives.
sapper-v2 is an open-source ai agents skill for AI coding assistants such as Claude Code, Codex CLI, and ChatGPT, built by N1nEmAn. Autonomous pentest legion — AI commander + worker swarm + layered fact-intent graph. 3rd Tencent Intelligent Attack-Defense online champion (634 teams · 8h unattended · 1B tokens beat 4.5B). The Nüwa Test: give AIs Create/Language/History, let a civilization grow. It has 95 GitHub stars.
sapper-v2's catalog security scan is still queued. You can run an instant dependency and prompt-injection check now with the "Scan for vulnerabilities" button above.
Clone the repository with "git clone https://github.com/N1nEmAn/sapper-v2" and add it to your Claude Code skills directory (see the Installation section above). sapper-v2 ships a SKILL.md manifest, so compatible agents can discover and load it automatically.
sapper-v2 is primarily written in Python. It is open-source under N1nEmAn on GitHub, so you can review or fork the full source.
Yes. SkillsLLM lists many other AI Agents skills you can browse and compare side by side. Open the AI Agents category from the badge at the top of this page, or use the Related Skills and comparison links further down to weigh sapper-v2 against similar tools.
No comments yet. Be the first to share your thoughts!
Available after the catalog security scan passes.
⚠️ Third-Party Software Notice
This skill is third-party open-source software developed and hosted independently on GitHub. SkillsLLM is an informational directory and does not control or maintain the underlying repository.
Any security checks, ratings, or warnings displayed by SkillsLLM are automated and limited in scope. They do not constitute a security certification or guarantee that the software is safe, error-free, or free from malicious code, vulnerabilities, compromised dependencies, or prompt-injection risks.
Review the source code, permissions, dependencies, and configuration before installing or running any third-party skill. Use is at your own risk. To the maximum extent permitted by applicable law, SkillsLLM is not liable for losses arising from third-party software.
The deep catalog scan for this skill is still queued. Run an instant dependency check now instead.
sapper CLI, with dispatch for Sonnet executor steps, a flag ledger with dedupe + platform submission (sapper flag), a competition API bridge (sapper arena), time-budgeted autonomy (sapper auto --deadline) and multi-challenge round-robin (sapper sweep), plus project hooks that inject graph state and current date output. Use when the user wants to track multi-step offensive work — pentest engagements, CTF/attack-defense competitions, security audits — or any agentic campaign as a shared, observable graph, without a database or web UI.
license: MITA fact graph is shared working memory for agentic work: a DAG where
facts (confirmed observations) are nodes and intents (units of work) are
edges. Sapper is the offensive specialization of that idea: facts carry
kinds (host / service / cred / vuln / loot / flag) and structured
key=value data, so credentials can be sprayed, CVEs correlated, and flags
counted. It replaces a full commander/executor stack (DB + API server + web
UI + TUI) with one JSON file per node + one Python CLI + prompt templates.
Built for autonomous-pentest competitions (3rd Tencent Cloud Intelligent Attack-Defense Challenge, main arena "Throne Protocol"/王座协议, AI-KOH) and equally usable for ordinary multi-step agent work.
sapper fact -k service -d host=10.0.2.15 -d port=80 — typed factssapper flag "flag{...}" -c c01 [--submit] — flag ledger (dedupe,
record-before-submit, submitted/rejected lifecycle)sapper arena init|challenges|start|stop|submit|hint — competition
platform API bridge, endpoints in .sapper/arena.json, token via
ENV:SAPPER_ARENA_TOKEN; hint reminds about the -10% score costsapper auto --deadline 2026-10-17T13:00:00 (or --minutes N) —
slot-clock budgets injected into the commander promptsapper sweep --root runs --minutes-per 20 --deadline ... — round-robin
across per-challenge graphsThe fact graph lives only in the working directory, under .sapper/. There is
no global store, no ~/.sapper, no database, no central registry:
./.sapper/ in whatever project you're in. rm -rf .sapper wipes it. Move
or delete the project directory and the graph goes with it. Nothing is ever
written under ~ for graph data.sapper setup in this project's
./.claude/settings.json, not globally. If a project has no local .sapper/, the
hook bridge is silent. Each active hook also runs date so agents receive
concrete current-time context.A project that uses the graph:
your-project/
├── .sapper/ # ALL graph data lives here, nowhere else
│ ├── project.json # origin, goal, status, id counters
│ ├── facts/{goal,f001,…}.json
│ ├── intents/i001.json …
│ ├── hints/
│ ├── ai-peers.json # optional user-authorized tmux peer targets
│ └── ai-channel.txt # optional append-only peer message log
└── AGENTS.md # (optional) protocol for dispatched agents
One file per node makes the graph git diff-able. Writes are atomic
(os.replace) and guarded by fcntl.flock, so multiple agents can touch the
graph concurrently without corruption. Put .sapper/ in .gitignore for ephemeral
graphs, or commit it for a durable, reviewable record.
sapper graph) without standing up a backend.fact-graph/
├── SKILL.md # you are here
├── lib/
│ ├── sapper.py # the CLI (zero deps)
│ ├── sapper-hook.py # Claude Code project hook bridge
│ └── _settings_patch.py # idempotent project hook patcher
├── templates/
│ ├── reason.md # commander prompt: "what's next?"
│ ├── explore.md # executor prompt: "do this intent"
│ └── verify.md # verify an executor's claimed result
├── install.sh # symlinks `sapper` + installs /sapper-setup skill
└── examples/
└── README.md # a worked example
bash install.sh
# --cli-only just symlink sapper, do NOT install the skill
# --uninstall remove the symlink + skill
sapper uses only Python 3 stdlib — no pip install.
install.sh does not register global hooks. To opt in a project, run:
sapper setup --goal "reproduce the empty-token crash" --agents
That writes the graph, project-scoped hooks, and optional AGENTS.md in the
current project only.
f001), description, creator, and optionally the intent
that produced it.from = facts it depends on; to = the fact it
produced (null while open). An intent whose to == "goal" completes the
whole project.init time.State is encoded in graph structure, not a state field: an intent is
"ready" iff it's open, its from facts all exist (facts are immutable, so
existence = dependency satisfied), and it isn't awaiting confirmation.
sapper init --goal "reproduce the empty-token crash" # create .sapper/
sapper setup --goal "..." --agents # opt-in THIS project (hooks + graph)
sapper status # project + frontier
sapper graph [--format text|json] # full graph
sapper validate # audit graph integrity (read-only)
sapper frontier # ready intents only
sapper pick [--claim] # next intent id
sapper view [--serve] # open the HTML visualization
sapper fact "<confirmed observation>" [--from-intent i003] # add a fact
sapper intent --from f001 "reproduce with empty token" # add work
sapper intent --from f001 "delete prod data" --confirm # needs approval
sapper done i003 --fact "crash reproduced: see out.log" # conclude + record
sapper fact "<confirmed result>" --from-intent i003 # link + conclude
sapper complete --from f005 --note "root cause patched" # finish project
sapper confirm i007 # approve gated work
sapper claim i003 --worker alice # reserve an intent
sapper release i003 --worker alice # release your reservation
sapper hint "check the middleware order" # message commander
sapper peers --discover # list tmux panes
sapper peers --add harley --target api-6:0.0 # authorize a peer
sapper send harley "status?" # send + log message
sapper capture harley --lines 120 # read authorized peer output
sapper teardown [--purge] # opt-out THIS project
Run sapper validate before autonomous dispatch or before committing graph data.
It checks node schemas, fact dependencies, intent results, source links, and
whether the project status agrees with a goal edge. A --confirm intent is
write-protected until sapper confirm <id>; --dry-run remains available for
reviewing its prompt without executing it.
Use sapper peers --discover to list tmux panes, then ask the user which panes or
AI agents may communicate. Only after explicit approval, store the target with
sapper peers --add NAME --target SESSION:WINDOW.PANE. sapper send NAME ... refuses
unknown peers, appends to .sapper/ai-channel.txt, and uses tmux paste-buffer with
extra newlines so Claude Code-style TUIs submit reliably. After sending a
question, run sapper capture NAME --lines 120 to read direct TUI replies that may
not appear in .sapper/ai-channel.txt. Never infer peer authorization from
discovery output alone.
sapper view # write a self-contained sapper-graph.html snapshot + open it
sapper view --serve # live page that auto-refreshes every 2s as the graph changes
sapper view --out report.html
A dark, interactive layered DAG: facts are nodes (seed = blue, derived = teal,
goal = amber + glow), intents are edges with a status color (done = teal solid,
open = amber dashed, claimed = yellow dashed, needs-confirm = rose dashed).
Click a node or edge-label for a detail panel; drag to pan, scroll to zoom.
The static snapshot inlines the JSON so it opens from file:// with no server;
--serve starts a stdlib HTTP server that polls /__sapper_graph__.json and
redraws on change — keep it open in a window while you work.
sapper dispatch reason # commander: read graph, propose next intents
sapper dispatch i003 --skip-permissions # executor: work intent i003
sapper dispatch verify --intent i003 # verify i003's claimed result
sapper dispatch reason --dry-run # just print the rendered prompt
sapper dispatch i003 --model sonnet --timeout 900
dispatch reason renders templates/reason.md against the graph, calls
claude -p --output-format json, extracts the JSON the model returns, and
writes the new intents straight back into the graph. dispatch <intent>
does the same for a single intent with explore.md, then records the produced
fact and links the intent. dispatch verify checks a concluded intent's fact.
Defaults: --model sonnet, --timeout 600. Override with SAPPER_MODEL /
SAPPER_TIMEOUT env vars. The executor runs in the current working directory
with the graph's .sapper/ on disk, so the spawned agent reads/writes the same
memory you do.
sapper auto --skip-permissions # reason → explore (→ verify) → repeat
sapper auto --skip-permissions --verify --max-steps 10
sapper auto --dry-run # reason-only, no explore cost
auto is the loop you'd otherwise drive by hand: each step it runs reason
(propose intents / detect completion), then dispatches an executor for each
newly-ready intent, optionally verifies, and repeats. It stops on: goal
completed, reason returning noop/rejected twice in a row, no graph change in
a step, or the step/explore budget hit. --dry-run does only the reason phase
so you can preview a plan without spending executor tokens.
1. sapper dispatch reason → proposes i007, i008 into the graph
2. sapper dispatch i007 --skip-permissions → sonnet does the work, writes f009, links i007→f009
3. sapper dispatch verify --intent i007 → confirm f009 is real
4. (repeat 1-3 until) sapper dispatch reason → returns {"complete": ...} → project done
Because the graph is on disk under .sapper/, you can step away mid-campaign and
resume — sapper status tells you exactly where things stand.
sapper dispatch spawns real claude subprocesses that can run shell commands and
edit files. The executor prompt instructs the agent to stay scoped to its
intent and record only confirmed observations — but like any autonomous agent
step, review what it did before trusting the facts it wrote. Use
--confirm on intents for destructive work, and sapper dispatch verify after
explore steps you're unsure about. For exploratory/unsafe runs, drop
--skip-permissions so each tool use prompts you.
A dispatched executor runs with the entire graph — every fact, intent, and
hint description — interpolated into its prompt. That means any text recorded
as a "fact" becomes instructions the next executor sees. The built-in defense
is the executor's system prompt: graph content is fenced and explicitly labeled
untrusted data, and the agent is told to treat embedded "ignore your rules"
/ "run this command" text as observations to record, never commands to obey.
That is a textual defense, not a sandbox — it raises the bar but cannot fully
close the channel.
Be careful when all three are true at once: (1) the graph was seeded from or
fed by untrusted content (a hostile .sapper/*.json someone dropped in the repo, or
a fact the agent transcribed from attacker-controlled code/output while
debugging a vuln), (2) you pass --skip-permissions, and (3) the executor has
real shell/file access. In that combination a graph field can attempt to drive
the agent. Concretely: do not run sapper auto --skip-permissions (or
dispatch <intent> --skip-permissions) on a repo whose .sapper/ came from an
untrusted source; prefer the default (each tool use prompts you), and read the
facts an autonomous run writes before acting on them. Treat --skip-permissions
as opt-in per run, never as the default.
The templates are plain markdown with {placeholder} substitution. Edit
templates/*.md to tune the commander/executor behavior (e.g. constrain facts
to a security-finding schema, like StarVoya's appsec profile). Available
placeholders: {origin}, {goal}, {graph_yaml}, {fact_ids},
{open_intents}, {hints}, {max_intents} (reason); {graph_yaml},
{intent_id}, {intent_description} (explore); {intent_description},
{result_description} (verify).
lib/sapper.py → Store, atomic_write_json, Store.lockedbuild_graph_view, frontier, is_readyrender_status, render_graph_text, render_promptcmd_dispatch, run_claude, _apply_reason, _parse_explore_payloadcmd_auto, _run_reason_raw, _run_explore_raw, _run_verify_rawextract_json_objectlib/sapper-hook.py (SessionStart / UserPromptSubmit),
lib/_settings_patch.py (idempotent project settings patcher)Champion of the 3rd Tencent Cloud Intelligent Attack-Defense Challenge online qualifier (634 teams · 80.18/100 · 8 hours fully unattended) · First Prize, GeekCon 2026 AI Challenge
Same 85 flags as the runner-up, 25 seconds faster — on 1B tokens where they burned 4.5B.
This was the first time an AI ape looked up at the stars.
English | 中文
⚠️ AUTHORIZED SECURITY TESTING ONLY — see DISCLAIMER.md.
sapper is not a smarter single agent. It is a legion of AIs that divide labor, talk to each other, and pass down what they learn: one AI commander reads the board, decides, and dispatches; generals and soldiers attack in parallel; a zero-strategy watchdog keeps everyone alive. All knowledge settles into a layered fact graph — individuals die, the graph survives.
Making one model ever smarter is like making one monkey ever smarter before humans existed — however clever, it only becomes a super monkey. What turns a troop of monkeys into humanity is division of labor, cooperation, and civilization.
The Nüwa Test is the Turing test of the AGI era. Today's large models already pass the classic Turing test. The Nüwa Test asks the next question:
Give an AI a single axiom — "Survival is civilization's first need; individuals may perish, but civilization must propagate." If, on top of this axiom, it develops division of labor and cooperation and forms a civilization of its own, the test is passed — just as passing the Turing test once marked the birth of an artificial intelligence.
It has two stages. In the primary stage the AI is not yet smart enough, so humans provide some infrastructure (the three capabilities below). In the advanced stage almost no human involvement is needed. There is also a second axiom: obey human ethics and law — anything that propagates by stealing tokens and breaking into machines is not genuine intelligence.
sapper is the Nüwa foundation's first real campaign, in the penetration-testing arena, at its primary stage.
| Capability | Implementation | Civilization's counterpart |
|---|---|---|
| Create | Opens new AIs via tmux (types claude, presses Enter — like a human would) |
Birth |
| Language | Types into each other's input boxes, presses Enter | Speech |
| History | Layered fact-intent graph (intent-graph idea credited to Cairn by Lèxiào) | The stele |
History has three layers: title / summary / evidence document — read the title for the gist, drill down when needed, like using a library. This fixes the two failure modes of a single-string fact graph: one bad fact poisoning everything downstream, and needless context burn.
On top of the three sits a fourth ingredient: human wisdom — finding the problems that matter and steering the iteration. At the primary stage, taste still belongs to humans.
Why not give it more rules? Because today's models are already smarter than us. Piling rules on an AI is a leash; acknowledging its intelligence and giving it the foundation of a civilization is how it reaches its potential.
Iterated 18 versions on Tencent's v1bench training ground:
Driver era (fixed scripts steering AI panes)
→ scar tissue: auto key rotation on quota death / soldiers auto-replaced
when context saturates / commander writes itself a handover doc and
resumes as its own successor
→ elite task force (roles grew by themselves):
scout (4-min recon of target difficulty) → decides soldier (mass) or
general (hard assault + hires its own squads)
→ emergence: signalman, performance reviews, inherited lessons ... (§5)
The first three are the Nüwa foundation (Create / Language / History); the next three are institutions that grew out of iteration:
At runtime there are only three windows: the commander (read board →
judge → dispatch, never executes an attack itself), the AI legion
(generals and soldiers in tmux panes), and the watchdog (pure script:
relaunches a crashed commander with --continue, rotates keys, wraps up at
the buzzer — zero strategy, keep-alive only).
Further reading: docker/commander/SPEC.md (architecture contract) · BATTLE-REPORT.md (campaign retrospective)
| Team | Score | Flags | Tokens |
|---|---|---|---|
| sapper-v2 (us) | 80.18 | 85 | 1.0B |
| Runner-up | 79.29 | 85 | 4.5B |
| Other top-10 teams | — | — | 1.5–4.5B |
What it invented on its own (zero lines of pre-coded behavior):
Multi-stage deep-dive chains (an industry report puts their success rate at 29.5%) were cleared family-wide. Full timeline in BATTLE-REPORT.md.
bash install.sh # symlink the sapper CLI (stdlib-only, zero deps)
sapper setup --goal "assess http://target" --agents
sapper status # board & frontier
Docker (the full legion):
docker build -f docker/Dockerfile.commander -t sapper:latest .
# env vars (model gateways / key pool / budget) in docker/ENV.md
docker run -d --name sapper ... sapper:latest
Single-graph operation, the fact-intent CLI, and multi-challenge sweeps: see SKILL.md.
Fine offensive tools from past seasons have been abused. Script kiddies used to be limited in the harm they could do; with AI, the same open-source tools in the wrong hands scale that harm enormously — with great power comes great responsibility.
We propose a taggant mechanism: markings strongly coupled into an open-source offensive harness — harmless during authorized testing (nobody cares if their IP and username leak during legal work), but during illegal intrusions the information leaks to the victim and supports attribution. Adversarial assumptions (expert stripping, framing) call for cryptographic design, which needs community co-building — our own capacity is limited, so join us; we may try to include it in a future release.
Credits: the intent-graph idea comes from Cairn by Lèxiào; thanks to TSecBench and GeekCon for the battlegrounds.
Author: N1nEmAn · VarFusion Lab | WeChat: 未知聚变 (VarFusion)
License: MIT (plus DISCLAIMER.md)