How Coodeen Works
Processes, data flow, and where state lives.
Overview
Coodeen is a native macOS app (SwiftUI with AppKit bridges) around the opencode agent. On launch it spawns the bundled opencode serve --hostname=127.0.0.1 --port=0 as a child process and talks to it over HTTP.
Processes
- Coodeen app (
apps/macos): supervises the opencode sidecar and handles the filesystem, git, terminal (SwiftTerm), web preview (WKWebView), and the SwiftUI interface. - opencode sidecar: child process that owns the agent, sessions, messages, tool execution, and provider auth.
Data Flow
- A view calls into
OpencodeAPI(sessions, prompts, providers) or a local service (files, git, actions). OpencodeClientsends the HTTP request to the sidecar, scoped to the project directory.- opencode streams events (
message.part.updated, tool call lifecycle, status) over/global/event(SSE). EventBusdecodes each event and hands it toChatStore, which updates the chat view model.
The event bus runs in a reconnect loop with a 15s heartbeat and exponential backoff (0.5s → 5s).
What's Stored Where
| What | Location |
|---|---|
| Sessions, messages, tool history | opencode — ~/.local/share/opencode/ |
| Provider API keys | opencode — ~/.local/share/opencode/auth.json |
| Per-session model and preview URL | App support folder, session-prefs.json |
| Last selected model | App support folder, app-config.json |
The app support folder is ~/Library/Application Support/Coodeen/. On first launch, existing preferences from the previous Electron build are copied over automatically.
Directory Scoping
Every opencode call is pinned to a specific project directory. Coodeen sets both x-opencode-directory (URL-encoded) as a header and directory as a query param, so POSTs and GETs both hit the right instance. Switching sessions switches the scope.
Open Source
Code on GitHub. Contributions welcome.