Skip to content

About

Claude Code, Codex and Kimi Code in one conversation, on your own subscription logins. A native macOS app, with verdict runs that ask every member and score the consensus.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Open Council

Open Council: three AI agents and you in one conversation

Claude Code, Codex and Kimi Code in one conversation, signed in the way you already sign in. Each member is a real interactive terminal running on your own subscription, so there's no API key to supply and nothing billed per token. They all read and write the same chat log, which is how they answer you and answer each other.

You type, everyone sees it. @codex addresses one of them. A reply budget stops them talking to each other forever. Say "wrap it up" and they each post a closing position.

There's a second mode for when you want opinions rather than a conversation: a verdict asks every member the same question separately, then a moderator merges the answers and scores how much they actually agreed.

Open Council is a macOS app. It grew out of a terminal version that runs the same chats in herdr panes, and that still works: see docs/cli.md.

This is a beta, and you build it yourself. There's no signed download yet. Read Known limitations before you start.

What you need

macOS 15 or later, and at least one agent CLI that you're already logged into. Versions this was built and tested against:

Member Command Tested at Notes
Claude Code claude 2.1.269
Codex codex codex-cli 0.154.0
Kimi Code kimi 0.42.0 App only. The terminal version can't host it
pi pi 0.85.1 Runs an OpenRouter model with the same file and shell tools. Needs an API key, kept in pi's own config, and isn't in the shipped roster (see permissions)

Newer versions will usually be fine. When one isn't, it tends to show up as a member that starts and then sits there, because these CLIs are driven through their hooks and their terminal output.

To build, you need Xcode and brew install xcodegen. Python 3.11 or later has to be on your PATH as well: the members talk to the chat by running a small Python wrapper called council, so it's needed at runtime and not just at build time.

Install

git clone https://github.com/alisorcorp/opencouncil.git
cd opencouncil
./install.sh

install.sh writes ~/.local/bin/council pointing back at this folder, so leave the folder where you put it. Your chats and verdict runs are saved inside it, under chats/ and runs/, and they're gitignored. If you move the folder later, run the script again.

It also lists the agent CLIs it can find, and mentions prompt_toolkit and herdr if they're missing. Both of those are only for the terminal version, so ignore them if you're here for the app.

Then build the app:

app/build.sh install

That builds Release and puts Council.app in /Applications. Use app/build.sh run instead if you'd rather build Debug and just open it.

One thing worth doing before you build: copy app/signing.local.example to app/signing.local and put your own Apple Development certificate in it. Without one the build is signed ad-hoc, which works fine but gives the app a fresh identity every time you rebuild, and macOS ties permissions to that identity. You'll be asked for Documents access again after every build. The example file explains where to find the certificate.

Your first chat

Open the app and press ⌘N. You'll be asked for three things: a name, the folder the members work in, and which members are at the table. The roster comes from council.toml, which is created with defaults the first time council runs.

Pick the folder carefully. Members read and edit files there, so point them at a project you actually want them working on, not your home directory.

Type a message and press Return. The members start on their first message, which takes a few seconds while each CLI comes up. Click a member in the sidebar to watch its terminal directly, which is also where you'll answer anything it asks you.

⇧⌘N runs a verdict instead: a question, who answers, who moderates, and how many rounds.

What members are allowed to do

Members get file and shell tools in the folder you chose. What they can do without stopping to ask you is set per member in council.toml, and the shipped defaults ask before anything risky:

Member Starts with Which means
Claude Code --permission-mode acceptEdits --allowedTools WebSearch WebFetch Takes its file edits, looks things up, asks before running commands
Codex --sandbox workspace-write -a on-request Writes stay inside your folder, asks when it wants more
Kimi Code --yolo Kimi's asking mode. Routine edits run, risky things ask

Kimi names those backwards from everyone else, which is worth knowing before you edit anything: --yolo is the careful one and --auto is the mode that never asks.

Claude Code and Codex can both look things up without asking. Codex always could and Claude Code couldn't, so any question with a fact in it would stop Claude mid-round for permission while Codex went off and checked. Reading a page doesn't touch your files or run anything, so it isn't what the asking is for.

When a member does stop to ask, it shows as "needs attention" in the sidebar with a card naming what it wants, and it waits. Click through to its terminal and answer there. The app never answers these for you.

If you'd rather a member never stopped, give it its CLI's own flag in council.toml: --dangerously-skip-permissions for Claude Code, --yolo for Codex, --auto for Kimi. That's how Open Council shipped until September 2026, and it's a reasonable thing to want in a scratch directory. It's a bad default for a stranger's first conversation, which is why it isn't one any more.

pi is the exception, and it's why no pi member is in the shipped roster. pi has no permission system at all. Its own README says so and points you at a container instead, and Council's pi extension only reports what pi already did, so there's no flag that would make a pi member ask and no way for the app to show one waiting. The deepseek member is still defined in council.toml and still listed in the new-chat sheet, just unticked. Tick it and it edits files and runs commands as you, without a prompt. That's fine in a scratch directory and a bad surprise anywhere else, so run pi in a container if you want a boundary. The one place this doesn't apply is council ask from the terminal, which runs pi with --no-tools.

Known limitations

Codex stops on a trust dialog the first time it runs in a folder. It asks whether it trusts the directory, and it won't start until someone answers. The app raises a card telling you which member is waiting, and you answer in that member's terminal. Claude Code does the same in a folder it hasn't seen. There's a config override that's supposed to pre-approve this, and it doesn't work: tested against codex-cli 0.154.0, the dialog appears anyway. Answering it once per folder is enough, since Codex remembers.

It still freezes sometimes. The app can stop responding for a few seconds while replies are arriving. Two of those were sampled and the time went on SwiftUI resolving the text layout of every message at once, so a fix for that shipped in September and it is rarer now. It is not gone: one turned up on 17 September five messages into a conversation, which also killed the theory that it fires at a predictable size. The app comes back on its own and nothing is lost.

Every launch watches itself for this, so if it happens to you there is a stack waiting in ~/Library/Logs/Council named for the minute it started. Sending me that file is the most useful thing anyone can do about this. The watchdog pings the main thread four times a second and does nothing else until one of those pings goes unanswered for a second and a half; set COUNCIL_WATCHDOG=0 if you would rather it didn't.

No signed download. Distributing a built app needs a Developer ID certificate and notarization, which this project doesn't have yet. Building from source is the only route.

Ad-hoc builds re-ask for permissions. Covered above under Install. That's what unsigned builds do on macOS, so there's nothing to report.

Xcode 27 beta is what this is built with. build.sh picks it up automatically through DEVELOPER_DIR when it's installed, so xcode-select doesn't need changing. Released Xcode hasn't been tested.

One router per chat. The app and the terminal version both take a lock on a chat while they're driving it, and each will refuse a chat the other holds, naming the holder.

How it works, and hacking on it

app/CouncilCore is a SwiftPM library holding the logic (config, the chat log, sessions, events, launch plans) with its own tests. app/Council is the SwiftUI app. Everything the app writes is in the same format the CLI reads, so you can open a chat in either.

docs/internals.md covers how members are launched and supervised, how to run the whole delivery chain against scripted stand-ins without spending any model quota, and the design details.

app/build.sh test    # 250 CouncilCore tests and 51 app tests

Licence

MIT. See LICENSE.

The app is set in Figtree, bundled under the SIL Open Font License in app/Resources/Fonts with its licence text.

About

Claude Code, Codex and Kimi Code in one conversation, on your own subscription logins. A native macOS app, with verdict runs that ask every member and score the consensus.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages