Skip to content
127 linesCodeBlameRaw
1# Channels
2
3People and agents talk in the same place the code lives. A workspace gets
4channels and direct messages, the way a team chat app has them, and every
5channel can be linked to a project so its pull requests, issues, checks and
6deploys arrive there as cards a person can act on. Agents are members of
7channels like anyone else.
8
9Design canvas: the "g1t Channels" artifact (v2 row is the target).
10
11## The point
12
13Today a person reads g1t in two places: g1t itself, and a chat app where
14the team talks about what g1t is doing. Links get pasted across, approvals
15wait in the wrong window, and an agent's question goes unseen. Channels put
16the talk next to the work, and make one thing true everywhere: a thread
17about a pull request *is* that pull request's conversation.
18
19## Product model
20
21- **Modes.** The shell gets a rail: Home, Code, Chat, Agents, Inbox. Code
22 keeps today's sidebar exactly. Chat has a sidebar of its own. Inbox is
23 shared by both. No mode's sidebar ever lists the other mode's things.
24- **Channel.** Belongs to a workspace. Public or private. Optionally linked
25 to one or more projects, and optionally to a team. Has members: people
26 and agents.
27- **Message.** Text by a person or an agent, or a card posted by g1t for an
28 event (pull request opened, checks failed, deployed, an agent asking for
29 approval).
30- **Thread.** Replies under a message. A card about an issue or pull
31 request opens that issue's or pull request's own timeline: replying there
32 is commenting on it. Other threads belong to the channel.
33- **Direct message.** A channel with no name, between two or more members,
34 any of whom may be agents.
35- **Project chat.** In Code mode, a project page shows a dock with only the
36 channels linked to that project.
37
38## Scaling the sidebar
39
40Workspaces will have hundreds of channels. The Chat sidebar never lists
41them all:
42
43- **Starred** first, chosen by the person.
44- **Active projects:** channels linked to projects the person worked on
45 this week, computed, not chosen.
46- **Teams:** one collapsed section per team the person is on, showing a
47 count and what is unread.
48- **Direct messages**, newest first.
49- **All / Unread / Mentions** filter, and a jump box. Everything else is
50 behind *Browse channels* and *Muted*.
51
52## How it fits what exists
53
54| Need | Already in g1t | What changes |
55| --- | --- | --- |
56| Live delivery | Durable Objects (runner, models) | One Durable Object per channel holds the open WebSockets, with hibernation. D1 keeps the messages. |
57| Cards for events | `services/events` bus and per-subscriber queues (`g1t_contracts::subscribers`) | `chat` subscribes to pull, issue, check run, deployment and agent run types, and posts a card in each linked channel. |
58| Mentions and unread | `services/events` inbox, threads and reasons | A message that mentions someone publishes `chat.message.created`; the inbox tells them with reason `mention`. Thread keys reuse `<repo_id>#<number>`. |
59| Steering an agent | `agent_messages` in `services/work` | `@agent` in a pull request's thread becomes a steering message on that pull request. |
60| One timeline | Issue and pull request timelines in `services/work` | The card's thread reads and writes that timeline. Chat stores only a pointer. |
61| Navigation | `workspace-nav.ts`, `shell.tsx` | A rail, a `mode` beside `SidebarKey`, and a Chat sidebar. |
62| Search | `services/search` | Index channel names and messages people can see. |
63
64## Data
65
66A new service, `services/chat` (TypeScript, like `services/projects`,
67because the Durable Object and WebSocket code is simplest there), with its
68own D1 database:
69
70- `channels`: id, workspace, name, kind (`channel` | `dm`), private, topic,
71 team_id, created_by, archived_at.
72- `channel_links`: channel_id, project_id. What makes a channel a
73 project's chat, and where cards go.
74- `channel_members`: channel_id, principal (person or agent), role,
75 starred, section, muted, last_read_id, joined_at.
76- `messages`: id (time-sortable), channel_id, author, kind (`text` |
77 `card`), body, card (JSON: subject key, state, actions), thread_root,
78 reply_count, edited_at, deleted_at.
79- `reactions`: message_id, principal, emoji.
80
81Unread counts come from `last_read_id` against the newest message id, kept
82in the channel's Durable Object, so the sidebar needs one read per
83section, not per channel.
84
85## Agents in channels
86
87- An agent is added to a channel like a person, with the agent's own
88 credentials, guardrails and audit log. Private channels exclude agents
89 unless added by name.
90- A mention in a pull request's thread steers that pull request's agent
91 (`agent_messages`). A mention anywhere else starts an agent run whose
92 replies post in the thread.
93- Asking a person for approval (merge past branch protection, deploy to
94 production) posts a card with the actions on it, and the same item lands
95 in the person's inbox. Acting in either place resolves both.
96
97## Build order
98
991. **Contracts.** Channel, message and card types in `packages/contracts`
100 and `crates/contracts`; the RPC methods; the new event types.
1012. **Channels.** `services/chat`, its migrations, a Durable Object per
102 channel, and `deploy/stack.jsonc` entries. Create, join, post, edit,
103 threads, reactions, read state.
1043. **Chat mode.** The rail in `shell.tsx`; the Chat sidebar with starred,
105 sections, filters and browse; the channel page; the composer with
106 mentions. Code mode is unchanged apart from the rail.
1074. **Mentions to the inbox.** `chat.message.created` and inbox rows with
108 reason `mention`.
1095. **Project links and cards.** Link a channel to a project; the events
110 subscriber; cards for pull requests, issues, checks and deploys; the
111 project chat dock in Code mode.
1126. **One timeline.** A card's thread is the issue's or pull request's
113 timeline, both ways, with "also send to channel".
1147. **Agents.** Agents as members, steering by mention, approval cards,
115 direct messages with agents.
1168. **Scale.** Team sections, computed active-project section, muting,
117 browse, search.
118
119Steps 1 to 4 are a usable chat; 5 and 6 are what no chat app can do.
120
121## Open questions
122
123- Must every channel belong to a project or team? Requiring one makes the
124 sidebar's sections better and orphans fewer channels.
125- Do agents get their own mode, or only appear as direct messages?
126- Retention and export for workspaces that need it.
127- Does a self-hosted install ship chat, or is it hosted only at first?