Skip to content

Board — API reference

Columns

ALL_STATUSES module-attribute

ALL_STATUSES: tuple[str, ...] = (*BOARD_ORDER, ARCHIVED)

ARCHIVED module-attribute

ARCHIVED = 'archived'

BACKLOG module-attribute

BACKLOG = 'backlog'

BLOCKED_TAG module-attribute

BLOCKED_TAG = 'blocked'

BOARD_ORDER module-attribute

BOARD_ORDER: tuple[str, ...] = (
    BACKLOG,
    REFINED,
    IN_PROGRESS,
    IN_REVIEW,
    DONE,
)

DONE module-attribute

DONE = 'done'

IN_PROGRESS module-attribute

IN_PROGRESS = 'in_progress'

IN_REVIEW module-attribute

IN_REVIEW = 'in_review'

LABELS module-attribute

LABELS: dict[str, str] = {
    BACKLOG: "Backlog",
    REFINED: "Refined",
    IN_PROGRESS: "In Progress",
    IN_REVIEW: "In Review",
    DONE: "Done",
    ARCHIVED: "Archived",
}

REFINED module-attribute

REFINED = 'refined'

is_valid_status

is_valid_status(status: str) -> bool

Return True if status is one of the fixed columns.

label

label(status: str) -> str

Return the display label for a status (falls back to the raw value).

Database

connection

connection(db_path: Path | None = None)

Context manager that opens and closes a board database connection.

ensure_schema

ensure_schema(conn: Connection) -> None

Apply any pending migrations to the database.

Safe to call on every connection open — checks a single integer and returns immediately if the schema is current.

PARAMETER DESCRIPTION
conn

Open board database connection.

TYPE: Connection

get_connection

get_connection(db_path: Path | None = None) -> Connection

Open a board database connection.

The connection has WAL journal mode enabled (for concurrent reads), foreign-key enforcement enabled (so card_comments cascade-delete on ON DELETE CASCADE), and the current schema applied via migrations.

PARAMETER DESCRIPTION
db_path

Override the database path (defaults to {data_dir}/board.db).

TYPE: Path | None DEFAULT: None

RETURNS DESCRIPTION
Connection

A sqlite3.Connection ready for use. The caller must close it.

get_data_dir

get_data_dir() -> Path

Return the mait-code data directory, creating it if needed.

get_db_path

get_db_path() -> Path

Return the board database path.

get_project

get_project() -> str

Return the current project identifier (basename of git root or cwd).

Delegates to mait_code.context.get_project(), falling back to the current directory name.

Export

FORMATS module-attribute

FORMATS: tuple[str, ...] = (MARKDOWN, JSON)

JSON module-attribute

JSON = 'json'

MARKDOWN module-attribute

MARKDOWN = 'markdown'

board_markdown

board_markdown(
    cards: Iterable[dict], *, project: str | None = None
) -> str

Render a board listing as one markdown document grouped by column.

PARAMETER DESCRIPTION
cards

Card dicts (each optionally carrying comments).

TYPE: Iterable[dict]

project

Project name for the document title, or None for an all-projects export.

TYPE: str | None DEFAULT: None

RETURNS DESCRIPTION
str

The markdown document, without a trailing newline.

card_markdown

card_markdown(card: dict, *, level: int = 1) -> str

Render one card as a markdown document.

PARAMETER DESCRIPTION
card

A card dict as returned by :func:~mait_code.tools.board.service.get_card, optionally carrying a comments list.

TYPE: dict

level

Heading level for the card title; sections render at level + 1. Defaults to a standalone document (# title).

TYPE: int DEFAULT: 1

RETURNS DESCRIPTION
str

The markdown document, without a trailing newline.

export_board

export_board(
    conn: Connection,
    *,
    fmt: str = MARKDOWN,
    project: str | None = None,
    statuses: Iterable[str] | None = None,
    include_archived: bool = False,
    search: str | None = None,
) -> str

Export a board listing as fmt — a JSON array or one markdown document.

Filter arguments mirror :func:~mait_code.tools.board.service.list_cards.

RAISES DESCRIPTION
ValueError

If fmt is not one of :data:FORMATS.

export_card

export_card(
    conn: Connection, card_id: int, fmt: str = MARKDOWN
) -> str

Export one card, comments included, as fmt.

RAISES DESCRIPTION
CardNotFound

If no card has card_id.

ValueError

If fmt is not one of :data:FORMATS.

Service

CardNotFound

CardNotFound(card_id: int)

Bases: Exception

Raised by mutations when no card has the given id.

NotInProgress

NotInProgress(card_id: int, status: str)

Bases: Exception

Raised when binding a session to a card that isn't In Progress.

add_card

add_card(
    conn: Connection,
    *,
    project: str,
    title: str,
    description: str | None = None,
    priority: str = "medium",
    created_by: str | None = None,
) -> int

Insert a backlog card and return its new id.

created_by names the client that raised the card when it arrives from somewhere other than a local session (see :mod:mait_code.remote); None means it was created locally.

add_comment

add_comment(
    conn: Connection,
    card_id: int,
    body: str,
    *,
    author: str = "me",
) -> None

Append a comment to a card and bump its updated_at.

Raises :class:CardNotFound if the id is unknown.

add_tag

add_tag(conn: Connection, card_id: int, tag: str) -> None

Add a tag to a card (idempotent).

Raises :class:CardNotFound if the id is unknown.

archive_card

archive_card(conn: Connection, card_id: int) -> None

Archive a card (hide it from default views).

Releases the card's session bindings. Raises :class:CardNotFound if the id is unknown.

bind_session

bind_session(
    conn: Connection, card_id: int, session: SessionRef
) -> None

Bind a Claude Code session to an In Progress card.

Idempotent: re-binding the same session refreshes its pid and time. A card may carry several bindings (parallel sessions on one card). Raises :class:CardNotFound if the id is unknown and :class:NotInProgress unless the card is In Progress.

block_card

block_card(
    conn: Connection,
    card_id: int,
    *,
    reason: str | None = None,
) -> None

Tag a card blocked in place; record reason as a comment if given.

Blocking no longer moves the card — it keeps its real flow position and gains a :data:BLOCKED_TAG tag. Raises :class:CardNotFound if the id is unknown.

card_sessions

card_sessions(conn: Connection, card_id: int) -> list[dict]

Return a card's active session bindings (empty for an unknown id).

complete_card

complete_card(
    conn: Connection,
    card_id: int,
    *,
    summary: str | None = None,
) -> None

Move a card to done with an optional completion summary.

Releases the card's session bindings. Raises :class:CardNotFound if the id is unknown.

edit_card

edit_card(
    conn: Connection, card_id: int, **fields: str
) -> None

Update arbitrary card columns, bumping updated_at.

Pass column names as keyword arguments (e.g. title=.., acceptance_criteria=..). Raises :class:CardNotFound if the id is unknown; a no-op (no fields) is the caller's concern.

get_card

get_card(conn: Connection, card_id: int) -> dict | None

Return one card as a dict, or None if no card has that id.

get_comments

get_comments(conn: Connection, card_id: int) -> list[dict]

Return a card's comments in insertion order.

list_cards

list_cards(
    conn: Connection,
    *,
    project: str | None = None,
    statuses: Iterable[str] | None = None,
    include_archived: bool = False,
    tag: str | None = None,
    search: str | None = None,
    session: str | None = None,
) -> list[dict]

Return cards ordered priority-then-oldest.

PARAMETER DESCRIPTION
conn

Open board connection.

TYPE: Connection

project

Restrict to one project, or None for every project.

TYPE: str | None DEFAULT: None

statuses

Restrict to these statuses; None means "all". When given, it takes precedence over include_archived.

TYPE: Iterable[str] | None DEFAULT: None

include_archived

When no statuses filter is set, whether to include archived cards (default excludes them).

TYPE: bool DEFAULT: False

tag

Restrict to cards carrying this tag, or None for no tag filter.

TYPE: str | None DEFAULT: None

search

Restrict to cards whose title contains this substring, case-insensitively, or None for no title filter.

TYPE: str | None DEFAULT: None

session

Restrict to cards with an active binding to this Claude Code session id, or None for no session filter.

TYPE: str | None DEFAULT: None

list_projects

list_projects(conn: Connection) -> list[str]

Return the distinct project names on the board, sorted.

list_tags

list_tags(conn: Connection, card_id: int) -> list[str]

Return a card's tags, sorted.

move_card

move_card(
    conn: Connection,
    card_id: int,
    new_status: str,
    *,
    session: SessionRef | None = None,
) -> None

Move a card to new_status, maintaining the done- and session-invariants.

Entering done stamps completed_at; leaving it clears the stamp. Moving anywhere but in_progress releases the card's session bindings; moving to in_progress with a session binds it. Raises :class:CardNotFound if the id is unknown.

next_refined

next_refined(
    conn: Connection,
    project: str,
    *,
    claim: bool = False,
    session: SessionRef | None = None,
) -> dict | None

Return the top refined card for project (priority, then oldest).

With claim=True the card is moved to in_progress first (guarded on its status so a concurrent claim can't double-move it) and, given a session, bound to it. Returns None when the project has no refined cards.

refine_card

refine_card(
    conn: Connection,
    card_id: int,
    *,
    description: str | None = None,
    acceptance: str | None = None,
) -> None

Move a card to refined, optionally setting description/acceptance.

Releases the card's session bindings. Raises :class:CardNotFound if the id is unknown.

remove_card

remove_card(conn: Connection, card_id: int) -> None

Delete a card permanently (comments cascade).

Raises :class:CardNotFound if the id is unknown.

remove_tag

remove_tag(
    conn: Connection, card_id: int, tag: str
) -> None

Remove a tag from a card (no-op if the tag is absent).

Raises :class:CardNotFound if the id is unknown.

review_card

review_card(
    conn: Connection, card_id: int, *, pr: str | None = None
) -> None

Move a card to in_review, recording pr as a PR reference.

The card is parked between in_progress and done until its pull request merges. Re-reviewing with a PR the card already carries (e.g. after a re-push) doesn't duplicate the reference. Raises :class:CardNotFound if the id is unknown.

summary_counts

summary_counts(
    conn: Connection, *, project: str | None = None
) -> dict[str, int]

Return per-column card counts (excluding archived).

The result always has a key for every :data:BOARD_ORDER status, defaulting to 0. project=None counts across every project.

unbind_session

unbind_session(
    conn: Connection, card_id: int, session_id: str
) -> bool

Remove session_id's binding from a card.

Returns True if a binding was removed, False if there was none. Raises :class:CardNotFound if the id is unknown.

unblock_card

unblock_card(conn: Connection, card_id: int) -> None

Remove the blocked tag from a card (keeps its flow position).

Raises :class:CardNotFound if the id is unknown.

Sessions

SessionRef

Bases: NamedTuple

A Claude Code session: its id and the pid of the process serving it.

current_session

current_session() -> SessionRef | None

Return the session this process runs under, or None outside one.

Both variables must be present and the pid a positive integer; anything less is treated as "not in a Claude Code session" rather than guessed at.

Entry point

main

main()