Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data format

Board layout

The default file backend stores the board below .pinto/ in the repository where pinto is run. The directory contains the configuration, individual PBI Markdown files, Sprint data, templates, and the issued_ids history. Each PBI is a separate file so that a Git diff shows the change to one item clearly.

The board is local-first: no account, server, or database service is required. File and Git backends are the plain-text compatibility boundary: their PBI and Sprint records remain human-readable and a Git diff can show each operation. SQLite is the explicit persistence exception. It exposes the same pinto operations through an opt-in, normalized database, but its versioned schema and migration rules replace the per-record text diff.

PBI files

A PBI file combines TOML frontmatter with a Markdown body:

+++
id = "T-1"
title = "Implement the parser"
status = "todo"
rank = "i"
created = "2026-01-01T00:00:00Z"
updated = "2026-01-01T00:00:00Z"
+++

Acceptance criteria and planning notes belong here.

The frontmatter carries structured fields such as the ID, title, status, rank, labels, relations, timestamps, and optional Sprint information. The body is user-authored Markdown and is preserved when the display locale changes.

An action PBI promoted from a Sprint Retro or Review has one additional machine-readable source link:

[source]
kind = "review"
sprint_id = "S-1"

kind is retro or review, and sprint_id identifies the parent Sprint and the corresponding child record. The link does not introduce another PBI or child-record state; the PBI’s normal status remains authoritative.

The filename stem is part of the record identity: tasks/T-1.md and archive/T-1.md must both contain id = "T-1". File reads validate active and archived items, as well as Sprint filenames, and stop on filename mismatches or duplicate logical IDs before a write or migration can overwrite existing data.

Statuses must be columns in the configured workflow. The rank is a fractional index used to keep ordering changes small. Completion and start timestamps are recorded when a PBI crosses the configured workflow boundaries.

Sprint files

A Sprint uses the same TOML-frontmatter/Markdown-body shape under .pinto/sprints/. Its title, state, planned dates, capacity settings, and timestamps are structured fields; its goal is the Markdown body. goal_achieved = true or goal_achieved = false records the explicit boolean retrospective result in frontmatter; a recorded result always accompanies a non-blank Goal, and writing a blank Goal clears the result. When the field is omitted, the Goal is unevaluated. Closing a Sprint writes closed_at plus spillover_points, spillover_items, and unestimated_spillover_items. Zero spillover values and an unset close time are omitted before close. These fields preserve retrospective context after unfinished PBIs are rolled over or released, while velocity continues to count completed work only.

Sprint Retro files

A Sprint Retro is stored separately under .pinto/retro/ as .pinto/retro/<SPRINT-ID>.md. Its ID is the parent Sprint ID, so the file name and the id frontmatter field must match. The body is free-form Markdown and the frontmatter records id, created, and updated:

+++
id = "S-1"
created = "2026-07-29T00:00:00Z"
updated = "2026-07-29T00:00:00Z"
+++

## What went well

The file and Git backends keep this record as plain text. The optional SQLite backend also keeps Retro files in this dedicated directory so the format stays visible and compatible with the Sprint CLI.

Sprint Review files

A Sprint Review is stored separately under .pinto/review/ as .pinto/review/<SPRINT-ID>.md. Its ID is the parent Sprint ID, so the file name and the id frontmatter field must match. The body is free-form Markdown and the frontmatter records id, created, and updated:

+++
id = "S-1"
created = "2026-07-29T00:00:00Z"
updated = "2026-07-29T00:00:00Z"
+++

## Demonstrated

The file, Git, and optional SQLite backends keep Review data separate from both the Sprint goal and Sprint Retro records.

The machine-readable show and list representations expose sprint_id as the explicit parent-Sprint reference for both child-record types. It currently matches the stable id, which is also the Sprint ID and filename stem. Complete export --json snapshots place these records in their retros and reviews collections; importing a snapshot restores the same IDs, parent links, times, and Markdown bodies.

Retro and Review show views generate parent-Sprint context at read time. The context is not written into either Markdown body: it includes the parent goal, state, schedule, close-time spillover, and any available capacity, velocity, burndown, or Cycle/Lead Time reports. Missing context is displayed as unavailable and represented as null in --json; a closed Sprint’s stored spillover remains available after unfinished PBIs are rolled over or released. The generated detail view also lists active PBIs whose [source] link points to that child record; their normal PBI statuses are read from the PBI files.

Removing a Sprint protects these one-to-one child records by default. The --delete-records option is required to remove the matching Retro and Review files with the Sprint; records for other Sprints are unaffected.

Configuration

.pinto/config.toml controls the shared workflow and presentation settings. The default workflow is:

columns = ["todo", "in-progress", "review", "done"]
done_column = "done"

It is the one file under .pinto/ intended for hand-editing. Beyond the workflow columns, it selects the storage backend, project identity, WIP limits, and display/timezone options. Personal interactive Kanban keybindings belong in $XDG_CONFIG_HOME/pinto/config.toml; they are not board data and are not included in board exports. See Configuration for every setting. Keep machine-readable JSON timestamps in UTC; the display timezone does not rewrite stored data.

Compatibility boundaries

Board configuration is a strict TOML schema and may gain keys between releases; an older binary can reject a newer .pinto/config.toml. Markdown PBI and Sprint records are the file-backed board data. File and Git backends are the plain-text compatibility boundary, while SQLite is the explicit persistence exception with its own versioned schema and migration rules. JSON is a machine-readable CLI output contract, not another persistence backend and not a configuration file. Personal keybindings are independent of all four board data formats.

Safe operations

Use pinto commands to add, transition, rank, edit, archive, and relate PBIs. The generated .pinto/issued_ids file preserves every issued item number so a permanently deleted ID is never assigned to a different PBI; do not remove it when changing storage backends. Do not maintain a second hand-edited backlog or edit task files as part of the normal workflow. Direct recovery is an exception for damaged data; validate the board with pinto list afterward.

For the full JSON contract and migration rationale, see JSON output and storage migration.