A background application that enforces a hard daily computer shutdown with escalating warnings. Named after the show where outies don't get a choice about when work ends. By contrast this severance is designed to promote better work/life balance rather than facilitate inhumane experimentation.
Time blindness and hyperfocus make it genuinely difficult to stop working. A notification you can dismiss isn't a boundary — it's a suggestion. Severance makes the default path "your computer turns off" and forces you to consciously opt out if you need to keep working.
Severance runs as a background daemon starting at login. At T-30 before the configured shutdown time (default 5:00 PM), it begins an escalating countdown:
| Phase | Window | Interval | Tmux Status |
|---|---|---|---|
| Gentle | T-30 to T-15 | Every 5 min | Yellow SHUTDOWN:Xm |
| Aggressive | T-15 to T-5 | Every 2 min | Red blinking SHUTDOWN:Xm |
| Final | T-5 to T-0 | Every 1 min | Red blinking SHUTDOWN:Xm |
| Shutdown | T-0 | Machine powers off | — |
At T-15, Severance checks all tmux panes for activity. Any pane idle for 15+ minutes gets a notification reminding you to leave a breadcrumb note.
On weekends, the machine never shuts down — you get the notification burst instead.
If you're dealing with an incident or genuinely need to keep working, activate the Overtime Protocol:
sev otpThis connects to the running daemon via BEAM RPC and switches to grace mode. Instead of shutting down at T-0, Severance fires a notification every 5 seconds for 60 seconds, then stops. It trusts your judgment after that.
Overtime is a single-day opt-out. If you leave the machine on past midnight, the daemon resets at midnight as though it just started — back to severance mode, waiting to enforce the next day's shutdown.
- macOS (uses
osascriptfor notifications and shutdown) - tmux (for status bar integration and stale pane detection)
Download the latest binary from the releases page and place it on your PATH:
# For Apple ARM processors
gh release download --repo 'KTSCode/severance' --pattern 'sev_macos_arm64' --output ~/bin/sev
# For Apple Intel processors
gh release download --repo 'KTSCode/severance' --pattern 'sev_macos_x86' --output ~/bin/sev
chmod +x ~/bin/sevreplace ~/bin in the above commands with a directory in your PATH if you don't have ~/bin
Requires asdf (manages Erlang, Elixir, and Zig)
and xz on PATH.
asdf install # installs toolchain from .tool-versions
mix deps.get
MIX_ENV=prod mix release sev
cp burrito_out/sev_macos_arm64 ~/bin/sev
chmod +x ~/bin/sevsev updateChecks GitHub releases for a newer version and replaces the binary in-place. Uses only OTP stdlib for HTTPS — no external dependencies required.
sev initCreates ~/.config/severance/config.exs, generates the LaunchAgent plist,
and prepares tmux integration. Safe to re-run.
Run sev init --with-tmux to seed a default tmux countdown publisher
and print the ~/.tmux.conf lines to paste.
Severance ships a self-contained, machine-readable reference built for LLM agents (Claude Code, Codex, Cursor, etc.):
sev help --agentIt documents every command, the config resolution order, all config keys
with their defaults, the publisher contract, the Severance.Status fields,
and task-oriented setup recipes — enough for an agent to configure Severance
in one shot. Point your agent at it, for example:
Run
sev help --agent, then set Severance up for me: create the config, set the shutdown time to 17:00, and wire the tmux countdown publisher.
The config file is evaluated as Elixir — code, not inert data. Only let an
agent edit ~/.config/severance/config.exs in a directory you control, and
review any publisher functions it writes before starting the daemon.
sev # start the daemon
sev status # show daemon status and version info
sev otp # activate overtime protocol
sev log # print the activity log
sev update # update to latest release
sev upgrade # update to latest release (alias for sev update)
sev version # print current version
sev help # print top-level usage (alias for sev --help)
sev help --agent # print the machine-readable reference for LLM agentscp rel/com.severance.daemon.plist ~/Library/LaunchAgents/
launchctl load ~/Library/LaunchAgents/com.severance.daemon.plistConfiguration is resolved in priority order (highest wins):
- CLI flag:
sev --shutdown-time 17:00 - Environment variable:
SEVERANCE_SHUTDOWN_TIME=16:30 sev - Config file:
~/.config/severance/config.exs - Compiled defaults
The config file is a plain Elixir term:
%{
shutdown_time: "17:00",
overtime_notifications: true,
log_file: "~/.local/state/severance/activity.log"
}Set overtime_notifications: false to disable the notification burst when
overtime is active or when starting after shutdown time.
Set log_file to a custom path to change where the activity log is
written. Defaults to ~/.local/state/severance/activity.log.
Publishers push status updates to status bars (tmux, polybar, etc.).
See docs/configuration.md for the full
contract. Out of the box, sev init --with-tmux seeds a tmux
countdown publisher that writes @sev_countdown once per minute.
See docs/architecture.md for how the system fits
together — the supervision tree, countdown state machine, config
resolution, and the RPC seam.
- asdf — installs Erlang, Elixir, and Zig from
.tool-versions - gh — GitHub CLI for releases and PRs
xz— required by the Burrito release builder
asdf install
mix deps.get
mix qualitymix quality # full suite: format, compile, credo, dialyzer, doctor, tests + coverage
mix quality --quick # fast iteration: skips dialyzer and coverage enforcementIndividual checks are still available (mix credo --strict, mix dialyzer,
mix test, etc.) but mix quality is the single entry point.
git config core.hooksPath .githooksThe pre-commit hook runs mix quality --quick before each commit.
From main, with a clean worktree synced with origin:
mix tag --major # bump major version (e.g. 0.11.0 -> 1.0.0)
mix tag --minor # bump minor version (e.g. 0.11.0 -> 0.12.0)
mix tag --patch # bump patch version (e.g. 0.11.0 -> 0.11.1)This orchestrates the full release:
- Shows the
[Unreleased]changelog entries and prompts for confirmation - Finalizes
CHANGELOG.mdunder the new version heading and commits it - Bumps the version in
mix.exs, commits, and creates an annotated tag - Pushes the commits and tag atomically to trigger the CI release workflow
This project is set up for AI-assisted development. Each coding session starts fresh and relies on durable repo files rather than chat history.
- AGENTS.md — shared conventions, build commands, workflow, and documentation lifecycle
- CLAUDE.md — Claude Code-specific configuration (hooks run
mix qualitybefore commits) - dialyxir — static type analysis via Dialyzer (PLTs cached in
priv/plts/) - MCP tools — runtime introspection via tidewave, erl_dist_mcp, and hex-mcp (see
.mcp.json)
Small, well-understood changes go straight to code. For anything larger:
- Research —
docs/research/<feature>.md - Spec —
docs/specs/<feature>.md - Plan —
docs/plans/<feature>.md - Execute — one phase at a time
- Homebrew distribution
- Linux support
- Configurable escalation phases
- Per-day shutdown schedules (e.g. earlier on Fridays)
- Add research doc on Do Not Disturb control
- It would be nice to give it a script or add a function to the config that is run at the do not disturb intervals
- I'd like to give it access to my calendar so that I can Guarantee that it won't cause users to miss meetings
- Reset the daemon at midnight as a fresh day, so overtime is a single-day opt-out and the next day's shutdown is enforced again
- Add a current-state architecture doc and centralize countdown phase definitions in a single Severance.Phase module
