Feature Reference

Keyboard shortcuts, configuration, and technical details

Keyboard Shortcuts

Board Navigation

KeyActionContext
qQuit the applicationGlobal
TabToggle focus between search box and boardGlobal
EscapeReturn to board from search / dismiss modalGlobal
UpNavigate to previous task in columnBoard
DownNavigate to next task in columnBoard
LeftNavigate to previous columnBoard
RightNavigate to next columnBoard
EnterOpen task detail dialogBoard (focused card)
rRefresh board from diskBoard
sSync task data with remoteBoard
OOpen board options/settings dialogBoard
aSwitch base filter to All (show all tasks)Board
lSwitch base filter to Locked (busy tasks + context)Board
fSwitch base filter to Free (tasks ready to pick)Board
iSwitch base filter to In-Flight (action-grouped active work)Board
ySwitch base filter to By-Topic (per-anchor swimlanes)Board
zSwitch base filter to By-Trail (implementation-trail waves)Board
oChoose the By-Topic lane sort order (opens a picker)By-Topic view
sChoose which trail the view shows — re-scans, so a trail created since the board started is listedBy-Trail view
rRe-read task files from disk and redraw the trailBy-Trail view
dRe-check the trail’s freshness against live task stateBy-Trail view (trail selected)
RLaunch an agent to re-author the trailBy-Trail view (trail selected)
SSync task data with remote, then redraw the trailBy-Trail view
gToggle Git add-on (intersect with git-linked tasks)Board
tToggle Type add-on (intersect with selected issue types — opens picker dialog)Board

Task Operations

KeyActionContext
Shift+RightMove task to next column (skips collapsed)Board (parent cards only)
Shift+LeftMove task to previous column (skips collapsed)Board (parent cards only)
Shift+UpSwap task with one aboveBoard (parent cards only)
Shift+DownSwap task with one belowBoard (parent cards only)
Ctrl+UpMove task to top of columnBoard (parent cards only)
Ctrl+DownMove task to bottom of columnBoard (parent cards only)
mMove the marked task(s) — or the focused card — to a columnBoard (parent cards only; hidden in In-Flight, By-Topic and By-Trail views)
nCreate a new taskBoard
xToggle expand/collapse child tasksBoard (parent or child card)
xExpand / collapse the focused task groupBoard (focused group header)
SpaceMark / unmark the focused task ( / )Board (parent cards only; hidden in In-Flight, By-Topic and By-Trail views)
cCommit focused modified taskBoard (shown when task is modified)
CCommit all modified tasksBoard (shown when any task is modified; hidden in By-Trail view)
pPick the focused task (start implementation)Board (context-dependent — shown when task is pickable)
TCreate an implementation trail from the focused taskBoard (hidden in In-Flight and By-Trail views)
wDraft a work report from selected columnsBoard (context-dependent — column-scoped; hidden in In-Flight, By-Topic and By-Trail views)
bLaunch brainstorm for the focused taskBoard (context-dependent — shown when task is brainstormable)
gResume the focused In-Flight task directlyIn-Flight row
sSign off a pending human gateIn-Flight row with pending human gate
fFail a pending human gateIn-Flight row with pending human gate

Column Operations

KeyActionContext
eOpen the column management dialog (add, edit, delete, reorder, merge)Board (not In-Flight / By-Topic / By-Trail)
Shift+UpMove the focused column one position up (left on the board)Column management dialog
Shift+DownMove the focused column one position down (right on the board)Column management dialog
EnterEdit the focused columnColumn management dialog
Ctrl+RightMove column one position rightBoard
Ctrl+LeftMove column one position leftBoard
X (Shift+X)Toggle collapse/expand for focused card’s columnBoard (focused card)
Ctrl+BackslashOpen command paletteGlobal
Click / Toggle column collapse/expandColumn header
Click Open column edit dialogColumn header
KeyActionContext
UpFocus previous fieldInside modal dialogs
DownFocus next fieldInside modal dialogs
LeftCycle to previous optionOn CycleField
RightCycle to next optionOn CycleField
EnterActivate focused button / navigate to linked taskInside modal dialogs
EscapeClose the dialogInside 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

PriorityBorder Color
HighRed
MediumYellow
Low / NormalGray

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:

GlyphFollow-up kindColor
Manual verificationCyan
Risk mitigationYellow
Upstream defectRed
Verification failureRed
Carry-overCyan
QA test gapMagenta
Review findingMagenta
Docs gapGray
·Unrecognized kindNone

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_kind is 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:

PlatformIndicatorColor
GitHub (github in hostname)GHBlue
GitLab (gitlab in hostname)GLOrange (#e24329)
Bitbucket (bitbucket in hostname)BBBlue
OtherIssueBlue

PR Platform Indicators

Tasks created from pull requests (via ait pr-import) display a pull request indicator on the task card info line:

PlatformIndicatorColor
GitHub (github in hostname)PR:GHGreen
GitLab (gitlab in hostname)MR:GLOrange (#e24329)
Bitbucket (bitbucket in hostname)PR:BBBlue
OtherPRGreen

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)

BaseKeySelector LabelShows
Allaa AllAll tasks (default)
Lockedll LockedBusy tasks: status Implementing or present in the lock list. When a child is busy, also includes its parent and all sibling children (context grouping).
Freeff FreeTasks that are ready to pick: neither Implementing nor locked. Parents are hidden when any of their children is busy.
In-Flightii In-FlightActive Implementing tasks grouped by next required action: Needs your action, Agent can continue, and Blocked.
By-Topicyy By-TopicTasks 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-Trailzz By-TrailThe 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:

ModeOrders lanes by
Recency (default)newest member’s updated_at / created_at, newest first
Topic idroot topic id, newest (highest) id first
Sizenumber of tasks in the lane, largest first
Alphabeticallane 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:

KeyRefreshesCost
rRe-reads task files from disk and redraws the stored trailInstant — no subprocess
sRe-scans task files for trails, including any created since the board startedA second or two — one artifact read per trail
dRe-checks the stored trail against live task state (freshness)About half a second
SRuns ait sync, then redrawsA full remote sync
RLaunches an agent to re-author the trail itselfMinutes

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-onKeySelector LabelShows
Gitgg GitRestricts the visible set to tasks with issue or pull_request metadata.
Typett TypeRestricts 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-data worktree (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:

ColorHex CodeName
#FF5555Red
#FFB86COrange
#F1FA8CYellow
#50FA7BGreen
#8BE9FDCyan
#BD93F9Purple
#FF79C6Pink
#6272A4Gray

Task Metadata Fields

The board reads and displays the following frontmatter fields from task files:

FieldTypeEditable from BoardDescription
prioritystringYes (cycle)low, medium, or high
effortstringYes (cycle)low, medium, or high
risk_code_healthstringYes (cycle)low, medium, or high — shown only when set by the risk-evaluation planning step; read-only for Done/Folded tasks
risk_goal_achievementstringYes (cycle)low, medium, or high — shown only when set by the risk-evaluation planning step; read-only for Done/Folded tasks
statusstringYes (cycle)Ready, Editing, Implementing, Postponed, Done, Folded
issue_typestringYes (cycle)Loaded from task_types.txt (defaults: bug, chore, documentation, enhancement, feature, performance, refactor, style, test)
labelslistRead-onlyTag list, displayed comma-separated
dependslistRead-only*Task IDs this task depends on. *Can remove stale references.
assigned_tostringRead-onlyPerson assigned to the task
issuestringRead-onlyURL to external issue tracker
pull_requeststringRead-onlyURL to external pull request / merge request (set by ait pr-import)
contributorstringRead-onlyPR author username, displayed as @username on the card
contributor_emailstringRead-onlyPR author email (shown in detail dialog)
implemented_withstringRead-onlyCode agent and model used to implement the task (e.g., claudecode/opus4_6)
created_atstringRead-onlyCreation timestamp (YYYY-MM-DD HH:MM)
updated_atstringAuto-updatedUpdated automatically on save
children_to_implementlistRead-onlyChild task IDs for parent tasks
folded_taskslistRead-onlyTask IDs that were merged into this task
folded_intostringRead-onlyTask ID this task was folded into
anchorstringYesTopic root used by the By-Topic view. Empty means the task is its own topic root.
file_referenceslistRead-onlyPointers 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.
boardcolstringAuto-managedColumn ID (set by board operations)
boardidxintegerAuto-managedSort index within column (set by board operations)
boardgroupstringAuto-managedGroup 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, and ait update --boardgroup rejects 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 LocationLockedUnlocked
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:

ButtonEnabled whenDisabled when
🔒 LockTask is unlocked AND status is not Done/Folded AND not read-onlyTask is already locked, or Done/Folded/read-only
🔓 UnlockTask is lockedTask is not locked

For details on the underlying lock mechanism, see the ait lock command reference.

DialogTriggerPurpose
Task DetailEnter on card / double-clickView/edit task metadata, lock status, pull request link, contributor info, and content; access Pick, Lock, Unlock, Save, Revert, Edit, Delete, Close buttons
Column Managee / 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 EditCommand palette “Add/Edit Column” / click in column header / Add or Edit in Column ManageSet column title and color
Column SelectCommand 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 sourcesPick the destination column (the chosen sources are omitted; Unsorted / Inbox is offered unless it is a source)
Merge ConfirmConfirming the destinationNames the source columns, the destination, and how many tasks will move
Move Tasks to Columnm 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 cardPick the destination column (collapsed columns and the column the whole selection already occupies are omitted)
Delete Column ConfirmAfter selecting column to deleteConfirm column deletion; warns about task count
Commit Messagec or C keyEnter commit message for modified task(s)
Delete Confirm“Delete” button in task detailConfirm task deletion; lists all files to be removed
Dependency PickerEnter on Depends field (multiple deps)Select which dependency to open
Remove Dep ConfirmEnter on missing dependencyOffer to remove stale dependency reference
Child PickerEnter on Children field (multiple children)Select which child task to open
Folded Task PickerEnter on Folded Tasks field (multiple)Select which folded task to view (read-only)
Lock Email“🔒 Lock” button in task detailEnter 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 ConflictSync detects merge conflictsShows conflicted files; offers “Resolve Interactively” (opens terminal) or “Dismiss”
SettingsO 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:

  1. Selected files are staged with git add <filepath>
  2. A commit is created with the user-provided message
  3. 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:

  1. Files are removed with git rm -f <filepath> (falls back to os.remove for untracked files)
  2. Empty child task/plan directories are cleaned up
  3. An automatic commit is created: “Delete task t and associated files”

Configuration Files

FileFormatPurpose
aitasks/metadata/board_config.jsonJSONBoard column definitions, order, and settings (auto-refresh)
aitasks/metadata/board_config.local.jsonJSONUser-local view state: which columns and which groups you have collapsed
aitasks/metadata/task_types.txtText (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

VariableDefaultPurpose
EDITORnano (Linux/macOS), notepad (Windows)External editor opened by the “Edit” button
TERMINALAuto-detectedTerminal emulator for “New Task” and “Pick” actions
PYTHONpython3Python 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.