From dibs
Take exclusive occupancy of a working directory so only one coding agent works in it at a time. Use before a tool or agent starts mutating a directory that another agent (often a different vendor) might also pick up, or when you need to know who currently holds a directory. claim/release/check on a vendor-neutral, cross-platform lockfile keyed by the directory's realpath; self-heals a lock left by a dead process and respects a live one.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dibs:dibsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Calling dibs on a directory: a small, vendor-neutral, cross-platform lock so
Calling dibs on a directory: a small, vendor-neutral, cross-platform lock so only one coding agent occupies a working directory at a time. A Claude and a Codex contend for the same lock through the same on-disk artifact, so neither needs to know about the other's hooks.
The lock is a file created with an atomic exclusive create
(open(O_CREAT|O_EXCL), the node wx flag) at a deterministic path keyed by
the target directory's realpath: ${LAICLUSE_HOME:-$HOME/.laicluse}/locks/<sha256-of-realpath>.lock.
The record holds the realpath, holder pid, agent, session id, hostname, a
nonce, and an acquired-at timestamp. Liveness is pid-based
(process.kill(pid, 0) on the same host), not a heartbeat: a lock whose holder
process is gone is taken over by the next claimer, while a live holder is
refused. No external binary, no flock, no native dependency.
The CLI lives in this plugin's bin/. Resolve the plugin root, then call it:
resolve_dibs_root() {
if [ -n "${DIBS_BIN:-}" ]; then dirname "$(dirname "$DIBS_BIN")"; return 0; fi
if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then printf '%s\n' "$CLAUDE_PLUGIN_ROOT"; return 0; fi
if command -v codex >/dev/null 2>&1; then
codex plugin list | awk '$1 == "dibs@laicluse-agent-fieldkit" { print $NF; found=1; exit } END { exit found ? 0 : 1 }'
return $?
fi
return 1
}
ROOT="$(resolve_dibs_root)" || { echo "dibs plugin root not found" >&2; exit 1; }
DIBS="${DIBS_BIN:-$ROOT/bin/dibs}"
node "$DIBS" claim <dir> [--pid <n>] [--agent <name>] [--session <id>] [--max-age-hours <n>] [--json]
node "$DIBS" release <dir> [--pid <n>] [--json]
node "$DIBS" check <dir> [--max-age-hours <n>] [--json]
held-by-self), or takes over a
stale lock whose holder is dead (took-over-stale). It exits non-zero and
names the holder (refused: held by <agent> (pid <pid>) since <acquired-at>)
when a live holder exists.free or the holder plus its liveness and staleness.--pid is the pid that must stay alive for the lock to count as live. Record
the long-lived holder (the agent or session process), not the ephemeral process
that runs dibs. It defaults to the calling process's parent pid. --json
prints the full result record for machine consumers.
The lock only helps if it is acquired before mutation, so the two reliable acquisition points are:
bonsai claims the lock for a worktree it hands out
(it consumes this one implementation; there is no second lock anywhere). The
git-native commit hook in the branch-worktree-discipline order remains the
backstop for agents without a reliable pre-mutation hook.--max-age-hours cap bound the
residual risk; v1 accepts it rather than adding a native process-start probe.EPERM), so dibs never breaks a lock it cannot prove dead; that lock
clears only via --max-age-hours. Within one user on one machine, the agent
case, liveness is exact.index.lock.Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
npx claudepluginhub epologee/laicluse-agent-fieldkit --plugin dibs