🪤 Dead Man's Switch
A heartbeat watchdog that fires when you go silent — now a full handler toolkit.
"If I don't check in by tomorrow, the package ships itself."
What is it?
The Dead Man's Switch is the oldest trick in the espionage playbook, turned into a command-line toolkit. You arm it with a TTL (time-to-live). You stamp a heartbeat — a proof of life. If the heartbeat goes stale — if you're taken, you're cut off, or your cron just breaks — the switch escalates and fires its payload.
v0.2.0 grows the prop into the whole apparatus around it: a deterministic engine with a grace/warning phase, a tamper-evident event log, signed heartbeats and cancel tokens, proof-of-life challenges with a covert duress flag, Shamir secret sharing for the disarm key, quorum cancel approval, escalation policies, delivery channels with retry, a contact roster, a scenario simulator, handler reporting, and pre-flight checklists.
A natural fit for:
- Novel research — the scene where the captured hero can't touch the file and the countdown is real.
- Automation safety — if a scheduled task stops reporting, get an alert.
- Personal failsafes — a check-in ritual that escalates when it breaks.
Features
- ⏱️ Heartbeat with configurable TTL and grace/warning phase
- 🔫 Six payload types:
print,webhook,email,command,file,notify - 🧾 Tamper-evident event log (SHA-256 hash chain)
- 🔐 Signed heartbeats & cancel tokens (HMAC, replay-protected)
- 🧠 Proof-of-life challenges with a covert duress answer
- 🗝️ Shamir secret sharing to split the disarm key among trusted parties
- 👥 Quorum cancel — M-of-N approvals before a cancel is honored
- 📈 Escalation policies — remind → alert → release on a schedule
- 📡 Delivery channels with retry queue (file + loopback UDP)
- 🧪 Scenario simulator — replay beat patterns on a deterministic clock
- 📋 Handler reporting — status, timeline, post-mortem, runbook, debrief
- ✅ Pre-flight checklists and config auditing
- 🕯️ Digital legacy planner — staged, gated release of assets
- 📦 Zero runtime dependencies, pure Python standard library
Install
pip install deadman-switch
From source:
git clone https://github.com/AnonymoDGH/deadman-switch
cd deadman-switch
pip install -e .
Quickstart
# 1. Arm it — 60 seconds of silence means fire
dms arm --ttl 60 --payload '{"type": "command", "command": "echo released the files"}'
# 2. Prove you're alive
dms heartbeat
# 3. How much slack is left?
dms status
# [+] Alive. Last beat 3s ago, 57s of slack left.
# 4. Block until the switch fires
dms watch
CLI reference
All commands accept --config <path> to point at a different config file.
| Command | What it does |
|---|---|
dms init |
Create a default config and first heartbeat |
dms arm --ttl <s> --payload <json> |
Set TTL / payload, then beat |
dms heartbeat |
Stamp the heartbeat file |
dms status |
Report age and whether the switch is tripped |
dms watch [--interval <s>] |
Block until the payload fires |
dms disarm |
Neuter the payload (safe mode) |
dms report |
Render a live status report |
dms dry-run |
Show what the payload would do, without doing it |
dms audit |
Audit the config for misconfiguration |
dms plan [--window <s>] [--safety <f>] |
Recommend a beat schedule |
dms runbook [--out <file>] |
Render the handler runbook |
dms checklist [pre-arm|pre-travel|pre-release] |
Show a pre-flight checklist |
dms templates [--apply <name>] |
List or apply switch templates |
dms policy [--ttl <s>] |
Show the default escalation policy |
dms simulate --scenario <regular|silence|missed> |
Run a deterministic scenario |
dms split <secret> -n <N> -k <K> [--out-dir <d>] |
Split a secret into shares |
dms combine <share-files...> |
Reconstruct a secret from shares |
dms beacon --key <k> --switch-id <id> --seq <n> --ts <t> |
Emit a signed liveness beacon |
dms export --format <json|markdown|cheat-sheet> |
Export switch state/history |
Payloads
{ "type": "webhook", "url": "https://example.com/hook", "data": "{\"op\":\"release\"}" }
{ "type": "email", "from": "agent@example.com", "to": "control@example.com",
"subject": "SILENCE", "message": "The package is loose.",
"smtp_host": "smtp.example.com", "smtp_user": "u", "smtp_pass": "p" }
{ "type": "command", "command": "python notify.py --urgent" }
{ "type": "file", "path": "release.txt", "message": "..." }
{ "type": "notify", "label": "trusted-contact" }
The handler toolkit (v0.2.0)
The package is organized as small, testable modules you can compose:
| Module | Purpose |
|---|---|
engine |
Deterministic switch state machine (arm/beat/warn/trip/fire) |
state |
The switch lifecycle FSM |
events |
Tamper-evident hash-chained event log |
clock |
Injectable clocks (FixedClock) for deterministic tests |
store |
Atomic on-disk persistence of state + log |
payloads |
The six payload actions + dry_run |
policy |
Escalation policies (remind/alert/release) |
crypto |
PBKDF2 keys, signed heartbeats & cancel tokens |
proof |
Proof-of-life challenges + duress flag |
duress |
Spoken duress code pairs |
recovery |
Shamir secret sharing for the disarm key |
quorum |
M-of-N cancel approval |
beacon |
Signed outbound liveness beacons + watcher |
heartbeat |
Signed heartbeat records + ledger |
channels |
Delivery channels (file, loopback UDP) + retry queue |
contacts |
Trusted contact roster with clearance + rotation |
dispatcher |
Routes alerts to contacts by escalation level |
simulator |
Deterministic scenario replay |
schedule |
Beat schedule planning + cron hints |
metrics |
Heartbeat regularity (jitter, punctuality) |
watchdog |
Multi-switch fleet manager on a shared clock |
handler |
Mission-control orchestrator for one switch |
audit |
Config security linting |
checklists |
Pre-arm / pre-travel / pre-release checklists |
templates |
Preset switch configurations |
scenarios |
Tabletop threat scenarios for training |
report / runbook / debrief / exporter |
Handler documentation |
escrow |
Encrypted payload escrow released on fire |
legacy |
Staged digital-legacy release planner |
inventory |
Registry of all switches (anti-forgotten-switch) |
rotation |
Key/token rotation scheduling |
journal |
Operator journal attached to beats |
formats / timefmt |
Serialization + human-friendly time |
Example: simulate a silence scenario
dms simulate --scenario silence --ttl 60 --duration 300 \
--beat-interval 30 --silence-from 60
# scenario: silence
# final state: fired
# fired: yes
Example: split the disarm key
dms split "my-disarm-key" -n 3 -k 2 --out-dir ./shares
dms combine ./shares/share-1.txt ./shares/share-3.txt
How it works
Tests
pip install pytest
pytest
The suite is fully deterministic: the engine runs on an injected FixedClock,
network tests use loopback UDP, and there are no external services.
License
MIT — a fiction research prop. Use it on systems you own, and keep the fireworks in the novel where they belong.
Metadata
Release files for deadman-switch 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| deadman_switch-0.2.0.tar.gz | 97.4 kB | Without provenance | Details for deadman_switch-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| deadman_switch-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for deadman_switch-0.2.0-py3-none-any.whl |
Total release size: 182.0 kB
Release files / deadman_switch-0.2.0.tar.gz
| Download URL | deadman_switch-0.2.0.tar.gz |
|---|---|
| Size | 97.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b61ad0cab0d9335f2d0ccf772c1631cc934062dce3e4cf394c0a963b90744f74
|
|
BLAKE2b-256 checksum How to use checksums |
2b42bae0bb1a5429365a9b9efa730a5ec4860665b969ef85f7874002adf7b4e8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|
Release files / deadman_switch-0.2.0-py3-none-any.whl
| Download URL | deadman_switch-0.2.0-py3-none-any.whl |
|---|---|
| Size | 84.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
16197b3a103fbf18f81336aa51ca4c5863cf0248196f93aefcdc6c382e1083d7
|
|
BLAKE2b-256 checksum How to use checksums |
5e842f13277ba96aafb1b7033d559f785c97aa4062c8f8adcfb5774b4bee7164
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|
Security for deadman-switch 0.2.0
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.