You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Okena is project-centric today: the sidebar lists projects, each project owns a layout of terminals, and a worktree is a child project. That model works well when one repo = one piece of work. It stops matching reality once the work is driven by agents: one task ("auth refactor") spans two or three repos, runs several agents at once or in sequence, and produces several worktrees and PRs. The user's question is no longer "what runs in project X" but "what am I working on, which of my agents needs me right now, and where is each task at".
This RFC proposes a mission-centric view layered on top of the current project model:
A mission is a unit of work with a lifecycle. It has a home project but can span any number of projects.
The fleet view shows all missions on one screen (or a wall monitor) as columns of live agent terminals — the same shape as today's project-column overview, with missions instead of projects.
An inbox lists everything that currently waits on the user, across missions, and lets them answer from there.
Motivation
Concrete pain today, with 8–15 agents running across ~10 projects:
Attention is per project, not per task. The sidebar's activity tiers (activity_order.rs: PINNED / NEEDS ATTENTION / RUNNING / RECENT, see Improve Projects Sidebar UX for Active vs Inactive Projects #120) tell me which repo has a bell, not which task is blocked and on what.
Cross-repo work has no home. A task touching webmaster and contember-oss is two unrelated worktree columns; the PRs live only in the browser; nothing ties them together or tells me when the task is done.
The overview does not scale to agents. Project columns are the right idea (live terminals, zoom on focus, Cmd+E to hide) but with agents most columns are idle most of the time and the interesting ones are spread across the strip.
Answering an agent means finding it first. A permission prompt or a design question sits in one terminal among many; the user has to locate it before they can react.
Proposal
1. Concepts
Project (exists)
Mission (new)
Answers
where — repo on disk, worktrees, shell, hooks, services
what and why — a unit of work with a goal and a status
Lifetime
long-lived
created → active → done → archived
Owns
terminals (PTY, persistence, daemon), layout
a cross-project layout that references terminals; a member list
worktrees, terminals and PRs from any projects (dynamic, mostly automatic)
Key decision: a mission does not own terminals. Terminals stay owned by their project/worktree exactly as today (cwd, PTY, daemon protocol, persistence untouched). A mission is a view over them. Membership is derived, not typed in:
a terminal started in a worktree that belongs to a mission → member;
a worktree created via the mission → member; branch names follow one convention shared across repos (mission/<slug>), so "add worktree in project X" is one action;
a PR opened for a mission branch (found by the GitHub extension) → member;
a mission with no worktree (a terminal in the main checkout) is a valid, cheap mission. Missions must be cheap to create or nobody creates them.
Note that today's "worktree = child project" is already a mission-lite (one task = one worktree). A mission generalises it to N worktrees in M projects plus PRs, and adds a status.
2. Data model (sketch, okena-state)
pubstructMissionData{pubid:String,pubtitle:String,pubgoal:String,// short markdownpubhome_project_id:String,pubcolor:FolderColor,pubstatus:MissionStatus,// Active | Blocked | Done | Archivedpubcreated_at:u64,publayout:Option<LayoutNode>,// cross-project: leaves reference terminal ids from any projectpubmembers:Vec<MissionMember>,// explicit members only; derived ones are computedpubtimeline:Vec<MissionEvent>,// worktree created, terminal started, PR opened/merged, CI failed…}pubenumMissionMember{Worktree{ project_id },Terminal{ terminal_id },Pr{ repo, number }}
Derived per render (not persisted): tier (attention | running | waiting | idle | done) from member agent states and PR states; the inbox; per-mission PR/CI status.
Where it lives: in WorkspaceData (daemon side), not only in the desktop client — the mobile client showing "who waits on me" and answering from the phone is probably the strongest single use case, and remote projects then work for free.
3. UI
Fleet view (replaces the project-column overview as the primary screen). Two densities:
Columns — direct analogue of today's project columns: one column per mission; header = color, title, home project, tier chip; body = the mission's live agent terminals stacked (each pane header shows project/branch because they are cross-project; a pane that needs the user has the border_bell frame and its Allow/Deny buttons inline); footer = PR chips with CI/review state and worktree chips (~dirty ↑ahead). Missions are ordered by tier with thin vertical tier separators. Click title / ⤢ = zoom into the mission board. Idle and done missions auto-collapse into a 30px vertical strip (title + agent state glyphs), click to expand; ⌘E collapses manually, like today's hide.
Cards — one compact card per mission (agents as one-line rows with state glyph, location, last message, sparkline; PRs; worktrees). For a wall monitor and for >15 missions.
Mission board (zoomed mission). Left rail: goal, status, members as a tree (project → worktree → terminals / PRs), timeline, + terminal, + worktree, mark done. Center: the mission's cross-project terminal layout (splits/tabs as today). Bottom context panel: diff of the focused terminal's worktree / PRs with checks / timeline.
Inbox (left rail, toggleable). One ordered list of things that wait on the user across all missions, longest-waiting first: agent permission prompts and questions, failed CI, PR conflicts. Each item can be acted on in place — Allow / Deny, answer 1/2, Re-run CI, "Fix with claude" (spawns an agent in that repo inside the mission). Enter jumps to the terminal or PR.
Navigation.⌘K becomes a mission switcher; the project switcher stays as a secondary. Projects becomes a settings/infra-level screen (repo, worktrees, which missions use them). Wall mode for a second monitor: hides inbox and chrome, keeps only attention/running columns.
4. Attention model (AgentSignal)
Today's signals — bell/OSC notification and foreground process — are too coarse for agents. Proposed extension API, per terminal:
Sources: Claude Code hooks (Notification, Stop, PermissionRequest) → okena signal --terminal $OKENA_TERMINAL_ID --state waiting-permission --msg "…" via the existing CLI; Codex analogously; OSC 133 prompt marks and OSC 9/777 as fallbacks. Ack = focusing the terminal (same semantics as today's unseen bell). Mission attention = max over member agents plus PR events (CI failed, conflicts, review requested) from the GitHub extension. This also gives #131 (desktop notification on attention) a proper source.
5. Lifecycle
create (title + home project, optionally a worktree right away) → members accrue mostly automatically → status derived (all PRs merged → offer Done) → Done triggers worktree cleanup (soft close exists) → Archived keeps timeline, PRs, token usage.
Incremental path
Not a rewrite. Each step is useful on its own:
Fleet view over today's data. No new type: treat each worktree child project as a mission-lite; add AgentSignal + inbox. Validates the control-panel screen and the attention model.
MissionData = folder + goal + status + auto-membership + PRs. Cross-project grouping already exists in FolderData; folders stay as static organisation ("where"), missions are the dynamic layer ("what").
Cross-project layout. The one real architectural change: LayoutNode leaves referencing terminals from several projects (terminal_id is already global in the registry; actions/rendering currently assume a project scope). Last, and only if step 1 shows that stacked panes per mission are not enough.
Open questions
Cross-project splits inside one mission — wanted, or are stacked/tabbed panes per worktree enough? (Decides whether step 3 exists.)
Missions in addition to folders, or replacing them?
Should a mission carry a "runbook" (an ordered list of commands that spawn terminals in sequence), or does orchestration stay in the agent tools and okena stays a multiplexer with signals? Proposal: start without it.
Column width: 400px per agent column truncates Claude Code output — is that acceptable in the overview, given zoom is one click away?
Where does membership live for remote projects (is_remote) — client-side view or daemon state? Proposal above: daemon.
Risks
Two mental models (project vs mission) → confusion. Mitigation: mission is the primary navigation; project is explicitly the infra level.
Missions become bureaucracy. Mitigation: automatic membership, missions without worktrees, one-key creation.
Auto-collapse hides something the user wanted to watch. Mitigation: pin/expand override persisted per window, like today's hidden_project_ids.
Summary
Okena is project-centric today: the sidebar lists projects, each project owns a layout of terminals, and a worktree is a child project. That model works well when one repo = one piece of work. It stops matching reality once the work is driven by agents: one task ("auth refactor") spans two or three repos, runs several agents at once or in sequence, and produces several worktrees and PRs. The user's question is no longer "what runs in project X" but "what am I working on, which of my agents needs me right now, and where is each task at".
This RFC proposes a mission-centric view layered on top of the current project model:
Motivation
Concrete pain today, with 8–15 agents running across ~10 projects:
activity_order.rs: PINNED / NEEDS ATTENTION / RUNNING / RECENT, see Improve Projects Sidebar UX for Active vs Inactive Projects #120) tell me which repo has a bell, not which task is blocked and on what.webmasterandcontember-ossis two unrelated worktree columns; the PRs live only in the browser; nothing ties them together or tells me when the task is done.Cmd+Eto hide) but with agents most columns are idle most of the time and the interesting ones are spread across the strip.Proposal
1. Concepts
FolderData { project_ids }(static, cross-project)Key decision: a mission does not own terminals. Terminals stay owned by their project/worktree exactly as today (cwd, PTY, daemon protocol, persistence untouched). A mission is a view over them. Membership is derived, not typed in:
mission/<slug>), so "add worktree in project X" is one action;Note that today's "worktree = child project" is already a mission-lite (one task = one worktree). A mission generalises it to N worktrees in M projects plus PRs, and adds a status.
2. Data model (sketch,
okena-state)Derived per render (not persisted): tier (
attention | running | waiting | idle | done) from member agent states and PR states; the inbox; per-mission PR/CI status.Where it lives: in
WorkspaceData(daemon side), not only in the desktop client — the mobile client showing "who waits on me" and answering from the phone is probably the strongest single use case, and remote projects then work for free.3. UI
Fleet view (replaces the project-column overview as the primary screen). Two densities:
project/branchbecause they are cross-project; a pane that needs the user has theborder_bellframe and its Allow/Deny buttons inline); footer = PR chips with CI/review state and worktree chips (~dirty ↑ahead). Missions are ordered by tier with thin vertical tier separators. Click title / ⤢ = zoom into the mission board. Idle and done missions auto-collapse into a 30px vertical strip (title + agent state glyphs), click to expand;⌘Ecollapses manually, like today's hide.Mission board (zoomed mission). Left rail: goal, status, members as a tree (project → worktree → terminals / PRs), timeline,
+ terminal,+ worktree,mark done. Center: the mission's cross-project terminal layout (splits/tabs as today). Bottom context panel: diff of the focused terminal's worktree / PRs with checks / timeline.Inbox (left rail, toggleable). One ordered list of things that wait on the user across all missions, longest-waiting first: agent permission prompts and questions, failed CI, PR conflicts. Each item can be acted on in place — Allow / Deny, answer 1/2, Re-run CI, "Fix with claude" (spawns an agent in that repo inside the mission). Enter jumps to the terminal or PR.
Navigation.
⌘Kbecomes a mission switcher; the project switcher stays as a secondary.Projectsbecomes a settings/infra-level screen (repo, worktrees, which missions use them). Wall mode for a second monitor: hides inbox and chrome, keeps only attention/running columns.4. Attention model (
AgentSignal)Today's signals — bell/OSC notification and foreground process — are too coarse for agents. Proposed extension API, per terminal:
Sources: Claude Code hooks (
Notification,Stop,PermissionRequest) →okena signal --terminal $OKENA_TERMINAL_ID --state waiting-permission --msg "…"via the existing CLI; Codex analogously; OSC 133 prompt marks and OSC 9/777 as fallbacks. Ack = focusing the terminal (same semantics as today's unseen bell). Mission attention = max over member agents plus PR events (CI failed, conflicts, review requested) from the GitHub extension. This also gives #131 (desktop notification on attention) a proper source.5. Lifecycle
create (title + home project, optionally a worktree right away) → members accrue mostly automatically → status derived (all PRs merged → offer Done) → Done triggers worktree cleanup (soft close exists) → Archived keeps timeline, PRs, token usage.
Incremental path
Not a rewrite. Each step is useful on its own:
AgentSignal+ inbox. Validates the control-panel screen and the attention model.MissionData= folder + goal + status + auto-membership + PRs. Cross-project grouping already exists inFolderData; folders stay as static organisation ("where"), missions are the dynamic layer ("what").LayoutNodeleaves referencing terminals from several projects (terminal_idis already global in the registry; actions/rendering currently assume a project scope). Last, and only if step 1 shows that stacked panes per mission are not enough.Open questions
is_remote) — client-side view or daemon state? Proposal above: daemon.Risks
hidden_project_ids.