Skip to main content

✋ call-dibs

Call dibs on shared stuff.

A tiny lock ledger so humans and AI agents stop fighting over the same phone, GPU, or test bench.

CI PyPI Python 3.8+ License: MIT

$ dibs claim phone-a --note "regression run"
claimed phone-a as alice

$ dibs claim phone-a                      # …from another session
BUSY phone-a: held by alice since 2026-09-02T21:14:03Z (3m ago) — "regression run"

$ dibs release phone-a
released phone-a (was alice)

Why

You have one test phone, one GPU, one hardware bench — and several terminals (or several coding agents) that can all reach it. dibs is the smallest thing that makes them take turns.

  • One file, no dependencies. A single Python script, stdlib only. No daemon, no server, no database.
  • Cross-platform. macOS, Linux, Windows.
  • Legible. The ledger is one human-readable JSON file per resource, and every "busy" says who, since when, and why.
  • Agent-friendly. Stable exit codes, --json, a blocking --wait, and a run wrapper that always releases — even when the command fails.

Install

pipx install call-dibs        # or: pip install call-dibs · uv tool install call-dibs

Works the same on macOS, Linux, and Windows. Prefer no package manager? It's one file — dibs.py — drop it on your PATH.

Set up

Tell dibs what you share. Write ~/.dibs/resources.json once, by hand:

{
  "phone-a": "Android test phone on the bench",
  "gpu-0": "the shared training GPU",
  "printer": "label printer, room 2"
}

Only these names can be claimed, so a typo can't silently create a new lock. dibs never edits this file.

Use

command what it does
dibs claim <r...> [--note ...] [--wait [--timeout N]] claim one or more resources. Exit 2 + holder info if busy; --wait waits in line
dibs release <r...> [--force] release
dibs status [r|group] [--json] who has what (a group tag shows its members)
dibs wait <r...> [--timeout N] block until free, without claiming
dibs run <r> -- <cmd...> claim → run → always release
dibs watch live terminal view

Exit codes: 0 ok · 2 busy · 3 not yours · 4 wait timeout · 1 error.

Who's asking

Every claim records an owner, and only that owner can release it. Name yourself once per session with DIBS_OWNER:

export DIBS_OWNER=alice                    # people
DIBS_OWNER=agent:task-123 dibs claim …     # agents: inline, so every call agrees

If it's unset, dibs falls back to user@host:pid — fine for one-off use, wrong for agents whose shell changes every command. --force releases someone else's lock when they're gone.

Groups

Claim several resources in one call and they form a group. The claim is all-or-nothing — if any resource is busy, nothing is taken — and the group gets a tag so you can drop the whole set at once:

$ dibs claim phone-a gpu-0 --note "regression run"
claimed gpu-0 as alice
claimed phone-a as alice
group g-3fa2c1: gpu-0, phone-a (discard with: dibs release g-3fa2c1)

$ dibs release g-3fa2c1

Name the group yourself with --as NAME.

Waiting in line

claim --wait takes a place in line. When something frees up, the longest waiter that can use it goes first, and a claim without --wait can't jump ahead of it — it gets BUSY … free, but next in line is …. A waiter still blocked on something else doesn't hold up devices it isn't using yet, so a big multi-resource claim can still lose its turn to smaller ones.

Your place lasts only while the wait is running: time out, Ctrl-C, or get killed and you're out of line (a retry starts at the back). dibs status shows the line under each resource; --json rows gain a waiting list.

For AI agents

skills/dibs/ is a drop-in skill for Claude Code (and reads fine as an AGENTS.md snippet for anything else). It teaches the protocol: claim before touching hardware, one call per set, wait in line instead of retrying, release as soon as you stop driving it (even to wait on a human), never force-break someone else's lock.

cp -r skills/dibs ~/.claude/skills/

Menu bar (macOS)

See the ledger at a glance: dibs ✋2 ⏳1 in the top bar when two things are claimed and one claim is waiting, dibs ✓ when everything is free, and who-has-what in the dropdown. Under SwiftBar each claimed resource also has Force release…, behind a confirm dialog — for holders that are gone. Install SwiftBar, then add the plugin:

open "swiftbar://addplugin?src=https://raw.githubusercontent.com/NeoMarcoPolo/call-dibs/main/contrib/dibs.5s.sh"

Start the UI when you want it with open -a SwiftBar; quit it from the dropdown's Quit item. (SwiftBar only runs when launched — set it as a login item if you'd rather have it always there.)

How it works

One JSON file per resource under ~/.dibs/ (override with DIBS_DIR). A claim is an atomic O_CREAT|O_EXCL create, so racing claimers get exactly one winner. Locks are advisory and are held until released — there is no expiry. A waiting claim keeps a small ticket in ~/.dibs/queue/ and refreshes it every poll; a ticket is dropped after 15 s without a refresh (longer with a slower --poll), so a waiter that died never blocks the line. The ledger is per-machine by default; point DIBS_DIR at a shared directory to span machines.

Contributing

python3 -m unittest discover tests. Keep it small.

Releases: bump version in pyproject.toml and dibs.py, then push a v* tag — CI publishes to PyPI via trusted publishing (maintainer approval required).

License

MIT

Release files for call-dibs 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for call-dibs 0.4.0
File Size Uploaded
call_dibs-0.4.0.tar.gz 17.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for call-dibs 0.4.0
File Interpreter ABI Platform
call_dibs-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 30.6 kB

Release files / call_dibs-0.4.0.tar.gz

Download URL call_dibs-0.4.0.tar.gz
Size 17.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d20219e5666c1d70869a74334219043a18d07dffdc3d46b016def71ebac70ff7
BLAKE2b-256 checksum
How to use checksums
9f45cb55021610b0877daf66dac811d94208e59e0760dd71c7deec61b90f43c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / call_dibs-0.4.0-py3-none-any.whl

Download URL call_dibs-0.4.0-py3-none-any.whl
Size 13.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3a2efe2720a277d922806f7daca1c701c65260c08a7f908da4791c04463fb7a9
BLAKE2b-256 checksum
How to use checksums
40242cdb92f3e10dc22e262ebe3ad333ca64981fc1c4fe386bf81fc32027e12c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page