Parallel coding agents are fast — but Android emulators, IoT boards, and serial consoles can only be safely controlled by one process at a time. Without coordination, agents overwrite each other's builds, collide on log streams, and produce flaky false-negative failures.
Arbiter adds a lightweight lease layer on top of your existing CLI tooling so agents queue for device access, work exclusively, and hand off cleanly.
arbiter-intro.mp4
npm install -g @nochoco-lee/arbiter
arbiter startarbiter shim install ~/.arbiter/bin adbThe steps below simulate how a coding agent interacts with Arbiter internally.
In a real setup, the agent skill handles lease acquisition and token propagation automatically. Here, we run the commands manually to demonstrate how the coordination flow works.
Configure the shell the way an autonomous coding agent session would be launched:
export PATH=~/.arbiter/bin:$PATH
export ARBITER_AGENT_SESSION=1Now try running a device command without a lease:
adb shellThe shim intercepts the command:
[ARBITER SHIM] State: no ARBITER_LEASE_TOKEN is set.
[ARBITER SHIM] Next: request a lease before running 'adb'.
[ARBITER SHIM] Command: arbiter request adb --wait
Request a lease:
arbiter request adb --waitExample output:
export ARBITER_LEASE_TOKEN=token-uuid-1234
Run commands with the token:
ARBITER_LEASE_TOKEN=token-uuid-1234 adb shellRelease the lease:
arbiter releaseIn normal agent workflows, lease acquisition and token handling are typically automated through the installed Arbiter skill.
Arbiter requires:
- Node.js 18+
Older Ubuntu releases may ship outdated Node.js packages through apt. Example installation using NodeSource:
curl -fsSL [https://deb.nodesource.com/setup_20.x](https://deb.nodesource.com/setup_20.x) | sudo -E bash -
sudo apt-get install -y nodejsnpm install -g @nochoco-lee/arbiter
arbiter startArbiter replaces device CLI commands with lightweight shims that enforce lease ownership before execution.
Available shims:
adb— required for Android workflowsandroid— optional companion shim for higher-level tooling
Both tools share the same lease slot.
arbiter shim install ~/.arbiter/bin adb
arbiter shim install ~/.arbiter/bin androidarbiter shim install C:\Arbiter\bin adb
arbiter shim install C:\Arbiter\bin androidImportant
Many Android projects bypass $PATH completely and invoke adb using an absolute SDK path (for example through Gradle or local.properties). Arbiter supports two mitigation strategies:
- Agent instructions that explicitly forbid absolute-path adb
- Optional SDK binary replacement on macOS/Linux (adb → adb.real)
Tip
If Arbiter cannot automatically discover the real binary location, it will prompt for the absolute path during installation.
Arbiter provides a built-in skill file that teaches coding agents:
- how to request leases
- how to pass tokens
- why absolute paths must be avoided
Run this inside your project root:
arbiter skills install arbiterThis generates: .agents/skills/arbiter/SKILL.md. Repeat this for each workspace where agents operate.
Agents should use shimmed binaries while humans continue using the real system tools. Do not add the Arbiter shim directory to your global system PATH. Instead, prepend it only inside the agent launcher environment.
export PATH=~/.arbiter/bin:$PATH
export ARBITER_AGENT_SESSION=1
codex (or claude)$env:Path = "C:\Arbiter\bin;" + $env:Path
$env:ARBITER_AGENT_SESSION = "1"
codex (or claude)set PATH=C:\Arbiter\bin;%PATH%
set ARBITER_AGENT_SESSION=1
codex (or claude)Arbiter is intentionally hint-driven. If an agent attempts to access a protected resource without a lease, the shim explains exactly how to recover.
Example output:
[ARBITER SHIM] State: no ARBITER_LEASE_TOKEN is set.
[ARBITER SHIM] Next: request a lease before running 'adb'.
[ARBITER SHIM] Command: arbiter request adb --wait
[ARBITER SHIM] Note: adb and android share the same lease.
arbiter request adb --waitExample output:
export ARBITER_LEASE_TOKEN=token-uuid-1234
Coding agents frequently spawn isolated shell sessions for each command they execute. Because environment variables may not persist between invocations, the safest pattern is to pass the lease token inline with every device command.
ARBITER_LEASE_TOKEN=token-uuid-1234 adb install app.apk
ARBITER_LEASE_TOKEN=token-uuid-1234 adb logcat -d
ARBITER_LEASE_TOKEN=token-uuid-1234 adb shell dumpsys battery$env:ARBITER_LEASE_TOKEN='token-uuid-1234'; adb logcat -dset ARBITER_LEASE_TOKEN=token-uuid-1234 && adb logcat -dTip
Human-operated interactive terminals can safely use a normal one-time export. The inline pattern mainly exists for autonomous agents that spawn isolated command sessions.
arbiter releasearbiter tuiDisplays:
- active leases
- queue depth
- current owners
- resource states
arbiter doctorVerifies:
- broker connectivity
- binary mappings
- shim configuration
arbiter logs --follow
arbiter logs --limit 50arbiter lease status --resource adbexport PATH=/tmp/arbiter_shims:$PATH
arbiter request adb --wait
ARBITER_LEASE_TOKEN=<token> adb install app1.apk
ARBITER_LEASE_TOKEN=<token> adb logcat -dAgent A now owns the device lease.
export PATH=/tmp/arbiter_shims:$PATH
adb install app2.apkThe shim blocks execution:
[ARBITER SHIM] State: no ARBITER_LEASE_TOKEN is set.
[ARBITER SHIM] Command: arbiter request adb --wait
Request the lease:
arbiter request adb --waitAgent B waits until Agent A releases ownership. Once released, Agent B automatically acquires the lease and continues.
Arbiter works by intercepting device CLI commands through lightweight shims. The shim checks lease ownership with a local broker daemon before forwarding execution to the real underlying binary.
Coding Agent
│
▼
Arbiter Shim ◄────► Arbiter Broker
│ (leases, queues, ownership)
▼
Real Device / Emulator
This allows multiple autonomous agents to share hardware safely without modifying the underlying tools themselves.
- Lease-based resource locking
- Queueing and ownership tracking
- Shared lease groups (adb + android)
- Graceful handoff during active commands
- Cooperative read-only permits
- Interactive terminal dashboard
- Audit history per resource
- Async reservation support for long waits
Arbiter does not:
- virtualize hardware
- sandbox processes
- isolate environments
- proxy device traffic
It only coordinates ownership and execution sequencing.
See CONTRIBUTING.md for:
- local development setup
- testing
- adapter implementation
- broker internals
MIT