Table of Contents
Open Table of Contents
Why this is useful
Beads records who created, claimed, updated or closed an issue. By default this can be a bit too generic when several tools run on the same machine.
If I have Claude in one tmux pane, Codex in another, and maybe Pi somewhere else, I want the Beads history to show something better than just my Unix user. I want names like:
claude-blog-w0-p1
codex-blog-w0-p2
pi-blog-w1-p0
That makes it much easier to understand later who did what.
The trick is simple: set BEADS_ACTOR before starting the agent.
File structure
I keep the Beads actor helpers outside .bashrc and only source them from there:
~/.bashrc
~/.config/beads/actors.bash
Create the directory first:
mkdir -p ~/.config/beads
The actor helper script
Create ~/.config/beads/actors.bash:
cat > ~/.config/beads/actors.bash <<'EOF'
# >>> beads actors >>>
#
# Beads actor identity for humans and AI agents.
#
# Beads uses BEADS_ACTOR for the audit trail and claim ownership.
# These helpers give every agent process a useful actor name, especially
# when multiple agents run in different tmux panes or terminals.
# Human default. Plain bd commands use this unless overridden.
export BEADS_ACTOR=Alex
# Build a stable suffix for the current terminal context.
#
# In tmux:
# session/window/pane, e.g. blog-w0-p2
#
# Outside tmux:
# shell PID, e.g. pid-48231
_beads_actor_suffix() {
if [[ -n "${TMUX:-}" ]] && command -v tmux >/dev/null 2>&1; then
tmux display-message -p '#S-w#I-p#P' 2>/dev/null | tr -c '[:alnum:]_.-' '-'
else
printf 'pid-%s' "$$"
fi
}
# Run an agent with a Beads actor identity.
#
# Arguments:
# $1 = actor prefix, e.g. claude, codex, gemini, pi
# $2 = command to execute, e.g. claude, codex, gemini, pi
# remaining args are passed through to the command.
#
# Override example:
# BEADS_AGENT_ACTOR=codex-reviewer codex-bd
_beads_run_agent() {
local agent_name="$1"
local command_name="$2"
shift 2
local actor="${BEADS_AGENT_ACTOR:-${agent_name}-$(_beads_actor_suffix)}"
echo "Starting $command_name with BEADS_ACTOR=$actor" >&2
BEADS_ACTOR="$actor" "$command_name" "$@"
}
claude-bd() {
_beads_run_agent "claude" "claude" "$@"
}
codex-bd() {
_beads_run_agent "codex" "codex" "$@"
}
gemini-bd() {
_beads_run_agent "gemini" "gemini" "$@"
}
pi-bd() {
_beads_run_agent "pi" "pi" "$@"
}
# Human role helpers.
#
# Useful when I want to run one bd command under a more specific role
# without changing the default shell identity.
developer-bd() {
BEADS_ACTOR="developer-$(_beads_actor_suffix)" "$@"
}
maintainer-bd() {
BEADS_ACTOR="maintainer-$(_beads_actor_suffix)" "$@"
}
human-bd() {
BEADS_ACTOR="human-$(_beads_actor_suffix)" "$@"
}
# Debug helper.
beads-actor() {
echo "BEADS_ACTOR=${BEADS_ACTOR:-}"
echo "BEADS_AGENT_ACTOR=${BEADS_AGENT_ACTOR:-}"
echo "computed suffix=$(_beads_actor_suffix)"
}
# <<< beads actors <<<
EOF
Source it from .bashrc
Add this block to ~/.bashrc, but only if it is not already there:
grep -q 'actors.bash' ~/.bashrc || cat >> ~/.bashrc <<'EOF'
# Beads actor helpers
if [[ -f "$HOME/.config/beads/actors.bash" ]]; then
source "$HOME/.config/beads/actors.bash"
fi
EOF
Reload the shell:
source ~/.bashrc
Or just open a new terminal.
Usage
Start agents through the helper functions:
claude-bd
codex-bd
gemini-bd
pi-bd
Arguments are passed through, so this also works:
pi-bd --model claude-sonnet-4.5
codex-bd --help
Check the current actor setup:
beads-actor
Inside tmux, this should print a suffix based on the tmux session, window and pane. Outside tmux it falls back to the shell PID.
Manual actor names
Sometimes I want a more meaningful actor name for a specific session:
BEADS_AGENT_ACTOR=codex-reviewer codex-bd
BEADS_AGENT_ACTOR=claude-migration claude-bd
BEADS_AGENT_ACTOR=pi-docs pi-bd
That override is only used for that command.
Human roles
For one-off human commands:
developer-bd bd update <id> --claim
maintainer-bd bd close <id> --reason "Rejected"
human-bd bd create "Task" --description "..." --type task --priority 2
These helpers are intentionally boring. They just set BEADS_ACTOR and run the command.
What shows up in Beads
After using one of these wrappers, Beads history and ownership should use the computed actor. For example:
claude-bd
# inside Claude/pi/codex/etc.
bd update aholbreich-blog-123 --claim
The claim should now belong to something like:
claude-blog-w0-p1
instead of a generic local username.
zsh note
I use bash here. For zsh the idea is the same, but source the file from ~/.zshrc instead of ~/.bashrc:
if [[ -f "$HOME/.config/beads/actors.bash" ]]; then
source "$HOME/.config/beads/actors.bash"
fi
The functions themselves should work in zsh too, but I keep the file named actors.bash because my primary shell setup is bash.
Small caveats
- If tmux is not installed or the shell is not inside tmux, the suffix uses the shell PID.
- If an agent launches sub-processes, they inherit
BEADS_ACTORunless overwritten. - If you run plain
bddirectly, it uses the defaultBEADS_ACTOR=Alex. - If you want every terminal pane to have a distinct human actor too, use
developer-bd,maintainer-bdorhuman-bdfor those commands.
Feedback
I appreciate feedback to all of this. Maybe there is better way?