Skip to content

Backlog

The Backlog plugin keeps the work that realizes a blueprint beside the definition: one markdown file per task in the root’s backlog/ folder, each serving the blueprints it names by their permanent id, or none, on a board whose statuses and columns the root defines. A task is not a blueprint: never a collection item, never checked as one, never in the index. A task dies when the work ships; the blueprint stays. Off by default; eidos plugin enable backlog switches it on and declares the folder.

  • Board: one column per configured column, a card per task with its type as an icon before the title, its id, its priority as an icon in its colour, and the root’s own properties it holds, dragged between columns to write the column’s first status. A column shows at most seven cards at its full height, fewer when the window has no room for seven, and scrolls within itself past them, its head and its count of every card staying in view, and a card dragged near its top or bottom scrolls it; the number is Column height on the Kanban tab (column_cards, 0 for every card). A task in a Done status not updated for more days than Hide done tasks on the Kanban tab (hide_done_days, empty by default, so none is hidden) is left off the board and out of its filters, its column saying how many it hides; it still lists in the tables, Attached tasks, and eidos backlog. A subtask is not a card unless you turn on Show subtasks on the board under Preferences → General (yours on every root, in preferences.yaml): off, its parent’s card counts its subtasks done (2/5); on, each subtask is a card naming its parent, dragged like any task. In the Backlog table a subtask is a row indented under its parent’s, at any depth, and a parent’s chevron folds what is under it; every parent starts open, a sort orders siblings within their parent, and a filter or a search that keeps a subtask but not its parent still shows the parent’s row, muted, for context. The Backlog table has a column for status, priority, assignee, milestone, each of the root’s own properties, the blueprints, and the day updated, and the Drafts for status, the blueprints, and the day updated, until the Task properties tab puts a property On table or off it, in both at once. Backlog lists every task in a backlog status with Promote onto the board. Both filter by status, priority, assignee, type, milestone, and blueprint, and by any property of the root’s switched to Filter; the table sorts by any column, and status, priority, and assignee edit in the row. A Milestones table sits beside them, filtered the same way by the milestone properties switched to Filter. A search box leads the filters on the board, the Backlog table, the Drafts, and the Milestones, as on every table: it keeps the tasks holding every word typed, in any case, in the id, the title, or a value the row shows other than its dates, so T-4KQ7 finds that task and the tasks naming it as their parent or a dependency. Every picker (a task’s blueprints and parent, Attach existing, the canvas’s blueprints) and Quick Open find a task, a blueprint, or a decision by its id or a former id, in any case, as well as by its title, and list the id before the title; a long title is cut with an ellipsis, whole on hover. A table shows the day a task was made or updated, the time on hover, and sorts by the moment, so the newest task is first however many were made that day. The board’s filters, the Backlog table’s, and the Drafts’ are in the page’s address (/p/backlog?sprint=Sprint+12&assignee=agent, the search as q), so a filtered board can be bookmarked, shared, and reloaded; By status, By type, and My work keep their own addresses. Once filtered, the board, the Backlog table, and the Drafts offer Save as view, and a view saved is listed in the activity under Board, All tasks, or Drafts; My work, the statuses, and the types are the views every root starts with. Saved views →
  • A task opens in a modal from the board, the table, or a blueprint’s attached tasks, with Expand for its own page, and follows the task by its id when its file is renamed, from the page or from outside: properties typed by kind (a calendar for a date), the checklist lines ticked into the file, each section a card in the editor, the file as text, Comments’ threads at the foot, and Delete in every mode. Under the sections a task lists its subtasks in order, nested, each with its type, its id, and its status set in place: a title opens one, a row dragged onto a sibling (or moved with the arrows on hover) takes that place, Add a subtask makes one, and Add existing makes a task already written one, taking the next place (never the task itself or one above it); each row’s ⋯, or a right-click on it, offers Remove from parent, which makes it a task at the top, and Delete task…, asked once. The task’s head names its parent and the task, each by its type’s icon and id (T-PARENT / T-TASK), the parent a link to it and never the chain above it, so you go up one step at a time. After them come its links, grouped by how each reads from this task (is blocked by, relates to): each the other task’s title, id, and status, set in place, a trash on hover to take the link out, and + to make one, asking the link type and then the task. A right-click on a row of the Backlog table or the Drafts, or on a card on the board, opens the task’s menu: Open, Open as a page, Assign to me (whoever you act as, beside anyone already on it), Copy id, the ways out to the file, and Delete.
  • A task an open task blocks is marked blocked on its card and in the Backlog table, the tasks blocking it named on hover, and once a task on the page holds a link the filters offer Links: Blocked, or a phrase the tasks are linked by.
  • New task, from the pages, the activity, a blueprint’s attached tasks, or the palette (over whatever page you are on, which stays under it), asks for the task’s type and title before anything is made (with more than one type, none is taken until one is picked), then makes the file, or a draft of it, and opens it, where the rest is filled in. It asks for no parent: a task goes under another from that one’s subtasks. Enter in the title makes it as Create does. From the Drafts it is New draft, whose Create draft makes a draft and never a task; only the draft’s Publish does.
  • Export, from the ⋮ at the top right of the Backlog table: Export this view… writes the tasks the table shows, in its order, and Export all tasks… every task in the folder, as one CSV file or an Excel workbook. A dialog asks for the Format (CSV to start, or Excel: a sheet whose first row, the fields’ names, stays in view and filters) and which fields: every property of the format and every one the root declares, each checked to start, and Content apart and unchecked: the task’s whole body, every section and its comment threads, the only way comments leave with a task. eidos backlog export does the same from the shell.
  • Backlog, an activity in the Activity Bar with the count of your open tasks, listing them by column, and My work: the open tasks assigned to you. Each status has a category, as in Jira: To Do, In Progress, or Done, set beside the status on the Settings tab (status_categories). A task in a Done status is finished and never shows in My work or the open counts, and a Done status is drawn green. A status left unset takes its category from where it sits: the backlog and the first column are To Do, the columns after it In Progress, and a status listed after every column’s (a Done kept off the board), or else the last column, is Done.
  • Attached tasks, a view in the Auxiliary Sidebar: the tasks serving the open blueprint, the count of open ones on its tab, and a way to start one for it or to attach one already written (Attach existing, which finds a task by its title or id among those not serving the blueprint yet). The editor’s block menu offers a task the same way.
  • The plugin’s settings page holds the statuses, columns, priorities (each with an icon and a colour, Jira’s from its place until one is chosen: up and red above the middle, equals and orange at it, down and blue below), milestones, a Task types tab (every field of a type and its sections labelled), and a Task properties tab. A task’s properties and a milestone’s are declared as the framework’s are: a card each, changed in the same form (the types a task property applies to ticked as checkboxes, its options added one at a time and put in order), placed in the order the reader shows them, and switched to Filter to be a dropdown over the board and the tables, or On table to be a column of the Backlog table and the Drafts (a milestone’s, of the Milestones table, where every one is a column until switched off). Beside Filter, Only show actively used in filters narrows that dropdown to the values an open task holds (one whose status is not in the Done category; for a milestone’s property, a milestone with an open task or none yet), so a sprint whose tasks are all Done drops out of the filter while it stays declared and on its tasks. The built-in properties a person sets take an Order there too, the order a task’s properties and New task show them in, the root’s own after them, and those a table can hold take On table (builtin_properties). A built-in that filters (status, priority, assignee, type, milestone, blueprints) offers every value the root declares (its statuses, priorities, users, types, milestones, and blueprints) and any other a task holds; In use beside its Filter switch narrows it to the values an open task holds, as Only show actively used in filters does for the root’s own (filter_in_use: true on its builtin_properties entry).

Frontmatter: id (the task’s permanent id, given when the task is made, in three parts: T- for any task as a blueprint’s is B-, then the task type’s prefix when it has one, then letters or digits; so T-1AC3 for a type with no prefix, and T-BP29 for a bug type whose prefix is B, the B after T- and never in its place), aliases (the ids the task was known by before, kept when its id changes; each still reaches the task wherever an id does), title, type (one the root declares; absent means default), status, assignee (aliases from the root’s users), milestone, priority, links (the links this task made, see Links), dependencies (retired for links: other tasks, by id, read and written until the root migrates), parent (a task, by id), created, updated (the moment the task was made and last changed: the local time with its offset, 2026-10-01T22:11:39-03:00; a day alone, from before or an import, reads as that day’s start), blueprints (the ids of the blueprints the task serves; none is fine), at (section and item: a place in the first of them, by content), and any property the root declares in the plugin’s settings. Labels are not the format’s: a root that wants them declares a labels List property with its options.

The body is the sections the task’s type declares, every one optional: by default ## Description, ## Checklist (a checklist of - [ ] #1 … lines), ## Implementation Plan, and ## Implementation Notes; a root may add its own (References or Modified Files as links, Definition of Done as a checklist, Final Summary as text). Each sits inside a region of the plugin’s own, <!-- backlog:<key> --> … <!-- /backlog:<key> -->, rewritten whole when the section is set; anything else in the file is kept as found, so editing a task by hand is fine.

The file name is the task’s id and the first words of its title (t-4kq7-rate-limit-the-login-form.md), so the files sort by id and a task is found by its id from outside the app: a title change or an id change renames the file, every link to it and its threads following. A task named before this is reported by the check, whose Rename renames it; eidos backlog rename-files renames every one, which you then commit. A command takes a task by its id or its name. An id can be given by hand (add --id) or changed later (set --id, or the pencil beside the id in a task’s head): the new one must not be any task’s id or former id, in any case, and a change keeps the old id as an alias and rewrites every reference in the root (dependencies, parents, decisions, comment threads, links). A task written before ids gets one from the check’s Assign id or eidos backlog ids. A template’s Tasks section is where a blueprint lists the tasks that serve it: in Framework Settings → Templates, each section has a type beside its heading, Text by default or Tasks while the Backlog is on, and a Tasks section holds a <!-- backlog:tasks --> region. In a blueprint of that template the plugin writes the tasks there after any change, adding the section’s heading in the template’s order where the blueprint lacks it, and takes out a list written anywhere else, such as the foot of an older body. A template with no Tasks section shows no tasks in the text; they still list in Attached tasks. The link lives on the task; never type into the region.

A subtask’s id is its place under its parent: the parent’s id, a dot, and its position, T-FT36.1, T-FT36.2, T-FT36.2.1, at any depth, and that number is the subtasks’ order. A new subtask takes the next place. Moving one among its siblings, or under another parent, where it takes the next place, renumbers them and everything under them, and those it leaves close up, as they do when one is removed; a parent’s id changing carries down to every descendant. Every reference in the root follows (dependencies, parents, decisions, comment threads), and a place that moves keeps no alias, so a subtask’s id is a place, not a lasting name to quote outside the root. A subtask moved to the top takes a drawn id, and a task made a subtask keeps its drawn id as an alias. A parent’s file lists its subtasks in a <!-- backlog:subtasks --> region at its foot, in order, nested by depth, each with its id, its title linked to its file, and its status, ticked when done; the plugin rewrites it after every change to a subtask and takes it out with the last, so an agent reading the file sees them. eidos backlog renumber gives places to subtasks written before them (their drawn ids kept as aliases) and settles a place two branches each added, the later taking the next.

types is the kinds of task the root works in, each a name, a title, an icon and a colour, and the sections its body holds: a template per kind, as a collection has variants. A root starts with one, default. The types are in an order, put in order on the Task types tab (drag a row’s number, or use its arrows) or with configure:type set <name> --position <n>, and every list of types follows it: the reader’s Type, the Type filter, New task’s picker, and By type in the sidebar. A type may also have an ID prefix, letters a new task of the type wears after T- and before its value: a bug type with B gives T-BF36, and the Task types tab shows the id a new task gets as you type the letters, and eidos backlog types lists it as ids T-B…. The value after the prefix is unique among every task whatever prefix it wears, so T-BF36 and T-CF36 never both exist; a subtask takes no prefix. A task whose type changes takes the new type’s prefix, its value kept and its old id kept as an alias. A prefix applies to new tasks; once one is saved, the Task types tab says how many tasks were written before it and offers to re-ID them, which eidos backlog reid does from the shell. statuses is the root’s ordered list; columns maps each board column to one or more statuses; a status in no column is a backlog status, listed on the Backlog page and never on the board. The default is Jira’s: Intake, To Do, In Progress, In Review, Done, with Intake on the backlog. A new task lands in default_status.

A task links to another and says how, as Jira’s linked work items do. link_types holds the kinds, each a name, an outward phrase, and an inward one: Jira’s four to start, blocks (blocks, is blocked by), relates (relates to, both ways), duplicates (duplicates, is duplicated by), and clones (clones, is cloned by). The Links tab of the plugin’s settings rewords a phrase, adds a type (named from its outward phrase, its inward phrase the same when left blank), removes one, and puts them in order, a row dragged by its number or moved by its arrows; the name is what the files write, so it stays when the phrases change. A task’s links are grouped in that order, and a new link starts on the first type.

A link is written once, on the task it was made from, as an entry of its links, one a line; the other task’s file is not touched, and it shows the inverse:

links:
- { type: blocks, task: T-4KQ7 } # this task blocks T-4KQ7
- { type: blocks, task: T-9ZQ4, direction: inward } # this task is blocked by T-9ZQ4
- { type: relates, task: T-2BCD } # relates to, read the same from either side

A task is blocked while an open task blocks it and it is open itself. A link follows a task’s id when it changes, as every reference does.

dependencies is retired for links: its direction was never said. Until a root migrates, a dependency is read and written as before, the tables offer it only while a task holds one, a task’s panel only while that task holds one, and New task never. The check reports each task still holding one as backlog/dependencies-retired; its fix, Migrate, or eidos backlog migrate-dependencies, makes every dependency a relates to link on the task that held it (one link for a pair) and takes the key out of every task and draft, the dates untouched.

A draft is a task not yet in the folder: the same file, kept under .eidos/plugins/backlog/drafts/ (shared with the root) or .eidos/plugins/backlog/local/drafts/ (local, never committed), in no list until it publishes, though show and set reach it by its name as they do a task. A draft has no threads and is projected nowhere.

  • backlog/ (or any folder declared owned_by: "@backlog/tasks"): the tasks, one file each. The root →
  • .eidos/plugins/backlog/settings.yaml, shared: types, sections, statuses, columns, default_status, priorities, priority_icons, priority_colors, column_cards, hide_done_days, milestones, milestone_properties, properties, builtin_properties, and link_types.
  • .eidos/plugins/backlog/drafts/ and local/drafts/: the drafts.
Terminal window
eidos backlog # every task, grouped by column
eidos backlog --status "In Progress" --assignee ada # --column, --milestone, --blueprint, --type, --where key=value, --json
eidos backlog --search "login page" # every word, in any case, in the id, the title, or a value the row shows
eidos backlog drafts --search T-4KQ7 # a draft by the task id it holds
eidos backlog add "Rate limit the login form" --for @login --body description="Anyone can guess forever." --add-line checklist="Locks after five tries"
eidos backlog sections --type bug # the keys a bug's sections take, and the options that write each
eidos backlog show T-4KQ7 # a task by its id, or by its file name
eidos backlog set T-4KQ7 --status "In Progress"
eidos backlog set T-4KQ7 --body implementation-notes="Tried a sliding window first."
eidos backlog set T-4KQ7 --reword-line checklist#1="Locks after five tries in a minute" --remove-line checklist#2
eidos backlog check T-4KQ7 1 # tick line #1 of the type's first checklist; --undo, --in <key>
eidos backlog promote <task> # from the backlog onto the board
eidos backlog link T-4KQ7 is-blocked-by T-9ZQ4 # a link, written on T-4KQ7: a type's name or either phrase
eidos backlog unlink T-9ZQ4 blocks T-4KQ7 # taken out of whichever file holds it
eidos backlog link-types # the root's link types, each name and its two phrases
eidos backlog migrate-dependencies --dry-run # what retiring dependencies would write; --yes to write
eidos backlog remove T-4KQ7 # delete a task, as the page's Delete does
eidos backlog export --assignee ada --field id --field title --content --out tasks.csv # the tasks the filters keep; --json
eidos backlog export --out tasks.xlsx # an Excel workbook, every task and every field
eidos backlog types # the types; sections [--type] lists a type's sections
eidos backlog configure:property add labels --type List --filter # a task property; set|remove, properties lists them
eidos backlog configure:type add bug --icon bug --color red --section "Steps:checklist" # a task type; set|remove
eidos backlog configure:type set bug --prefix B # new bug tasks are T-B…; "" clears it
eidos backlog configure:type set bug --position 1 # bug first in every list of types
eidos backlog configure:type rename-section default checklist "Done When" --dry-run # every task of the type follows, heading and region
eidos backlog configure:status add Blocked --column "In Progress" --color red # a status; set|rename|remove, --category, --position, --default
eidos backlog configure:status rename "In Review" Review # the tasks in it follow, their dates kept
eidos backlog configure:priority add urgent --position 1 --icon double-up --color red # a priority; set|rename|remove
eidos backlog configure:column add Waiting --statuses Blocked --position 2 # a board column; set|rename|remove
eidos backlog configure:milestone add Beta --date 2026-11-01 # a milestone; set|rename|remove, rename carries its tasks
eidos backlog configure:link-type add causes --inward "is caused by" # a kind of link; set|remove, --position <n> its place
eidos backlog configure:builtin set priority --position 1 --no-table # a built-in property's place, column, and filter
eidos backlog reid --type bug --was X --dry-run # how many tasks would take the prefix (X the one it had); --yes to write
eidos backlog reid --scheme --yes # also redraw the ids drawn under another id scheme than the root's
eidos backlog add "Log in" --id T-LOGIN # an id by hand, refused when any task holds it
eidos backlog set T-LOGIN --id T-SIGNIN # a new id, the old kept as an alias, every reference following
eidos backlog add "Old task" --property labels=finance,feature --created 2025-03-01T09:30:00-03:00 --updated 2025-04-02 # an import: a moment, or a day alone
eidos backlog draft "An idea" --local # drafts, draft:move <draft> shared|local, publish <draft>
eidos backlog add "Draft it" --parent T-FT36 # a subtask, T-FT36.1 then T-FT36.2…
eidos backlog set T-FT36.2 --position 1 # moved to first, the siblings renumbered
eidos backlog renumber # places for subtasks written before them, a place two branches added
eidos backlog project # rewrite every backlog:tasks region and backlog:subtasks list that drifted
eidos backlog ids # ids for tasks written before them, and references moved onto ids
eidos backlog rename-files --dry-run # every task named the old way, old name to new; without --dry-run, renamed with every link

set sets one thing per option: --id, --type, --status, --title, --assignee, --milestone, --priority, --for, --section, --item, --dependency (retired for links), --parent, --position <n> (a subtask’s place among its siblings), --property name=value, or a section by the key its type declares: --body key=text for its contents, and for a checklist --add-line key=text, --reword-line key#n=text, and --remove-line key#n (the lines after it renumbered, their ticks kept). add takes --body and --add-line too, and eidos backlog sections --type <type>, add --help, and set --help list the keys. configure:type rename-section <type> <key> <title> renames a section and carries every task of the type, heading and region, as a status renamed carries its tasks.

--property is typed by the property’s declaration: a List takes its items comma-separated or the flag repeated, a Number a number, a Checkbox on or off. Every write stamps updated with the moment; --created and --updated on add and set give the dates instead (a moment, or a day alone), so an import keeps the ones it came with. configure:property and configure:type write the task properties and task types to the plugin’s settings.yaml as its page does, one entry at a time; --dry-run prints the entry and writes nothing.

To take a task as an agent: read its blueprints, set the status to the working column’s, do the work in the blueprint or the code, tick its checklist lines as they are met, write what you learned in its notes section (Implementation Notes by default), and set the status to the last column’s. Never write a task’s name into a blueprint.

backlog/blueprint-missing (a task names a blueprint the root does not have), backlog/status-unknown, backlog/type-unknown, backlog/priority-unknown (a priority the root does not declare; one given as High where the root declares high is written as high), backlog/no-done-status (no status is in the done category, so every task reads as open), backlog/dependency-missing (a dependency the backlog does not have), backlog/dependencies-retired (a task still holding dependencies; Migrate makes every one in the root a relates to link), backlog/link-missing (a link to a task the backlog does not have), backlog/link-type-unknown (a link by a type the root does not declare), backlog/id-missing (a task written before ids; Assign id fixes it), backlog/id-duplicate (two files holding one id), backlog/alias-taken (a former id kept in aliases that another task holds as its id), backlog/alias-duplicate (a former id two tasks keep), backlog/id-draft (under the sequential id scheme, a draft id still on the default branch; eidos ids finalize gives it its number), backlog/reference-by-name (a dependency or parent still written as a file name; Use ids fixes it), backlog/file-name (a task whose file is not named by its id and the first words of its title; Rename fixes one and eidos backlog rename-files every one), backlog/region-stale (a blueprint’s backlog:tasks region that is not what the tasks would write; Project fixes it), backlog/subtask-position (a subtask whose id is not its place under its parent; Renumber fixes it), and backlog/subtasks-stale (a parent’s backlog:subtasks list that is not what its subtasks would write; Project fixes it). Off again, the folder and its tasks stay where they are, still declared, and nothing of the plugin shows.