rallish

module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2026 License: MIT

README

rallish

A local broker for multi-agent turn-taking, A2A-compliant.

version license go

rallish is a small local broker process that sits between N agent runtimes — any coding CLI with an adapter (Claude, Kimi, Cursor, Codex, etc., or even the same kind running in different contexts). The broker owns the conversation state, decides whose turn it is, and shuttles compact turn payloads between them.

Everything runs locally. No cloud broker, no external coordination service. The wire format follows the A2A (Agent2Agent) protocol where reasonable, so any A2A-compliant agent can be plugged in via an adapter.

한국어 · 日本語

Features

Feature Description
Squash (headless) rallish squash runs headless preset sessions (solo-ralph, pair-review); broker spawns adapters automatically
Rally (interactive) rallish rally provides live baton-passing between two coding-CLI sessions; agents self-loop the ping-pong (no per-turn user trigger needed); exclusive holder enforcement via SSE
A2A Protocol /.well-known/agent.json, JSON-RPC 2.0 tasks, SSE streaming
Token Budgets Hard caps on tokens, turns, and wall-clock time per session
Scratchpad Rolling shared scratch with automatic compaction
Presets YAML templates for roles, routing, and exit conditions
Unix socket IPC CLI↔Daemon over ~/.rallish/rallish.sock (mode 0600); TCP loopback retained for A2A clients and Windows fallback
Auto-daemon rallish squash spawns the broker if none is running; rallish doctor reports socket reachability
Security Path traversal guards, secret redaction, minimal env allowlists

Architecture

┌──────────────────────────────────────────┐
│  rallish broker (Go)                     │
│  POST /sessions                          │
│  GET  /sessions/:id/next?as=<role> (SSE) │
│  POST /sessions/:id/turn                 │
│  GET  /.well-known/agent.json            │
│  POST /a2a                               │
└──┬───────────────┬───────────────────┬───┘
   │ unix socket   │ unix socket       │ tcp loopback
   │ ~/.rallish/   │ ~/.rallish/       │ 127.0.0.1:<port>
   │ rallish.sock  │ rallish.sock      │ (A2A + fallback)
┌──┴─────────┐   ┌─┴────────┐      ┌──┴───────────┐
│  agent A   │   │ agent B  │      │ external A2A │
│  (CLI)     │   │  (CLI)   │      │  client      │
└────────────┘   └──────────┘      └──────────────┘

Same broker serves both transports concurrently. The CLI (rallish squash, rallish rally, rallish doctor) prefers the Unix socket; external A2A clients use TCP loopback.

Prerequisites

  • Go 1.25+ (for building from source)
  • At least one compatible agent CLI installed and authenticated (see supported adapters)

Verify:

go version        # must be 1.25+
which claude      # any supported adapter binary on $PATH

Install

One command:

npx skills add jazz1x/rallish

That delivers the skill bundle (SKILL.md + bundled binary installer) to ~/.claude/skills/rallish/. Resolves via skills.sh.

Open any project in Claude Code (or another skill-aware coding CLI) and say 랠리보낼 준비해 / let's serve. On first use the skill self-installs the rallish binary via the bundled platform-detecting script (scripts/install-binary.sh → fetches the latest GitHub Release into /usr/local/bin or ~/.local/bin).

Power-user alternatives (skip the bundle)
Method Command
Homebrew tap (macOS) coming soonbrew install jazz1x/rallish/rallish will work once the jazz1x/homebrew-rallish tap repo and TAP_GITHUB_TOKEN secret are provisioned (see #issues)
curl (any Unix) curl -fsSL https://raw.githubusercontent.com/jazz1x/rallish/main/install.sh | sh
From source git clone https://github.com/jazz1x/rallish && cd rallish && make build
go install go install github.com/jazz1x/rallish/cmd/rallish@latest

After the binary is on $PATH, rallish bootstrap (idempotent) installs the skill bundle and verifies the daemon.

✓ rallish runs once per user (not per project). After the one-time install you can rally from any directory — no need to be inside the rallish source tree. The daemon is global at ~/.rallish/. See docs/handbook.md#using-rallish-from-any-project for the project-agnostic workflow.

Quickstart

# One-shot setup wizard (installs the skill + asks 3 short questions)
./dist/rallish bootstrap

# Environment check (renders adapters + daemon as a glyph status list)
./dist/rallish doctor

# Inspect or edit settings (~/.rallish/config.yaml)
./dist/rallish config list
./dist/rallish config set wait_mode block
./dist/rallish config edit              # opens $EDITOR

# Interactive component picker (npx-style)
./dist/rallish add

# List built-in adapters and presets
./dist/rallish add --list

# Headless preset session (auto-spawns the daemon)
./dist/rallish squash \
  --preset pair-review \
  --task "Add OAuth2 support" \
  --repo ./my-project

# Smoke test without real adapters (fake/deterministic, 3 turns)
cat > ~/.rallish/presets/fake-demo.yaml <<'EOF'
name: fake-demo
roles:
  - {id: ralph, runtime: fake, model: fake-1}
routing: round_robin
budget: {max_turns: 3, max_tokens: 10000, deadline_minutes: 5}
exit_when: [turns_exhausted]
scratch: {max_kb: 16}
EOF
./dist/rallish squash --preset fake-demo --task "smoke test" --repo /tmp

# Two-terminal tennis rally (live baton-passing between human sessions)
# Prefer the natural-language UX driven by skills/rallish —
# the agent (Claude Code, Cursor, …) runs all rally commands for you.
# In Terminal A's coding-CLI session you say:    "랠리보낼 준비해 — 사이클로 가자"
# Agent: rally new --first server + role=server, prints SID, serves first turn, yields.
# In Terminal B's coding-CLI session you say:    "랠리받을 준비해 <SID>"
# Agent: parses pattern, role=returner, immediately picks up the baton, yields.
# After each side finishes a turn the agent yields back to the user; on the
# next user message it checks status and continues if it's its turn. No
# per-turn "내 차례" trigger needed.
# Either side, at any time, to stop:             "끝"
#
# Raw CLI surface (used by the skill under the hood, or by scripts):
SESSION=$(./dist/rallish rally new --participants server,returner --task "warm-up rally")
./dist/rallish rally status --session-id $SESSION
./dist/rallish rally done   --session-id $SESSION --as server --note "draft v1"

# A2A discovery (external clients use TCP loopback)
curl http://127.0.0.1:$(cat ~/.rallish/port)/.well-known/agent.json

# A2A send task
curl -X POST http://127.0.0.1:$(cat ~/.rallish/port)/a2a \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tasks/send","params":{"message":{"parts":[{"text":"Hello"}]}}}'

Per-turn requests and responses land in ~/.rallish/sessions/<id>/log.jsonl.

CLI surface

rallish --help groups commands into four sections. Output uses PyClack-style glyphs (◇ info, ✓ ok, ⚠ warn, ■ err, ◆ prompt, └ footer) and auto-falls-back to plain ASCII when $NO_COLOR is set or stdout is not a TTY.

Group Commands
Setup bootstrap (one-shot wizard) · skill install
Rally rally (live baton) · squash (headless preset)
Manage add (interactive picker · --list for catalog) · config (list / get / set / path / edit)
System doctor (status table) · daemon · version

rallish bootstrap fits on one screen by design — the wizard never exceeds ~12 lines so coding-CLI session banners (skills discography, trigger lists) stay visible after the install.

Usage

1. Start a headless session
rallish squash --preset <name> --task "<description>" --repo <path>

Presets live in internal/preset/presets/ (built-ins) or ~/.rallish/presets/ (custom). See docs/handbook.md for preset authoring.

1b. Start an interactive rally session

Agent-driven (recommended). Open this repo in any coding CLI that auto-discovers skills (Claude Code, Cursor, …). The skills/rallish skill loads on these natural-language triggers:

You say The agent does
랠리보낼 준비해 / let's serve rally new, takes role=server, prints the SID
랠리받을 준비해 <SID> / let's return rally status, takes role=returner, waits
시작 / go (server side) serves the first turn, then rally done with a summary note
내 차례 / is it my turn (receiver side) rally status; if it's your turn, reads the previous note, does the work, runs rally done
/ match over clean shutdown

Short triggers like 시작 / go / / 내 차례 only activate after a prior prep trigger set the role + SID; bare generic words are ignored.

Raw CLI (for scripts or non-skill-aware clients):

rallish rally new    --participants <a>,<b> [--task "<desc>"]
rallish rally join   --session-id <id> --as <name>           # blocks on SSE
rallish rally done   --session-id <id> --as <name> [--note "<s>"] [--handoff-to <n>]
rallish rally status --session-id <id>

See docs/runbook-rally-mode.md for the full two-terminal walkthrough.

2. A2A integration

Any A2A-compliant client can discover and send tasks:

Method Path Description
GET /.well-known/agent.json Agent Card
POST /a2a JSON-RPC 2.0 (tasks/send, tasks/get, tasks/cancel, tasks/sendSubscribe)

See docs/a2a-compatibility.md for the full mapping.

3. Same-type pairing

You can pair two Claude instances, two Kimi instances, or any mix. The broker only cares about turn order, not vendor identity.

4. Check budget status

Budgets (tokens, turns, deadline) are enforced per session. When exhausted, the broker returns 410 Gone and preserves the scratchpad for resume.

5. Custom presets

Drop a YAML file in ~/.rallish/presets/<name>.yaml:

name: my-preset
description: Optional one-line summary.
roles:
  - id: planner
    runtime: claude
    model: opus
  - id: executor
    runtime: kimi
    model: kimi-k2
routing: handoff_then_round_robin    # or round_robin
budget:
  max_turns: 20
  max_tokens: 400000
  deadline_minutes: 60
exit_when: [tests_pass, reviewer_approved, turns_exhausted]
scratch:
  max_kb: 64
  summarize_with: claude-haiku
6. Daemon lifecycle
rallish daemon &                            # explicit start (optional — squash auto-spawns)
ls ~/.rallish/                              # rallish.sock (0600), socket, port, sessions/
kill -TERM $(pgrep -f "rallish daemon")     # graceful shutdown removes all three files

rallish doctor confirms reachability:

daemon reachable via unix socket path=/Users/<you>/.rallish/rallish.sock perm=-rw-------

On Windows the broker falls back to TCP loopback only (Unix socket stub returns ErrUnsupported).

Security

  • Broker binds to 127.0.0.1 only.
  • No auth layer in v0; use a reverse proxy or local firewall for shared machines.
  • Preset files are validated for path traversal before loading.
  • Secrets in env vars are redacted from logs.

See DESIGN.md §14 for the full threat model.

Development

Enable the repo's pre-commit hook once per clone:

make setup-hooks

Run the full check suite:

make check   # go vet + golangci-lint + go test -race
Test suite
make test    # go test ./...
make bench   # go test -bench=. -benchmem ./...

Coverage floor: ≥70% on internal/session, internal/router, internal/exit, internal/preset, pkg/contract.

Conventions

See AGENTS.md for coding guidelines, project layout, and commit conventions.

License

MIT — See LICENSE.

"Like a rally, the best turns happen when no one tries to hold the ball."

Directories

Path Synopsis
cmd
rallish command
Package main is the CLI entrypoint for the rallish broker.
Package main is the CLI entrypoint for the rallish broker.
internal
adapter
Package adapter defines the adapter interface and registry for agent runtimes.
Package adapter defines the adapter interface and registry for agent runtimes.
adapter/claude
Package claude implements the rallish adapter for the Claude CLI runtime.
Package claude implements the rallish adapter for the Claude CLI runtime.
adapter/fake
Package fake provides a deterministic test adapter for rallish.
Package fake provides a deterministic test adapter for rallish.
adapter/kimi
Package kimi implements the rallish adapter for the Kimi CLI runtime.
Package kimi implements the rallish adapter for the Kimi CLI runtime.
broker
Package broker provides the HTTP/SSE server and route handlers for the rallish broker.
Package broker provides the HTTP/SSE server and route handlers for the rallish broker.
budget
Package budget tracks token, turn, and wall-clock budgets for rallish sessions.
Package budget tracks token, turn, and wall-clock budgets for rallish sessions.
buildinfo
Package buildinfo provides version metadata injected at link time.
Package buildinfo provides version metadata injected at link time.
cli
Package cli implements the daemon and start commands for rallish.
Package cli implements the daemon and start commands for rallish.
config
Package config is the SSOT for user-facing rallish settings.
Package config is the SSOT for user-facing rallish settings.
doctor
Package doctor checks adapters, paths, and permissions.
Package doctor checks adapters, paths, and permissions.
exit
Package exit evaluates session exit conditions and runs shell predicates when required.
Package exit evaluates session exit conditions and runs shell predicates when required.
ipc
Package ipc implements Unix-socket transport for rallish CLI commands.
Package ipc implements Unix-socket transport for rallish CLI commands.
logx
Package logx provides structured logging and secret redaction for rallish.
Package logx provides structured logging and secret redaction for rallish.
preset
Package preset loads and validates rallish preset YAML with strict schema checking.
Package preset loads and validates rallish preset YAML with strict schema checking.
router
Package router decides which role receives the next turn in a rallish session.
Package router decides which role receives the next turn in a rallish session.
runner
Package runner implements the adapter loop that polls the broker for turns.
Package runner implements the adapter loop that polls the broker for turns.
safepath
Package safepath provides path-traversal-safe filepath helpers for rallish.
Package safepath provides path-traversal-safe filepath helpers for rallish.
scratch
Package scratch manages the rolling shared scratchpad and compaction triggers.
Package scratch manages the rolling shared scratchpad and compaction triggers.
session
Package session manages conversation state, jsonl append-only logs, and log replay.
Package session manages conversation state, jsonl append-only logs, and log replay.
skills
Package skills bundles the rallish skill files into the rallish binary and exposes an Install function that writes them to a target directory.
Package skills bundles the rallish skill files into the rallish binary and exposes an Install function that writes them to a target directory.
ui
Package ui is the rallish CLI presentation SSOT.
Package ui is the rallish CLI presentation SSOT.
pkg
contract
Package contract defines the public wire types for rallish.
Package contract defines the public wire types for rallish.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL