A local council room for coordinating multiple coding agent CLIs.
Project description
councli
councli is a local council room for multiple coding agent CLIs. It broadcasts
prompts to installed assistants, records their responses on an inspectable
blackboard, gives them shared visibility into each other's output, and returns a
unified answer while preserving each assistant's native harness.
It is not a model provider, not a replacement for Claude Code/Codex/AGY/Kimi,
and not a new tool sandbox. The assistants remain ordinary binaries on your
machine; councli is the room, recorder, router, and coordination layer around
them.
Features
- Shared conversation turns by default.
- Explicit
/deliberateand/votecommands for stronger coordination. - Slash-command autocomplete, prompt history, and a terminal-friendly control plane.
- File-backed blackboards under
.councli/runs/. - Packet-file prompts and response sidecars for inspectable collaboration.
- Configurable participants for
codex,claude,agy,codewhale,kimi, and custom adapters. /enable <agent>,/disable <agent>, and/agentsfor participant control.- Native attach mode for using an assistant's own TUI when
tmuxis available. - Read-only broadcast mode for comparing answers across assistants.
- Trust pins for command templates, binary paths, binary hashes, and elevated command surfaces.
- Packaged JSON Schemas under
councli.schemasfor protocol artifacts. - Graceful degradation when an assistant is missing, disabled, unauthenticated, or missing a configured model.
Platform support
councli is a pure Python CLI for Python 3.11+.
| Platform | Install | Core council turns | Native tmux attach |
|---|---|---|---|
| Linux | Supported | Supported | Supported with tmux |
| macOS | Supported | Supported | Supported with tmux |
| Windows | Supported | Supported with exec-mode agents | Use WSL for tmux |
| WSL | Supported | Supported | Supported with tmux |
Assistant availability depends on whether that assistant CLI is installed,
authenticated, configured, and on PATH in the same shell.
Install
Recommended install from PyPI:
pipx install councilroom-ai
councli --help
The PyPI distribution is councilroom-ai; the installed shell command is
councli.
Install from GitHub:
pipx install "git+https://github.com/mosesmrima/councli.git"
councli --help
Install from a local checkout:
git clone https://github.com/mosesmrima/councli.git
cd councli
pipx install .
councli --help
For Linux, macOS, Windows, WSL, shell completion, upgrade, and troubleshooting
details, see docs/INSTALL.md.
Quick start
From the project you want the assistants to inspect:
councli setup
councli doctor
councli
Inside the interactive shell:
/agents
/enable claude
what can you all do?
/deliberate compare sqlite and postgres for this app
/vote choose the transport: exec, tmux
/assistant codex
/quit
Normal prompts run a shared conversation turn. Slash commands opt into stronger coordination or local control-plane actions.
Development
git clone https://github.com/mosesmrima/councli.git
cd councli
uv sync
uv run pytest -q
uv build
For contribution guidance, see CONTRIBUTING.md. For build
and release details, see docs/PACKAGING.md.
Documentation map
docs/INSTALL.md: install on Linux, macOS, Windows, WSL.docs/PACKAGING.md: build, wheel checks, release steps.docs/ARCHITECTURE.md: high-level design.docs/PROTOCOL_DESIGN.md: shared-turn protocol, state machine, sidecars, and locking rules.docs/SECURITY_MODEL.md: command trust, artifact secrecy, elevated command risk, and hardening gates.docs/TERMINAL_SUBSTRATE.md: tmux, PTY, TUI, native sessions, and terminal capture boundaries.docs/ADAPTER_CONTRACT.md: adapter readiness, capability-aware routing, launch states, and response sidecars.docs/STATE_CONCURRENCY.md: events, blackboard projection, locking, crash recovery, and indexing.docs/RESEARCH_FINDINGS.md: consolidated research findings and implementation handoff.
Config
councli init writes .councli/config.yaml in the current project.
Assistant command and transport fields in that file are pinned in user-local councli state
($COUNCLI_STATE_HOME, $XDG_STATE_HOME/councli, or
~/.local/state/councli). The trust pin also records resolved binary paths and
executable hashes for enabled agents. If you edit command templates, binaries,
backend, enabled flags, broadcast flags, session names, or tmux input settings,
or if an installed assistant binary changes, review the file and run
councli trust before running assistant commands again. If a project was
intentionally moved or renamed, run councli trust --repair-identity after
reviewing the config. Use councli trust --dry-run to inspect command-field,
binary, and hash changes before accepting the current config.
Project-level fields include:
schema_version: current config schema marker, currentlycouncli.config.v1. Usecouncli config checkandcouncli config migrateto inspect or upgrade legacy configs.
Each agent has:
enabled: whether to consider it. Prefer/enable <agent>and/disable <agent>in the interactive shell for normal toggles; those commands update the config, refresh trust, and reload the current session.backend:execortmux.binary: executable name to find onPATH.display_name: optional human-readable adapter name.capabilities: optional intent list such aschat,deliberate,vote,broadcast, andassistant. Empty means infer support from configured commands.command_capabilities: what the normal prompt command may do, using values such asplanning_only,reads_workspace,writes_workspace,runs_tools,network_access, andfull_permission.broadcast_capabilities: capabilities forbroadcast_command. If omitted, legacy configs infer read-only behavior frombroadcast_read_only.start_capabilities/resume_capabilities: capabilities for native tmux start/resume commands.read_only_policy:safe_onlyby default forchat,deliberate,vote, and synthesis. Setallow_full_permissiononly when unsafe shared-turn routing is intentional.broadcast_policy:safe_onlyby default. Setallow_full_permissiononly when an unsafe broadcast fallback is intentional.version_command: optional lightweight version probe command.readiness_command: optional bounded, non-mutating probe for auth/model/quota readiness. Nonzero output is classified into statuses such asauth_required,model_unconfigured, orquota_unavailablewhen possible.sandbox_wrapper: optional argv prefix for exec-mode prompt commands, such as a localbwrap,firejail, orsystemd-runwrapper. It is prepended to the rendered assistant command and is a trusted command-bearing field.probe_timeout_seconds: timeout for version/probe commands.readiness_timeout_seconds: timeout for the readiness probe.command: argv template. Forexec,{prompt}is replaced with the generated prompt.broadcast_command: optional argv template for read-only broadcast/planning.broadcast_enabled: whether the agent can participate in broadcast.broadcast_read_only: legacy advisory field retained for old configs.broadcast_timeout_seconds: optional broadcast-specific timeout.resume_command: optional argv template where{session_id}is replaced by an imported native session id.session_name: tmux session name fortmuxbackend.start_command: command used to start the tmux session.done_marker: legacy base marker. Tmux runs use a unique per-turn marker to avoid stale scrollback.prompt_style:compactorverbatim. Usecompactby default for TUI safety.input_method:pasteortype. Usetypefor TUIs that keep bracketed paste in a draft composer.submit_keys: tmux keys used to submit after input, usually["Enter"].post_paste_delay_seconds: delay between input and submit.timeout_seconds: max run time for one prompt.
Consensus settings:
max_rounds: maximum implementation/review attempts before stopping.min_confidence: minimum0.0to1.0confidence for a vote or review to count toward majority. Low-confidence responses remain in the transcript and decision JSON, but they do not approve a plan or implementation.
Context packing settings:
peer_context_latest_rounds: number of prior rounds included in the prompt excerpt for a follow-up round.peer_context_per_participant_chars: maximum characters copied from one participant into the peer-context excerpt.peer_context_total_chars: maximum characters copied into the whole peer-context excerpt before councli points agents at the full blackboard.peer_context_include_failures:summary,full, oromitfor failed participant output in later-round prompts.
Native session settings:
tmux_socket: dedicated tmux socket name, defaultcouncli.detach_key: simple tmux key chord used to return from attached assistant sessions, defaultC-].raw_log_max_bytes: rotate raw pane recordings when they exceed this size on session start.raw_log_backups: number of rotated raw recordings to keep.session_prefix: prefix for project-scoped tmux session names.
Artifact hygiene settings:
prune_default_classes: artifact classes pruned by default, currently raw logs, session archives, and session snapshots.redact_patterns: regexes used bycouncli artifacts scrub.redact_replacement: replacement text for scrubbed secrets.scrub_max_file_bytes: skip larger files during scrub to avoid accidental expensive rewrites.
councli deliberately does not model each participant's native feature set.
Slash commands, @file mention syntax, MCP configuration, plugins, goals, and
tool-specific subagents remain native to Codex, Claude Code, AGY, Kimi, or
CodeWhale. The MVP coordination layer sends ordinary task/packet prompts and
records artifacts; after a council pass, the user can still enter any native
participant session and use that tool's full UI directly.
Example:
agents:
codex:
enabled: true
binary: codex
command: ["codex", "exec", "{prompt}"]
timeout_seconds: 900
If an agent is unavailable, councli records that and continues with the available agents.
During one interactive councli chat session, repeated auth/model/quota
failures are marked degraded and skipped on later turns until you restart the
session.
councli doctor --json emits per-intent readiness objects, so setup scripts can
distinguish ready, missing_binary, unsupported_intent, tmux_unavailable,
auth_required, model_unconfigured, quota_unavailable, and disabled
participants without scraping the table output.
Native tmux-backed sessions are supported for CLIs that behave better interactively:
agy:
enabled: true
backend: tmux
binary: agy
command: ["agy"]
session_name: councli-agy
start_command: ["agy", "--dangerously-skip-permissions"]
done_marker: "<<<COUNCLI_DONE:agy>>>"
prompt_style: compact
input_method: paste
submit_keys: ["Enter"]
post_paste_delay_seconds: 0.5
timeout_seconds: 900
Useful commands:
councli sessions list
councli sessions start agy
councli sessions attach agy
councli sessions capture agy
councli sessions stop agy --dry-run
councli sessions prune --dry-run
Run inspection commands:
councli status
councli show latest
councli show <run-id-prefix> --blackboard
councli verify latest
councli verify <run-id-prefix> --json
councli recover latest
councli recover <run-id-prefix> --json
councli artifacts list
councli artifacts scrub --dry-run
councli artifacts scrub --write
councli artifacts prune --older-than 30 --dry-run
councli artifacts prune --older-than 30 --delete
councli worktrees prune --status abandoned --dry-run
councli worktrees prune --status abandoned --delete
status lists recent run ids with task, participants, decision, review, and
implementation status when present. show reopens a run's durable state and
prints the paths to its blackboard, machine state, event log, and artifacts.
verify checks a run's event log, refs, response sidecars, and rebuildable
projections before you trust, export, or share the output.
recover rebuilds state.json and blackboard.md from the run's event log
and artifacts, then verifies the rebuilt projections.
security prints the trusted command surface, resolved binaries, version
metadata, and drift status without running agent prompts, so it can diagnose
trust failures that would block doctor. Use doctor --security when you want
the same security summary beside normal readiness checks.
artifacts scrub redacts common secret-looking tokens from text artifacts and
defaults to dry-run. artifacts prune removes old raw logs, session archives,
and snapshots by default, and only deletes when --delete is supplied.
artifacts export creates a redacted .tar.gz support bundle with a manifest.
It exports run/task/ledger/snapshot artifacts by default and excludes raw
terminal recordings unless you explicitly choose that artifact class.
worktrees prune finds councli-created implementation worktrees from run state.
It defaults to dry-run and only removes safe registered worktrees on councli/
branches under the expected .councli-worktrees/<repo> directory.
metrics derives local JSON or OpenMetrics-style counters from event logs,
participant response sidecars, and artifact sizes.
Interactive councli shell:
councli chat
Inside chat, type a normal prompt to run a shared conversation turn. councli
fans the prompt out to available assistants, records their responses on the
blackboard, synthesizes a single council answer, and returns to councli>.
Normal prompts do not force a fixed orient/propose/critique/revise/vote
lifecycle.
Terminology:
- A
councli chatsession is the interactive shell lifetime. - A turn is one user prompt inside that shell.
- A round is one fan-out pass to participants inside a turn.
Every new prompt starts a new turn, so seeing Round 1 multiple times in one
interactive session is expected.
Use explicit commands when you want stronger coordination:
/deliberate <prompt>asks participants to respond independently, then gives them a peer-aware second round before synthesis./vote <prompt>asks for explicit votes and records a decision artifact./assistant <name>attaches to a native assistant session./synthesizer <name>chooses which assistant writes the unified answer./agents,/enable <name>, and/disable <name>manage participants.
Local shell commands include /help, /doctor, /agents, /enable,
/disable, /status, /show, /sessions, /assistant <name>, /broadcast <prompt>, /brief [task], /synthesizer [name|auto|clear], /deliberate <task>, /vote <task>, and /quit. Unknown / commands are rejected
explicitly. To send a task that literally starts with /, prefix it as
//task.
/assistant codex attaches your terminal to Codex's native tmux session. Codex
owns the keyboard, slash commands, permission prompts, and UI exactly as if you
had launched it directly. Press Ctrl-] to detach back to councli. Raw pane
output is recorded under .councli/session-recordings/ for audit/debugging;
councli does not parse terminal screen output as the semantic source of truth.
Use native.detach_key in config to choose a different detach chord. If you are
already inside tmux, councli unsets $TMUX for the inner attach and uses its
dedicated tmux server.
/broadcast <prompt> and councli broadcast use configured non-interactive
commands where available. Broadcasts are meant for planning, critique,
comparison, and review, not concurrent edits in the same worktree. Broadcast
does not inject prompts into active tmux assistant sessions; it launches
headless subprocesses, records each participant result, and does not retry
failed participants. broadcast_command is preferred when configured. If it is
missing, councli may fall back to the normal prompt-capable command and
records that read-only enforcement was not explicit. If a tool is not
authenticated or lacks a configured model, that participant is recorded as a
runtime failure instead of blocking the rest.
Before council/broadcast runs, councli writes an inspectable task brief under
.councli/tasks/<run-id>/brief.md and copies it into the run directory. The
brief points at native sessions and recent councli events instead of silently
stuffing hidden history into prompts.
Use /brief or councli brief to print the latest brief and a pasteable
instruction for an attached assistant.
Tmux sessions are project-scoped by a hash of the project path and run under the
dedicated tmux -L councli server. .councli/project.json stores the project
identity so accidental project moves or copied .councli/ directories are
detected. If a session already exists but its pane is in another directory,
councli refuses to reuse it. sessions list reconciles the registry against
live tmux sessions, shows the pane's current command, and marks missing, dead,
shell-returned, or cwd-mismatched sessions stale.
sessions stop kills configured tmux-backed participant sessions. sessions prune kills configured councli tmux sessions plus visible councli-room-*
rooms, archiving captured pane text first by default under
.councli/session-archives/. Use --dry-run before cleanup when you want to
inspect the target list.
The council command is a compatibility entrypoint for an explicit shared
deliberation turn against available participants:
councli council -p codex -p agy "Decide the smallest safe plan"
It writes packet files, participant response sidecars, synthesis artifacts, and
a blackboard under .councli/runs/<run>/. The older fixed phase engine remains
hidden for development while the shared-turn protocol is hardened.
CodeWhale/DeepSeek is supported with the non-interactive command:
codewhale:
enabled: true
binary: codewhale
command: ["codewhale", "--yolo", "exec", "--auto", "{prompt}"]
timeout_seconds: 900
Kimi Code is supported with:
kimi:
enabled: true
binary: kimi
command: ["kimi", "--prompt", "{prompt}"]
timeout_seconds: 900
Current limits
This is v0. It now focuses the public surface on shared conversation,
deliberation, explicit voting, native attach, durable artifacts, and adapter
readiness. Hidden experimental worktree execution/review commands still exist
for development, but they are not the MVP path and require
COUNCLI_EXPERIMENTAL=1. Next steps are:
- Keep improving adapter-specific readiness probes where each CLI exposes a richer safe diagnostic command.
- Continue polishing the interactive prompt and consider a full-screen TUI only after the protocol proves useful in normal terminals.
- Decide whether to delete or separately package the hidden execution/review prototype.
See docs/ARCHITECTURE.md for the design and docs/ADAPTER_CONTRACT.md for the generic adapter contract. State and concurrency rules live in docs/STATE_CONCURRENCY.md. Participant-specific CLI notes live in docs/ADAPTERS.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file councilroom_ai-0.1.0.tar.gz.
File metadata
- Download URL: councilroom_ai-0.1.0.tar.gz
- Upload date:
- Size: 193.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3680c8b177a95c50255568fa4a895fd0f60cecaa296adf2cd85cc87f25bd0a5f
|
|
| MD5 |
2f9fb0dd55cbe9d1c0f7b4b434998914
|
|
| BLAKE2b-256 |
76d459bb1e09a90e5dc98ca57db0c7d7c75dbfbce4f27634f5deb94404d64b29
|
Provenance
The following attestation bundles were made for councilroom_ai-0.1.0.tar.gz:
Publisher:
publish.yml on mosesmrima/councli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
councilroom_ai-0.1.0.tar.gz -
Subject digest:
3680c8b177a95c50255568fa4a895fd0f60cecaa296adf2cd85cc87f25bd0a5f - Sigstore transparency entry: 1841491371
- Sigstore integration time:
-
Permalink:
mosesmrima/councli@843f7ed97692b87cfed44c47455a708a87717242 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mosesmrima
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@843f7ed97692b87cfed44c47455a708a87717242 -
Trigger Event:
release
-
Statement type:
File details
Details for the file councilroom_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: councilroom_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 104.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ad2a76895829fc51ed92ff5a2f54711799fed81595222e7382622dea0434103b
|
|
| MD5 |
fb490e14d162182769d98995fea3f40d
|
|
| BLAKE2b-256 |
754453294a882497f7664e1c9b560543c9032457d60103863c89882156522b46
|
Provenance
The following attestation bundles were made for councilroom_ai-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on mosesmrima/councli
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
councilroom_ai-0.1.0-py3-none-any.whl -
Subject digest:
ad2a76895829fc51ed92ff5a2f54711799fed81595222e7382622dea0434103b - Sigstore transparency entry: 1841491486
- Sigstore integration time:
-
Permalink:
mosesmrima/councli@843f7ed97692b87cfed44c47455a708a87717242 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/mosesmrima
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@843f7ed97692b87cfed44c47455a708a87717242 -
Trigger Event:
release
-
Statement type: