Feature Reference
Maturity:
Depth:
Keyboard Shortcuts
Board Navigation
| Key | Action | Context |
|---|---|---|
q | Quit the application | Global |
Tab | Toggle focus between search box and board | Global |
Escape | Return to board from search / dismiss modal | Global |
Up | Navigate to previous task in column | Board |
Down | Navigate to next task in column | Board |
Left | Navigate to previous column | Board |
Right | Navigate to next column | Board |
Enter | Open task detail dialog | Board (focused card) |
r | Refresh board from disk | Board |
s | Sync task data with remote | Board |
O | Open board options/settings dialog | Board |
a | Switch base filter to All (show all tasks) | Board |
l | Switch base filter to Locked (busy tasks + context) | Board |
f | Switch base filter to Free (tasks ready to pick) | Board |
i | Switch base filter to In-Flight (action-grouped active work) | Board |
y | Switch base filter to By-Topic (per-anchor swimlanes) | Board |
z | Switch base filter to By-Trail (implementation-trail waves) | Board |
o | Choose the By-Topic lane sort order (opens a picker) | By-Topic view |
s | Choose which trail the view shows — re-scans, so a trail created since the board started is listed | By-Trail view |
r | Re-read task files from disk and redraw the trail | By-Trail view |
d | Re-check the trail’s freshness against live task state | By-Trail view (trail selected) |
R | Launch an agent to re-author the trail | By-Trail view (trail selected) |
S | Sync task data with remote, then redraw the trail | By-Trail view |
g | Toggle Git add-on (intersect with git-linked tasks) | Board |
t | Toggle Type add-on (intersect with selected issue types — opens picker dialog) | Board |
Task Operations
| Key | Action | Context |
|---|---|---|
Shift+Right | Move task to next column (skips collapsed) | Board (parent cards only) |
Shift+Left | Move task to previous column (skips collapsed) | Board (parent cards only) |
Shift+Up | Swap task with one above | Board (parent cards only) |
Shift+Down | Swap task with one below | Board (parent cards only) |
Ctrl+Up | Move task to top of column | Board (parent cards only) |
Ctrl+Down | Move task to bottom of column | Board (parent cards only) |
m | Move the marked task(s) — or the focused card — to a column | Board (parent cards only; hidden in In-Flight, By-Topic and By-Trail views) |
n | Create a new task | Board |
x | Toggle expand/collapse child tasks | Board (parent or child card) |
x | Expand / collapse the focused task group | Board (focused group header) |
Space | Mark / unmark the focused task (☑ / ☐) | Board (parent cards only; hidden in In-Flight, By-Topic and By-Trail views) |
c | Commit focused modified task | Board (shown when task is modified) |
C | Commit all modified tasks | Board (shown when any task is modified; hidden in By-Trail view) |
p | Pick the focused task (start implementation) | Board (context-dependent — shown when task is pickable) |
T | Create an implementation trail from the focused task | Board (hidden in In-Flight and By-Trail views) |
w | Draft a work report from selected columns | Board (context-dependent — column-scoped; hidden in In-Flight, By-Topic and By-Trail views) |
b | Launch brainstorm for the focused task | Board (context-dependent — shown when task is brainstormable) |
g | Resume the focused In-Flight task directly | In-Flight row |
s | Sign off a pending human gate | In-Flight row with pending human gate |
f | Fail a pending human gate | In-Flight row with pending human gate |
Column Operations
| Key | Action | Context |
|---|---|---|
e | Open the column management dialog (add, edit, delete, reorder, merge) | Board (not In-Flight / By-Topic / By-Trail) |
Shift+Up | Move the focused column one position up (left on the board) | Column management dialog |
Shift+Down | Move the focused column one position down (right on the board) | Column management dialog |
Enter | Edit the focused column | Column management dialog |
Ctrl+Right | Move column one position right | Board |
Ctrl+Left | Move column one position left | Board |
X (Shift+X) | Toggle collapse/expand for focused card’s column | Board (focused card) |
Ctrl+Backslash | Open command palette | Global |
Click ▼ / ▶ | Toggle column collapse/expand | Column header |
Click ✎ | Open column edit dialog | Column header |
Modal Navigation
| Key | Action | Context |
|---|---|---|
Up | Focus previous field | Inside modal dialogs |
Down | Focus next field | Inside modal dialogs |
Left | Cycle to previous option | On CycleField |
Right | Cycle to next option | On CycleField |
Enter | Activate focused button / navigate to linked task | Inside modal dialogs |
Escape | Close the dialog | Inside modal dialogs |
Task Card Anatomy
┌─────────────────────────────────┐ ← Border color = priority
│ ▲ ☐ t47 * playlists support │ ← Follow-up glyph (only on follow-up tasks), mark (☑ marked / ☐ unmarked), task number (cyan), * if modified (orange), title (bold)
│ 💪 medium | 🏷️ ui,api | GH | PR:GH | @alice │ ← Effort, labels, issue/PR indicator, contributor
│ 🔒 alice@example.com │ ← Lock indicator (if locked)
│ 🚫 blocked | 👤 alice │ ← Status/blocked, assigned to
│ 🔗 t12, t15 │ ← Blocking dependency links
│ 📎 folded into t42 │ ← Folded indicator (if applicable)
│ 👶 3 children │ ← Child task count (if parent)
└─────────────────────────────────┘
Not all lines are shown on every card — lines only appear when the corresponding data exists.
Group Header Anatomy
Tasks that share a boardgroup slug are drawn under a group header row inside their column:
▾ perf work (3) · 2 match · ▲2 ◈1
│ │ │ │ └─ Follow-up roll-up: a per-kind tally of the members' glyphs
│ │ │ └────────- Match count — only during a filter pass
│ │ └─────────────────- Member count
│ └────────────────────────────- Group title, humanized from the slug (perf_work → perf work)
└──────────────────────────────- ▾ expanded / ▸ collapsed
A group of a single member draws no header — it renders as a plain card, while keeping its slug. See How to Group Tasks in a Column.
Priority Color Coding
| Priority | Border Color |
|---|---|
| High | Red |
| Medium | Yellow |
| Low / Normal | Gray |
The focused card always shows a double cyan border, regardless of priority.
Follow-up Provenance Glyphs
A task carrying a followup_kind — one that was auto-spawned by a workflow seam rather than created as new work — shows a coloured glyph at the start of its card:
| Glyph | Follow-up kind | Color |
|---|---|---|
◇ | Manual verification | Cyan |
▲ | Risk mitigation | Yellow |
▼ | Upstream defect | Red |
✗ | Verification failure | Red |
↻ | Carry-over | Cyan |
◐ | QA test gap | Magenta |
◈ | Review finding | Magenta |
▤ | Docs gap | Gray |
· | Unrecognized kind | None |
Reading the glyphs:
- An ordinary task draws nothing — no glyph and no blank placeholder, so cards for genuine new work are unchanged.
- A task whose
followup_kindis not one of the known kinds still renders, as the uncoloured·, rather than being dropped. - A group header rolls up its members’ kinds as a per-kind tally (
▲2 ◈1), in the order of the table above with unrecognized kinds last. A collapsed group mounts no member cards, so the header is the only place that provenance can surface. - A trail ghost card carries no glyph by design — a ghost is a referenced task with no local file, so there is nothing to classify.
ait ls and the pick flow surface the same provenance in text form — see Task Management.
Issue Platform Indicators
The board detects the issue tracking platform from the URL hostname:
| Platform | Indicator | Color |
|---|---|---|
GitHub (github in hostname) | GH | Blue |
GitLab (gitlab in hostname) | GL | Orange (#e24329) |
Bitbucket (bitbucket in hostname) | BB | Blue |
| Other | Issue | Blue |
PR Platform Indicators
Tasks created from pull requests (via ait pr-import) display a pull request indicator on the task card info line:
| Platform | Indicator | Color |
|---|---|---|
GitHub (github in hostname) | PR:GH | Green |
GitLab (gitlab in hostname) | MR:GL | Orange (#e24329) |
Bitbucket (bitbucket in hostname) | PR:BB | Blue |
| Other | PR | Green |
GitLab uses “MR” (Merge Request) terminology, which the indicator reflects.
View Filters
The View Selector widget at the top-left of the filter area renders as:
[a All | l Locked | f Free | i In-Flight | y By-Topic | z By-Trail] g Git t Type
It splits filtering into a base radio (mutually exclusive — exactly one is always active) and two independent add-on toggles. The active base and any active toggle are highlighted in bold cyan; inactive segments are dimmed. All filters compose with text search using AND logic.
Base filters (radio)
| Base | Key | Selector Label | Shows |
|---|---|---|---|
| All | a | a All | All tasks (default) |
| Locked | l | l Locked | Busy tasks: status Implementing or present in the lock list. When a child is busy, also includes its parent and all sibling children (context grouping). |
| Free | f | f Free | Tasks that are ready to pick: neither Implementing nor locked. Parents are hidden when any of their children is busy. |
| In-Flight | i | i In-Flight | Active Implementing tasks grouped by next required action: Needs your action, Agent can continue, and Blocked. |
| By-Topic | y | y By-Topic | Tasks clustered into per-anchor swimlanes by their topic key (anchor, else a child’s parent topic, else own id). A topic with two or more tasks gets its own lane (labelled by the root task); lone tasks collapse into one Ungrouped lane. |
| By-Trail | z | z By-Trail | The members of one implementation trail, laid out as wave columns (W1 · …). Each card carries its classification, confidence, and any drift marker; Enter opens the full narrative. Press s to choose which trail is shown. |
Pressing the key for the currently active base is a no-op. Locked and Free are leaf-level inverses (Locked ∪ Free = All, Locked ∩ Free = ∅) — the Locked view additionally includes parent/sibling cards as context.
By-Topic lanes: The By-Topic view uses the task’s anchor field when set;
otherwise a child falls back to its parent topic and a standalone task falls
back to its own id. If the root task is archived or not currently loaded, the
anchor id still remains the stable lane key. Topics with only one visible task
are collected in the trailing Ungrouped lane. See Topic anchoring for creation flags, inheritance rules, and when to use anchors instead of parent-child tasks or dependencies.
By-Topic lane sort order: Lanes are ordered most-recently-touched first by
default. In the By-Topic view, press o to open a picker and choose the lane
sort mode:
| Mode | Orders lanes by |
|---|---|
| Recency (default) | newest member’s updated_at / created_at, newest first |
| Topic id | root topic id, newest (highest) id first |
| Size | number of tasks in the lane, largest first |
| Alphabetical | lane label, case-insensitive |
The Ungrouped lane stays pinned last in every mode. The choice persists per-user (in your local board settings), so it survives restarts without affecting teammates.
By-Trail
An implementation trail is a durable, wave-structured record of how a group
of tasks should be sequenced, with the evidence behind that ordering. Trails are
created and re-authored by the /aitask-trail skill — on the board, focus a task
in any other view and press T to start one. The By-Trail view is a read-only
projection of a stored trail: it never writes the trail itself.
Press z to enter the view and s to choose which trail it shows. Each wave
becomes a column headed W1 · <title>, and each card shows the member’s
classification glyph, its confidence, its task status, and any drift marker.
Enter opens the full narrative for that member. Members that are not live
tasks in this repository — cross-repo members, archived tasks, and tasks that
have gone missing — appear as read-only ghost cards.
Keeping the view current. Five keys refresh different things, at very different costs:
| Key | Refreshes | Cost |
|---|---|---|
r | Re-reads task files from disk and redraws the stored trail | Instant — no subprocess |
s | Re-scans task files for trails, including any created since the board started | A second or two — one artifact read per trail |
d | Re-checks the stored trail against live task state (freshness) | About half a second |
S | Runs ait sync, then redraws | A full remote sync |
R | Launches an agent to re-author the trail itself | Minutes |
Reach for r when a task’s status changed on this machine — it is free. Reach
for s when a new trail was created since the board started: the scan reads
task files from disk, so the new trail is listed without restarting the board
(leaving and re-entering the view with z re-scans too). Reach
for S when the change was made elsewhere: task data lives on the aitask-data
branch, so a status set by another machine or a remote agent only arrives in this
checkout through a sync. Use d to re-check drift without re-authoring anything;
it never modifies the stored trail. R is the heavyweight option — it hands the
trail to an agent, which rewrites it. After a refresh is launched, the view
watches for the new version and reloads on its own when it lands, giving up after
about half an hour.
If the scan cannot read one of your task files — a task being rewritten at that
exact moment, or a malformed one — the view says so and leaves the trail list
alone rather than reporting that there are no trails. Press s again.
Drift markers. A trail records what it knew when it was written. When a member’s live state no longer matches that snapshot, the card shows an amber marker:
⚠ status_changed: status 'Ready' -> 'Implementing'
Up to two reasons are shown per card, with (+N more) when there are others; the
complete list is in the detail screen. Common reasons are status_changed,
task_completed, task_archived, task_folded, task_deleted,
dependency_changed, gate_state_changed, and plan_changed. Drift is a signal
that the trail’s sequencing advice may be out of date — R re-authors it.
Keys that behave differently here. The footer relabels itself per view, so it always shows what the keys actually do. In By-Trail it reads:
r Refresh R Agent Refresh d Freshness s Select Trail S Sync
C (commit all modified tasks) is hidden in this view. A trail is a reading
projection rather than a set of tasks you own, while “commit all” acts on every
modified task in the repository — so the key is withheld rather than silently
doing something wider than the view suggests. T, w, and the card-move keys
are hidden for the same reason.
Add-on filters (toggle)
| Add-on | Key | Selector Label | Shows |
|---|---|---|---|
| Git | g | g Git | Restricts the visible set to tasks with issue or pull_request metadata. |
| Type | t | t Type | Restricts the visible set to tasks whose issue_type is in the persisted selection. Turning the toggle on always opens the type-picker dialog so the selection can be reconfirmed or edited; turning it off requires no dialog. |
Add-ons compose with the active base. Example: l + g shows busy tasks linked to an issue/PR; f + t (with bug selected) shows free bug tasks ready to pick.
Locked view auto-expansion: When the base filter switches to Locked, parent tasks that have at least one busy child are automatically expanded (their child cards are displayed). When switching away, these auto-expanded parents are collapsed back unless they were manually expanded before entering the view.
Column Configuration
Columns are stored in aitasks/metadata/board_config.json:
{
"columns": [
{"id": "now", "title": "Now", "color": "#FF5555"},
{"id": "next", "title": "Next Week", "color": "#50FA7B"},
{"id": "backlog", "title": "Backlog", "color": "#BD93F9"}
],
"column_order": ["now", "next", "backlog"],
"settings": {
"auto_refresh_minutes": 0,
"sync_on_refresh": false
}
}
- id — Unique identifier (auto-generated from title on creation)
- title — Display name (can include emojis)
- color — Hex color code for the column header and border
- column_order — Controls left-to-right display order
- settings.auto_refresh_minutes — Interval in minutes for periodic board refresh (0 to disable, default 0)
- settings.sync_on_refresh — Enable automatic sync with remote on each auto-refresh interval (default false). Requires
.aitask-dataworktree (data branch mode). When enabled, the board subtitle shows “+ sync” - settings.collapsed_columns — List of column IDs that are currently collapsed (default: empty). Collapsed columns show only their title and task count in a narrow strip. Tasks in collapsed columns are not rendered, which improves performance for boards with many tasks
The “Unsorted / Inbox” column is a special dynamic column (ID: unordered) that appears automatically when tasks exist without a boardcol assignment.
Color Palette
When adding or editing a column, you can choose from 8 predefined colors:
| Color | Hex Code | Name |
|---|---|---|
| ● | #FF5555 | Red |
| ● | #FFB86C | Orange |
| ● | #F1FA8C | Yellow |
| ● | #50FA7B | Green |
| ● | #8BE9FD | Cyan |
| ● | #BD93F9 | Purple |
| ● | #FF79C6 | Pink |
| ● | #6272A4 | Gray |
Task Metadata Fields
The board reads and displays the following frontmatter fields from task files:
| Field | Type | Editable from Board | Description |
|---|---|---|---|
priority | string | Yes (cycle) | low, medium, or high |
effort | string | Yes (cycle) | low, medium, or high |
risk_code_health | string | Yes (cycle) | low, medium, or high — shown only when set by the risk-evaluation planning step; read-only for Done/Folded tasks |
risk_goal_achievement | string | Yes (cycle) | low, medium, or high — shown only when set by the risk-evaluation planning step; read-only for Done/Folded tasks |
status | string | Yes (cycle) | Ready, Editing, Implementing, Postponed, Done, Folded |
issue_type | string | Yes (cycle) | Loaded from task_types.txt (defaults: bug, chore, documentation, enhancement, feature, performance, refactor, style, test) |
labels | list | Read-only | Tag list, displayed comma-separated |
depends | list | Read-only* | Task IDs this task depends on. *Can remove stale references. |
assigned_to | string | Read-only | Person assigned to the task |
issue | string | Read-only | URL to external issue tracker |
pull_request | string | Read-only | URL to external pull request / merge request (set by ait pr-import) |
contributor | string | Read-only | PR author username, displayed as @username on the card |
contributor_email | string | Read-only | PR author email (shown in detail dialog) |
implemented_with | string | Read-only | Code agent and model used to implement the task (e.g., claudecode/opus4_6) |
created_at | string | Read-only | Creation timestamp (YYYY-MM-DD HH:MM) |
updated_at | string | Auto-updated | Updated automatically on save |
children_to_implement | list | Read-only | Child task IDs for parent tasks |
folded_tasks | list | Read-only | Task IDs that were merged into this task |
folded_into | string | Read-only | Task ID this task was folded into |
anchor | string | Yes | Topic root used by the By-Topic view. Empty means the task is its own topic root. |
file_references | list | Read-only | Pointers to source files / line ranges (e.g., foo.py:10-20). Pressing Enter on a focused row opens ait codebrowser at the referenced location. See Creating Tasks from Code. |
boardcol | string | Auto-managed | Column ID (set by board operations) |
boardidx | integer | Auto-managed | Sort index within column (set by board operations) |
boardgroup | string | Auto-managed | Group slug within the column (see Group Header Anatomy) |
Board Data Fields
Three metadata fields are managed internally by the board:
boardcol— The column ID where the task is placed (e.g.,"now","backlog","unordered"). Tasks without this field appear in the “Unsorted / Inbox” column.boardgroup— The group slug within the column. The slug is the group’s identity — there is no group registry, no group ID and no stored title — so two spellings are two different groups, andait update --boardgrouprejects a slug outside[a-z0-9_]+rather than normalizing one into the other. An explicit""means “deliberately ungrouped”, which is not the same as the field being absent.boardidx— The sort index within a column. Lower values appear higher; ties are broken by filename. Values are widely spaced rather than consecutive, and may be negative — a movement writes only the moved task’s file, placing it in the gap between its new neighbours rather than renumbering the column. Only the relative order is meaningful. When repeated moves into the same position exhaust a gap, that single column is re-spaced automatically.
These fields are always written last in the frontmatter and are updated using a reload-and-save mechanism that prevents overwriting other metadata fields changed externally.
Lock Status Display
Lock information is not stored in task files – it is fetched from the remote aitask-locks branch via aitask_lock.sh --list and maintained in memory as a lock map. The board refreshes the lock map on startup, on every manual/auto refresh, and after lock/unlock operations.
| Display Location | Locked | Unlocked |
|---|---|---|
| Task card | 🔒 user@example.com (additional line) | No lock line shown |
| Task detail | 🔒 Locked: user@co on hostname since timestamp | 🔓 Lock: Unlocked (dimmed) |
Locks older than 24 hours show a (may be stale) warning in the detail view.
Button states in detail dialog:
| Button | Enabled when | Disabled when |
|---|---|---|
| 🔒 Lock | Task is unlocked AND status is not Done/Folded AND not read-only | Task is already locked, or Done/Folded/read-only |
| 🔓 Unlock | Task is locked | Task is not locked |
For details on the underlying lock mechanism, see the ait lock command reference.
Modal Dialogs Reference
| Dialog | Trigger | Purpose |
|---|---|---|
| Task Detail | Enter on card / double-click | View/edit task metadata, lock status, pull request link, contributor info, and content; access Pick, Lock, Unlock, Save, Revert, Edit, Delete, Close buttons |
| Column Manage | e / command palette “Manage Columns” | List every column with its position, color, ID and task count; Add, Edit, Delete and Merge buttons, Enter to edit and Shift+Up/Shift+Down to reorder |
| Column Edit | Command palette “Add/Edit Column” / click ✎ in column header / Add or Edit in Column Manage | Set column title and color |
| Column Select | Command palette “Edit/Delete/Collapse/Expand Column” | Pick which column to act on |
| Column Multi-Select (Merge from) | “Merge” in Column Manage / command palette “Merge Columns” | Pick one or more source columns to merge (Unsorted / Inbox is offered only when it holds tasks) |
| Column Select (Merge into) | Confirming the merge sources | Pick the destination column (the chosen sources are omitted; Unsorted / Inbox is offered unless it is a source) |
| Merge Confirm | Confirming the destination | Names the source columns, the destination, and how many tasks will move |
| Move Tasks to Column | m with tasks marked / command palette “Move Tasks to Column” | Review which marked tasks will move, in board order, before a destination is chosen |
| Column Select (Move to) | Confirming the review, or m on a single focused card | Pick the destination column (collapsed columns and the column the whole selection already occupies are omitted) |
| Delete Column Confirm | After selecting column to delete | Confirm column deletion; warns about task count |
| Commit Message | c or C key | Enter commit message for modified task(s) |
| Delete Confirm | “Delete” button in task detail | Confirm task deletion; lists all files to be removed |
| Dependency Picker | Enter on Depends field (multiple deps) | Select which dependency to open |
| Remove Dep Confirm | Enter on missing dependency | Offer to remove stale dependency reference |
| Child Picker | Enter on Children field (multiple children) | Select which child task to open |
| Folded Task Picker | Enter on Folded Tasks field (multiple) | Select which folded task to view (read-only) |
| Lock Email | “🔒 Lock” button in task detail | Enter email for lock ownership; confirms to acquire lock via aitask_lock.sh |
| Unlock Confirm | “🔓 Unlock” button (when lock belongs to different user) | Shows lock details (who, where, when); offers “Force Unlock” or “Cancel” |
| Sync Conflict | Sync detects merge conflicts | Shows conflicted files; offers “Resolve Interactively” (opens terminal) or “Dismiss” |
| Settings | O key / command palette “Options” | Configure board settings (auto-refresh interval, sync on refresh) |
Git Integration Details
The board auto-detects whether task data lives on a separate aitask-data branch (via the .aitask-data/ worktree) or on the current branch (legacy mode). All git operations are routed through a worktree-aware helper, so the board works transparently in both modes.
Modified file detection:
The board queries git status --porcelain -- aitasks/ on startup and after each refresh to identify modified .md files. Modified tasks show an orange asterisk (*) next to their task number. In branch mode, this targets the aitask-data worktree automatically.
Commit workflow:
- Selected files are staged with
git add <filepath> - A commit is created with the user-provided message
- The board refreshes git status after commit
In branch mode, commits target the aitask-data branch, not the main code branch.
Revert workflow:
Runs git checkout -- <filepath> to discard local changes and restore the last committed version.
Delete workflow:
- Files are removed with
git rm -f <filepath>(falls back toos.removefor untracked files) - Empty child task/plan directories are cleaned up
- An automatic commit is created: “Delete task t
and associated files”
Configuration Files
| File | Format | Purpose |
|---|---|---|
aitasks/metadata/board_config.json | JSON | Board column definitions, order, and settings (auto-refresh) |
aitasks/metadata/board_config.local.json | JSON | User-local view state: which columns and which groups you have collapsed |
aitasks/metadata/task_types.txt | Text (one per line) | Valid issue types for the Type cycle field |
These files are auto-created with defaults if they don’t exist. The .local.json layer is yours alone — collapsing a column or a group changes only your view, never a teammate’s.
Environment Variables
| Variable | Default | Purpose |
|---|---|---|
EDITOR | nano (Linux/macOS), notepad (Windows) | External editor opened by the “Edit” button |
TERMINAL | Auto-detected | Terminal emulator for “New Task” and “Pick” actions |
PYTHON | python3 | Python interpreter (used by launcher if shared venv is unavailable) |
Terminal auto-detection order: $TERMINAL, then x-terminal-emulator, xdg-terminal-exec, gnome-terminal, konsole, xfce4-terminal, lxterminal, mate-terminal, xterm. If none found, the board suspends to run commands in the current terminal.
Next: Monitor — the dashboard of every pane in your tmux session.