Cards

Cards started with a problem I kept running into while working with coding agents: the work was in a plan.md, but by the next session it was hard to tell what had actually happened. A plan is easy to rewrite, and two workers can trip over the same file. I wanted the work queue, the decisions, and the evidence to stay with the project.

Cards browser dashboard showing the Engineering board grouped by status

I didn't want another hosted tracker to set up and maintain with the code. Cards puts everything in the repo: JSON snippets describe the card types and states, and the same board is usable from the browser, CLI, terminal UI, HTTP API, or a Model Context Protocol (MCP) server for agents. I use Cards to manage Cards itself; the engineering board in the repo is its real backlog.

A card type defines the fields a work item needs. This excerpt from the programming-task type requires a description and branch, and gives the work log places to record a commit and its author:

{
  "id": "programming-task",
  "name": "Programming Task",
  "schema_version": 1,
  "fields": [
    { "id": "description", "type": "text", "required": true },
    { "id": "branch", "type": "string", "required": true },
    {
      "id": "work_log",
      "type": "repeating",
      "required": false,
      "display": "feed",
      "item_fields": [
        { "id": "commit_hash", "type": "string", "required": true },
        { "id": "notes", "type": "text", "required": false },
        { "id": "author", "type": "user", "required": true },
        { "id": "timestamp", "type": "date", "required": true }
      ]
    }
  ],
  "allowed_columns": ["backlog", "todo", "in_progress", "review", "done"]
}

An agent can ask the board for its next programming task. take-next claims it atomically; -q prints just the card ID:

$ cards take-next --board engineering --type programming-task -q
card_7e090c38

The agent can then record the branch, commit hash, and notes on that card. Each update includes the card's current version, so if I or another agent changed it meanwhile, the write is rejected instead of quietly overwriting the newer state. Comments and the work log leave a record I can review and the next session can pick up.

The live database is SQLite, so there's no separate database server to run. For a handoff, I export cards, comments, and links to a JSONL snapshot and commit it with the project; a fresh checkout can restore that board state. The database remains the working copy, while the definitions and snapshot keep project coordination readable and close to the code.

Cards engineering board in the terminal UI, with work grouped by status

The terminal UI is another way to work with the same board.

Cards card details displayed in a classroom-style custom theme

It supports custom themes and comes with a few out of the box. The one above has a friendly classroom vibe if you want to escape the enterprise day-job look.

Cards card details showing related and parent work items

Dependencies are fully supported, allowing Epic-Story-Task style structure, or whatever you want - these are defined in the board schema. The docs explain how card definitions work. It could even be used for automation workflows, here's an example that could be used for manufacturing and job tracking. And what's more enterprise reliable than JSON and git?

Cards is open source (MIT) and still in beta, but I'm using it on many projects for quite a while now. I want to keep the core small (cards, fields, events, links, comments, columns, and storage) and keep it open for integration to clients with a modular design and hooks for callbacks.