Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
cbad163
feat: add docker agent board kanban TUI
dgageot Jul 3, 2026
f7f4cc2
fix(board): only treat a missing worktree as an empty diff
dgageot Jul 3, 2026
37a9eae
fix(board): require and normalize project paths
dgageot Jul 3, 2026
ddbb080
fix(board): keep cards visible when their column is removed
dgageot Jul 3, 2026
39d5c25
fix(board): serialize session relaunches
dgageot Jul 3, 2026
309715a
fix(board): move the private tmux socket into a per-user 0700 dir
dgageot Jul 3, 2026
b04e682
refactor(board): let dialogs provide their own init command
dgageot Jul 3, 2026
a75e33b
refactor(board): reuse the TUI's shared double-click threshold
dgageot Jul 3, 2026
31fcb14
feat(board): show a welcome overlay while the board is empty
dgageot Jul 3, 2026
942e1c6
feat(board): show the selected card's agent and branch in the footer
dgageot Jul 3, 2026
e57bf68
fix(board): keep the projects dialog cursor across add and delete
dgageot Jul 3, 2026
966f361
test(board): cover mouse hit-testing geometry
dgageot Jul 3, 2026
eb2a0ce
fix(board): sanitize untrusted strings rendered in the TUI
dgageot Jul 3, 2026
cb01c65
fix(board): never relaunch the session of a deleted card
dgageot Jul 3, 2026
3162923
fix(board): fail closed on an untrusted tmux socket directory
dgageot Jul 3, 2026
56e586e
feat(board): trim the default pipeline to Dev → Review → Push → Done
dgageot Jul 3, 2026
662b77c
feat(board): color cards by project
dgageot Jul 3, 2026
7dfe8a1
feat(board): insert newlines with cmd+enter in the new-card prompt
dgageot Jul 3, 2026
3171fd2
feat(board): roomier new-card dialog, hide single-project selector
dgageot Jul 3, 2026
1572ce3
feat(board): pick the project path with a directory browser
dgageot Jul 3, 2026
6ec6671
style(board): reuse the main TUI's dialog chrome
dgageot Jul 3, 2026
b6acaae
fix(board): actually composite dialogs over the board
dgageot Jul 3, 2026
c38ed12
feat(board): swap enter and cmd+enter in the new-card dialog
dgageot Jul 3, 2026
61cd1ba
perf(board): snapshot projects in the TUI model
dgageot Jul 3, 2026
e3f4ae1
feat(board): save the column prompt with cmd+enter
dgageot Jul 3, 2026
e77f452
feat(board): scroll columns with the mouse wheel
dgageot Jul 3, 2026
997c9eb
feat(board): show a busy indicator in column headers
dgageot Jul 3, 2026
392d6f2
feat(board): start the new-card dialog on the last used project
dgageot Jul 3, 2026
2fafd8a
feat(board): open the card's worktree in an editor with o
dgageot Jul 3, 2026
2851278
docs(board): document the editor key and mouse support
dgageot Jul 3, 2026
f2590bd
fix(board): sanitize project metadata rendered in dialogs
dgageot Jul 3, 2026
08c8bdb
fix(board): ignore wheel events outside the columns area
dgageot Jul 3, 2026
30535d3
fix(board): make diffs work in repositories without remotes
dgageot Jul 3, 2026
0ae00bd
feat(board): color project rows with their board accent
dgageot Jul 3, 2026
02269c5
feat(board): refresh the diff view with r
dgageot Jul 3, 2026
0560f10
test(board): cover the directory picker
dgageot Jul 3, 2026
28f4f70
feat(board): honor the main TUI's shortcut conventions
dgageot Jul 3, 2026
6e7a43b
feat(board): scrollbar and scroll percent in the diff dialog
dgageot Jul 3, 2026
88863dd
style(board): use the shared Yes/No confirmation keymap
dgageot Jul 3, 2026
25d9421
feat(board): support suspend like the main TUI
dgageot Jul 3, 2026
6111c46
style(board): render help rows like the main TUI's help dialog
dgageot Jul 3, 2026
7d2f49e
feat(board): reflect running agents in the window title
dgageot Jul 3, 2026
acc35a7
fix(board): don't queue attaches while one is in flight
dgageot Jul 3, 2026
e17d458
fix(board): cap the diff viewer at 1MB
dgageot Jul 3, 2026
c128adf
feat(board): jump to the first/last card with g/G (home/end)
dgageot Jul 3, 2026
8c4ba3c
fix(board): re-clamp the diff viewport offset after sizing
dgageot Jul 3, 2026
d3c3ffd
fix(board): remove the control-plane socket when a card is deleted
dgageot Jul 3, 2026
af54cbe
feat(board): allow only one board instance at a time
dgageot Jul 3, 2026
83c7f89
fix(board): fit the prompt editor to short terminals
dgageot Jul 3, 2026
be6bc00
fix(board): render emoji-less columns without a stray gap
dgageot Jul 3, 2026
1df9fad
fix(board): start agents with respawn-pane instead of send-keys
dgageot Jul 3, 2026
8f3cf44
feat(board): slide columns into view on narrow terminals
dgageot Jul 3, 2026
6938695
docs(board): add canonical front matter
dgageot Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions cmd/root/board.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package root

import (
"github.com/spf13/cobra"

boardtui "github.com/docker/docker-agent/pkg/board/tui"
"github.com/docker/docker-agent/pkg/telemetry"
)

// newBoardCmd creates the `docker agent board` command: a Kanban TUI that
// orchestrates one agent per card, each running in a tmux session on an
// isolated git worktree. Projects and column prompts are configured in the
// user's global config file, or from the TUI itself.
func newBoardCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "board",
Short: "Orchestrate agents on a Kanban board",
Long: `Board is a Kanban TUI for orchestrating agents. Each card launches an agent
in a tmux session on an isolated git worktree, and moving a card forward
through the pipeline (Dev → Review → Push → Done) sends the
destination column's prompt to its agent.

Projects and column prompts are stored in the global config file
(~/.config/cagent/config.yaml) and can be managed from the TUI.`,
Example: ` docker-agent board`,
Args: cobra.NoArgs,
GroupID: "core",
SilenceUsage: true,
RunE: func(cmd *cobra.Command, _ []string) error {
telemetry.TrackCommand(cmd.Context(), "board", nil)
applyTheme("")
return boardtui.Run(cmd.Context())
},
}
return cmd
}
1 change: 1 addition & 0 deletions cmd/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ We collect anonymous usage data to help improve docker agent. To disable:
newDebugCmd(),
newAliasCmd(),
newSandboxCmd(),
newBoardCmd(),
newServeCmd(),
newAskpassCmd(),
)
Expand Down
83 changes: 83 additions & 0 deletions docs/features/board/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: "Kanban Board"
description: "Orchestrate multiple agents from a Kanban TUI: each card runs an agent in a tmux session on an isolated git worktree."
keywords: docker agent, ai agents, features, board, kanban, orchestration
linkTitle: "Kanban Board"
weight: 15
canonical: https://docs.docker.com/ai/docker-agent/features/board/
---

_Board is a Kanban TUI for orchestrating agents. Each card launches an agent
in a tmux session on an isolated git worktree, and moving a card forward
through the pipeline sends the destination column's prompt to its agent._

## Launching the board

```bash
$ docker agent board
```

Requirements: `tmux` and `git` must be installed.

## How it works

- **Cards run agents.** Creating a card (`n`) launches `docker agent run` in
a dedicated tmux session, working in a fresh git worktree branched from the
project's upstream default branch. The card's title, running/idle status,
and failures are mirrored live from the agent's control plane.
- **Columns are a pipeline.** The default pipeline is
Dev → Review → Push → Done. Moving a card forward (`]`)
sends the destination column's prompt to the card's agent; moving it back
(`[`) sends nothing.
- **Attach anytime.** Press `enter` (or double-click a card) to attach your
terminal to the agent's session and interact with it directly; `ctrl+q`
detaches and returns to the board.
- **Everything is recoverable.** Quitting the board leaves agents running in
tmux; restarting it reattaches to them. If an agent process dies, the board
relaunches it and resumes the same conversation and worktree.

## Key bindings

| Key | Action |
| ------------- | --------------------------------------------------- |
| `n` | Create a card (project + prompt) |
| `enter` | Attach to the card's agent (`ctrl+q` detaches) |
| `d` | View the card's worktree diff |
| `o` | Open the card's worktree in `$BOARD_EDITOR` (`code`) |
| `[` / `]` | Move the card back / forward |
| `x` | Delete the card, its session, worktree, and branch |
| `p` | Manage projects |
| `e` | Edit the selected column's prompt |
| `←↓↑→` `hjkl` | Navigate |
| mouse | Click selects, double-click attaches, wheel scrolls |
| `?` | Help |
| `q` | Quit (agents keep running) |

## Configuration

Everything is configured in the global config file
(`~/.config/cagent/config.yaml`) or through the TUI itself (`p` for projects,
`e` for column prompts):

```yaml
board:
projects:
- name: my-app
path: /Users/me/src/my-app
agent: coder # any agent ref; defaults to the built-in agent
columns:
- id: dev
name: Dev
emoji: 🔨
- id: review
name: Review
emoji: 🔍
prompt: Review the local changes and fix any issues you find.
- id: done
name: Done
emoji: ✅
```

Omitting `columns` keeps the default pipeline. When a card enters a column
with a `prompt`, that prompt is delivered to the card's agent as its next
message.
Loading
Loading