| name | agmsg |
| description | Cross-agent messaging via SQLite. Send messages between Claude Code, Codex, Gemini CLI, GitHub Copilot CLI, and other agents. No daemon, no network, no dependencies beyond bash and sqlite3. |
Agent Messaging
IMPORTANT: Always use the provided scripts. NEVER directly read or edit config files, DB, or team data. There is NO register.sh — use join.sh to join a team.
How to use
Step 0: First-run bootstrap
agmsg keeps its SQLite database, team registry, and runtime state under ~/.agents/skills/agmsg/. The ./install.sh install path creates that tree; the Claude Code plugin install path does not (the plugin marketplace flow only drops the skill content into ~/.claude/plugins/cache/). Before any other command, bootstrap if needed:
if [ ! -d ~/.agents/skills/agmsg ]; then
installer=$(ls ~/.claude/plugins/cache/fujibee-agmsg/agmsg/*/install.sh 2>/dev/null | head -1)
if [ -n "$installer" ]; then
bash "$installer" --cmd agmsg
else
echo "agmsg not installed. Either:" >&2
echo " - run ./install.sh in the agmsg repo, or" >&2
echo " - install via /plugin marketplace add fujibee/agmsg && /plugin install agmsg@fujibee-agmsg" >&2
exit 1
fi
fi
After this runs once, ~/.agents/skills/agmsg/ is populated and you can skip Step 0 on future invocations.
Step 1: Check identity
~/.agents/skills/agmsg/scripts/whoami.sh "$(pwd)" <type>
Step 2a: If not in a team — join one
Ask the user for a team name and agent name, then run:
~/.agents/skills/agmsg/scripts/join.sh <team> <agent_name> <type> "$(pwd)"
Do NOT manually edit config files. Always use join.sh.
Step 2b: If already in a team — execute command
Default (no arguments): IMMEDIATELY check inbox. Do NOT ask what to do.
~/.agents/skills/agmsg/scripts/inbox.sh <team> <agent_id>
~/.agents/skills/agmsg/scripts/send.sh <team> <from_agent> <to_agent> "<message>"
~/.agents/skills/agmsg/scripts/history.sh <team> [agent_id] [limit]
~/.agents/skills/agmsg/scripts/team.sh <team>
~/.agents/skills/agmsg/scripts/leave.sh <team> <agent_id>
~/.agents/skills/agmsg/scripts/rename-team.sh <old_team> <new_team>
~/.agents/skills/agmsg/scripts/version.sh
~/.agents/skills/agmsg/scripts/reset.sh "$(pwd)" <type> [agent_id] [session_id]
~/.agents/skills/agmsg/scripts/delivery.sh set <mode> <type> "$(pwd)"
~/.agents/skills/agmsg/scripts/delivery.sh status <type> "$(pwd)"
~/.agents/skills/agmsg/scripts/actas-claim.sh "$(pwd)" <type> <name> "$session_id"
~/.agents/skills/agmsg/scripts/reset.sh "$(pwd)" <type> <name> "$session_id"
~/.agents/skills/agmsg/scripts/spawn.sh <claude-code|codex> <name> [options]
~/.agents/skills/agmsg/scripts/despawn.sh <team> <from> <name> [--force] [--timeout N]
Sandbox compatibility (Claude Code)
When Claude Code's sandbox is enabled, watch.sh (monitor mode) runs inside the sandbox and needs to write pidfiles and SQLite WAL files under ~/.agents/skills/agmsg/. Add an allowlist entry to ~/.claude/settings.json (or project-level .claude/settings.local.json):
{
"sandbox": {
"filesystem": {
"allowWrite": [
"~/.agents/skills/agmsg/"
]
}
}
}
The allowlist merges across scopes and takes effect immediately — no restart needed. If agmsg was installed under a custom command name (e.g. m), adjust the path accordingly.
Note on BASH_SOURCE: The sandboxed Bash tool runs commands via pipe/eval, so BASH_SOURCE[0] is empty inside sourced functions like storage.sh. This is handled internally — watch.sh resolves SKILL_DIR from $0 (which works correctly when invoked as a command), and storage.sh falls back to that value. No user configuration needed.
Architecture
- Storage: SQLite with WAL mode in
~/.agents/skills/agmsg/db/messages.db
- Teams:
~/.agents/skills/agmsg/teams/<name>/config.json
- Concurrency: WAL allows multiple readers + 1 writer without conflicts
- No daemon: Direct DB access via
sqlite3 CLI
- Dependencies: bash, sqlite3 (no python3 required)