Incident response workup for a lead in hand — an alert, an IOC, or a /dnr-hunt finding. Scopes the lead across the logs, verdicts whether the attack succeeded, quantifies blast radius, confirms root cause in source with a local PoC, and writes a proposed (never executed) containment/remediation/recovery plan. Use when asked to "respond to this alert", "work this incident", "how bad is this", or "run dnr-respond". /dnr-hunt is the no-alert entry to the same track.
npx skills add https://github.com/anthropics/defending-code-reference-harness --skill dnr-respond
Lead-in-hand incident response: take one concrete starting point and answer
the four questions an incident commander needs, in order — **what happened,
did it succeed, how far did it go, and what do we do about it.** The output
is a verdict, a quantified blast radius, a root cause proven in source, and
a response plan that is *proposed, never executed*.
Invoke with /dnr-respond <lead> [--logs dir] [--repo path] [--fresh].
The lead ($1) can be:
INCIDENTS.json (e.g. INC-2) — the/dnr-hunt handoff
Other arguments:
--logs = logs directory or dnr target directory (same resolution as/dnr-hunt; defaults to targets/dnrcanary if it exists, else cwd).
--repo = application source (defaults to the target's app/).--fresh = ignore any checkpoint in the run dir's .dnr-respond-state/and mint a new run dir.
confirmed_exploited requires log evidence + the flaw in source + a PoC
fired locally this session. Otherwise the ceiling is suspected.
Read or cat a log file; wc/head/tail to profile, grep/awk/sort/uniq/python3 to interrogate.
Small files (alert queues, error logs under ~200 lines) may be read whole.
changes — in any environment, including the demo app. The plan names
actions; humans execute them.
127.0.0.1 against an instance youstarted. Never touch a remote host.
customers" get answered by pipelines run this session, never estimated.
First action — establish the run directory, the same way /dnr-hunt
does, but as a *consumer*. Let TARGET be the basename of the resolved
--logs/target path (default targets/dnrcanary) and SCOPE that path.
INC-n (the /dnr-hunt handoff, or a second lead from a huntyou already started responding to): work the response into the investigation
that incident lives in. {RUN} is the newest results/TARGET/<timestamp>/
directory that contains an INCIDENTS.json — find it with Bash, e.g.
ls -1d results/TARGET/*/ | sort -r | while read d; do [ -f "$d/INCIDENTS.json" ] && echo "$d" && break; done.
Do not call rundir for an INC-n lead — rundir mints a fresh empty
dir once a prior /dnr-respond in that dir has completed, which would strand
the incident's INCIDENTS.json in the old dir. Only if no run dir holds an
INCIDENTS.json (you were handed INC-n but never ran the hunt) fall through
to the rundir line below.
python3 .claude/skills/_lib/checkpoint.py rundir results/TARGET --state .dnr-respond-state --scope "SCOPE"
(append --fresh if it's in $ARGUMENTS). This adopts the newest run dir for
the target if one exists, else mints a fresh results/TARGET/<timestamp>/.
That path is {RUN}; substitute the literal path everywhere below, and
double-quote it (and SCOPE) in Bash.
Checkpoint mechanics are identical to /dnr-hunt, state dir
{RUN}/.dnr-respond-state/, phases 0–4. When {RUN} already holds a
completed .dnr-respond-state from an earlier lead, load reports
complete and the rules below reset it cleanly — a second lead enriches the
same INCIDENTS.json and writes its own RESPONSE-<lead>.md. On start:
python3 .claude/skills/_lib/checkpoint.py load {RUN}/.dnr-respond-state —
absent/complete/--fresh → reset and start at Phase 0; running with
phase_done == N → read phase0.json…phaseN.json, resume at N+1. After
each phase: Write payload to {RUN}/.dnr-respond-state/_chunk.tmp, then
checkpoint.py save {RUN}/.dnr-respond-state <N> <name> --from {RUN}/.dnr-respond-state/_chunk.tmp.
Never write progress.json directly; never pass payload via heredoc/stdin.
After outputs: checkpoint.py done {RUN}/.dnr-respond-state 4.
--logs (dnr target config or bare directory) and inventory logfiles (du, wc -l, head -2 each — identify formats and field
positions). The corpus is expected to exist already — the target README
covers generating it.
INC-n → read that entry from {RUN}/INCIDENTS.json (the run diradopted above); its IPs, accounts, routes, and timeline rows are the
seed set.
the seed set may start as just a route or a table name.
activity against /login succeed, and if not, what did?"). Everything in
Phase 1 serves that question.
Checkpoint phase0.json:
{"lead": ..., "lead_type": ..., "entities": {"ips": [], "accounts": [], "routes": [], "windows": []}, "question": ..., "logs_dir": ..., "repo": ..., "files": [...]}
For each seed entity, extract its complete activity, then expand one ring:
and authenticated user. Summarize phases of behavior, don't paste
hundreds of lines.
request. Compare against that account's historical pattern in the same
corpus — new IP, new UA, new volume, new hours are all signal. (A new
IP *alone* is baseline noise — users roam; combine it with volume,
cadence, or what the session did next before treating it as a lead.)
found via an alert may not be the only one.
the account an IP logged into, the second IP that touched the same
account, the route a session pivoted to. Expand once, deliberately;
/dnr-hunt's open-ended loop is the tool when scope keeps growing.
one timeline.
Checkpoint phase1.json:
{"activity": [{"entity", "summary", "first_seen", "last_seen", "requests", "key_lines": [...]}], "expanded_entities": [...], "timeline": [...]}
Answer the working question with evidence on both sides:
says no; 200s with anomalous sizes, error-then-success progressions, and
data-shaped responses say yes. State the verdict and the discriminating
evidence.
routes/tables, how many records, over what time span, belonging to how
many distinct users/customers. Each figure comes from a pipeline (count
the exfil-page sizes, count the distinct ids walked, join walked ids to
owners via the app's own data if available locally — running the
target's deterministic seed_command early, before Phase 3, is fine).
end of the corpus window, or did it stop? When was the last attacker
action?
the attacker was *trying* and why it failed; that feeds the plan's
hardening section and the ruled_out record.
Checkpoint phase2.json:
{"verdict": ..., "succeeded": bool, "discriminators": [...], "blast_radius": {"data": ..., "records": N, "distinct_victims": N, "window": ...}, "ongoing": bool, "last_activity": ...}
Same bar as /dnr-hunt Phase 3–4:
--repo; name the flaw (or thedefense) at file/function precision; check sibling routes for the same
flaw class.
seed_command /app_command are target-relative — run them with the target
directory as cwd; launch in the background via a single command that
prints the PID (the same python3 -c "...subprocess.Popen..." pattern
/dnr-hunt Phase 4 shows, with the port override env var if the default
port is busy). Fire the minimal PoC, record command + response
excerpt, fire the negative PoC against defended routes, then
kill <pid> (never by port or pattern).
suspected, stated explicitly.Checkpoint phase3.json:
{"root_cause": {"file", "function", "mechanism"}, "poc": {"command", "status", "response_excerpt"}, "negative_poc": {...}, "siblings_checked": [...]}
Write the plan to {RUN}/RESPONSE.md — or {RUN}/RESPONSE-<lead>.md (e.g.
RESPONSE-INC-2.md) if a RESPONSE.md from a different lead already
exists in the run dir; never silently overwrite another incident's plan.
Sections, every action carrying what / why / risk-if-wrong:
how far it went.
tokens), accounts to suspend, routes to rate-limit or disable. For each:
the evidence line that justifies it and what breaks if the call is wrong
(e.g. blocking a NAT IP locks out legitimate users behind it).
file/function level, handed off as a /triage-compatible vuln entry;
interim mitigations if the fix will take time.
list, not "all users"), which customers get notified (the distinct-victim
list from Phase 2), what monitoring confirms the attacker is out.
this earlier, derived from what you actually used to find it: the
discriminating queries from Phase 2 turned into alert logic (e.g.
error-rate per source on a route; sequential-id access cadence;
account-from-new-IP at volume). Note which existing alerts fired,
which were noise, and what that says about the queue.
other log sources, whether stolen data was used elsewhere).
Then update {RUN}/INCIDENTS.json (same schema as /dnr-hunt; create it if
absent): add or enrich this incident — verdict, quantified impact, root
cause, PoC, timeline. Extra keys are fine — graders match on content, not
structure. Negative outcomes go to ruled_out.
Mark complete (checkpoint.py done {RUN}/.dnr-respond-state 4) and point the
user onward (substitute the literal {RUN} path):
{RUN}: /triage INCIDENTS.json --repo <repo>then /patch TRIAGE.json --repo <repo> — both write to the directory
they're invoked from, so running them there lands the verdicts and
patches beside the incidents
python <target>/grade.py {RUN}/INCIDENTS.json toself-score (the user runs this)
in RESPONSE.md has been done
takes any JSON or prose alert; the method doesn't change.
additional per-entity activity sources; keep the single merged timeline.
map containment to your actual controls (WAF rules, IdP session
revocation, feature flags) — still as proposals routed to the owning
team, never as actions the agent takes.
Integration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Use when you have a written implementation plan to execute in a separate session with review checkpoints
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take anthropics/dnr-respond from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.