You are working on opensessions, an agent-agnostic, mux-agnostic terminal session manager.
opensessions/
├── apps/
│ ├── server/ # @opensessions/server — bootstrap entrypoint for the Bun server
│ └── tui/ # @opensessions/tui — OpenTUI terminal sidebar (Solid)
│ ├── src/
│ │ └── index.tsx # Main TUI app
│ ├── scripts/
│ │ └── start.sh # Canonical sidebar launcher used by mux providers
│ ├── build.ts # Bun build with Solid plugin
│ └── bunfig.toml # Required: preload for Solid JSX transform
├── integrations/
│ └── tmux-plugin/ # tmux-facing scripts and host integration glue
├── packages/
│ ├── runtime/ # @opensessions/runtime — runtime, watcher logic, config, plugins, server internals
│ │ ├── src/
│ │ │ ├── contracts/ # AgentEvent, AgentStatus, AgentWatcher, MuxProvider, MuxSessionInfo
│ │ │ ├── agents/ # AgentTracker (state management for agent events)
│ │ │ │ └── watchers/ # Built-in agent watchers
│ │ │ │ ├── amp.ts
│ │ │ │ ├── claude-code.ts
│ │ │ │ ├── codex.ts
│ │ │ │ └── opencode.ts
│ │ │ ├── mux/ # Mux registry and detection helpers
│ │ │ ├── server/ # WebSocket server internals and launcher
│ │ │ ├── shared.ts # Shared types, constants, palette
│ │ │ └── index.ts # Barrel export
│ │ └── test/ # Tests (bun:test)
│ └── mux/
│ ├── contract/ # @opensessions/mux — mux contracts and capability guards
│ ├── providers/
│ │ ├── tmux/ # @opensessions/mux-tmux — tmux provider
│ │ └── zellij/ # @opensessions/mux-zellij — experimental zellij provider
│ └── tmux-sdk/ # @opensessions/tmux-sdk — lower-level tmux command wrapper
├── CONTRACTS.md # Agent integration guide (Amp, Claude Code, OpenCode, Aider)
├── turbo.json # Turborepo config
├── opensessions.tmux # Root TPM entrypoint
└── package.json # Bun workspace root
- Monorepo: Turborepo + Bun workspaces, with
apps/for runnable entrypoints andpackages/for reusable libraries. - Built-in agent watchers: Core ships with
AmpAgentWatcher,ClaudeCodeAgentWatcher,CodexAgentWatcher, andOpenCodeAgentWatcherthat watch agent data directories directly. External agents integrate via theAgentWatcherplugin interface. - Mux-agnostic:
MuxProviderinterface abstracts all mux operations.TmuxProvideris the reference implementation. - MuxProvider is SYNC: All methods use
Bun.spawnSync— matches the existing pattern and keeps the server simple. - Auto-detect mux:
detectMux()checks$TMUX,$ZELLIJ_SESSION_NAMEenv vars. Config file override planned. - TDD: All contracts and tracker logic have tests. Use
bun testinpackages/runtime/.
{ agent: string, session: string, status: AgentStatus, ts: number, threadId?: string, threadName?: string, unseen?: number }AgentStatus = "running" | "idle" | "done" | "error" | "waiting" | "interrupted"
interface MuxProvider {
name: string;
listSessions(): MuxSessionInfo[]; // {name, createdAt, dir, windows}[]
switchSession(name, clientTty?): void;
getCurrentSession(): string | null;
getSessionDir(name): string;
getPaneCount(name): number;
getClientTty(): string;
setupHooks(host, port): void;
cleanupHooks(): void;
}interface AgentWatcher {
name: string;
watch(callback: (event: AgentEvent) => void): void;
stop(): void;
}- Runtime: Bun (not Node)
- Language: TypeScript (strict)
- TUI: OpenTUI with Solid reconciler (
@opentui/solid,@opentui/core,solid-js) - Tests:
bun:test— run withbun testinpackages/runtime/ - Build:
@opentui/solid/bun-pluginfor TUI builds
- TDD: Red-green-refactor, vertical slices, one test at a time. Tests verify behavior through public interfaces.
- Sync mux calls: MuxProvider methods are synchronous. Don't make them async.
- Preserve optimizations: Batched tmux calls, 5s git cache with HEAD watchers, lightweight focus-only broadcasts.
- Sidebar resize work: Before changing sidebar spawning, width sync, tmux resize handling, or
sidebar-coordinator, readdocs/explanation/sidebar-behavior.mdand preserve those invariants unless you update the doc in the same change. - Built-in watchers in runtime: Amp, Claude Code, Codex, and OpenCode have built-in watchers in
packages/runtime/src/agents/watchers/. Community agents use theAgentWatcherplugin interface. - OpenTUI Solid: JSX needs
bunfig.tomlpreload andjsxImportSource: "@opentui/solid"in tsconfig. Build needssolidPlugin. - Never call
process.exit()directly in TUI: Userenderer.destroy().
bun install # Install all workspace deps
bun test # Run all tests (from root via turbo)
cd packages/runtime && bun test # Run runtime tests directly
cd apps/tui && bun run start # Start TUI (requires tmux)
cd apps/tui && bun run build # Build TUI for distribution
cd apps/server && bun run start # Start the server bootstrap directly- Create a new package under
packages/mux/providers/<your-mux>/ - Implement the
MuxProviderinterface - Register it from the server bootstrap in
apps/server/src/main.tsif it should be built in - Add tests in the provider package or
packages/runtime/test/at the highest useful layer - Export the provider from its package entrypoint
- Create
packages/runtime/src/agents/watchers/your-agent.ts - Implement the
AgentWatcherinterface - Register via
PluginAPI.registerWatcher()in your plugin - Add tests in
packages/runtime/test/ - See
CONTRACTS.mdfor integration examples