Custom Status Values
Could not copy markdown source body. Please use "view as markdown".
Issue status defaults to todo, in-progress, done. Teams that want richer workflows (e.g. backlog, review, blocked, qa) register status as a property with their own option list. status is a regular property key, so there is no new API to learn.
When no extension registers status, fp falls back to the built-in three. Behavior is identical to projects that never installed an extension.
Workflow Extension
Section titled “Workflow Extension”Drop this file in .fp/extensions/workflow.ts. It declares a five-status workflow and uses the built-in status icons so the desktop renders them with the same look as the defaults.
import type { ExtensionInit } from "@fiberplane/extensions";
const init: ExtensionInit = async (fp) => { await fp.issues.registerProperty("status", { label: "Status", display: fp.ui.properties.select( fp.ui.properties.option("backlog", { label: "Backlog", icon: "no-status", color: "neutral", }), fp.ui.properties.option("todo", { label: "Todo", icon: "to-do", color: "neutral", }), fp.ui.properties.option("in-progress", { label: "In Progress", icon: "in-progress", color: "blue", }), fp.ui.properties.option("review", { label: "For Review", icon: "for-review", color: "purple", }), fp.ui.properties.option("done", { label: "Done", icon: "done", color: "success", }), ), });
fp.on("issue:status:changing", ({ from, to }) => { if (from === "backlog" && to === "done") { return { code: "NO_SKIP_REVIEW", message: "Issues must pass through review before being marked done.", }; } return undefined; });};
export default init;The order of options inside select(...) controls everything: the picker order, kanban column order, filter-bar order, sort priority, and tab-completion order. To reorder, edit the extension.
The first option is the default for new issues created without --status. The last option is treated as the completed state, so issues with it are not counted as open work.
Reserved Values
Section titled “Reserved Values”deletedis reserved as a soft-delete marker. Registering an option withvalue: "deleted"(or a case- or separator-insensitive equivalent likeDeletedorde-leted) is rejected when the extension loads.- All other non-empty strings are accepted as status values.
Built-in Fallback
Section titled “Built-in Fallback”When no extension registers status, fp behaves as if these three options were registered:
| Value | Label | Icon | Color |
|---|---|---|---|
todo | Todo | to-do | neutral |
in-progress | In Progress | in-progress | blue |
done | Done | done | success |
Once an extension registers status, its option list replaces the fallback entirely. If multiple extensions register status, the last to load wins (extensions load globals first, then project, alphabetically by filename within each scope).
Icon Names
Section titled “Icon Names”PropertyOption.icon accepts three families of names, and you can mix them within a single registration.
Built-in status icons (recommended for status)
Section titled “Built-in status icons (recommended for status)”The desktop ships six status icons. Use these for status options to match the rest of the UI:
to-do(empty circle)in-progress(half-filled circle)for-review(circle with inset arrow)done(filled circle with check)no-status(dashed circle)cancelled(circle with diagonal slash)
Lucide names that remap to built-in icons
Section titled “Lucide names that remap to built-in icons”Common Lucide names for the same shapes are accepted as aliases. They render the built-in variant, not the raw Lucide icon, so the look stays consistent:
| Input | Renders as |
|---|---|
circle, circle-empty | to-do |
loader-circle, circle-half | in-progress |
circle-arrow-right, circle-arrow | for-review |
circle-check | done |
circle-dashed | no-status |
circle-slash, circle-x | cancelled |
Name matching is case-, separator-, and whitespace-insensitive.
Raw Lucide passthrough
Section titled “Raw Lucide passthrough”Any other name is looked up as a Lucide icon by its PascalCase equivalent, so flag, clock, git-branch, and the like render the matching Lucide icon. A name Lucide does not recognize falls back to a dashed circle.
The “current” Set
Section titled “The “current” Set”Some surfaces (the CLI --current filter and “current work” views) need to know which statuses count as active work. fp derives this set automatically from the registered order; there is nothing to declare on individual options.
To set your own values, override them in TOML config. The override is read from three tiers, most specific first:
.fp/config.local.toml: this user, this project.fp/config.toml: this project, all users~/.fiberplane/config.toml: this user, all projects
[status]current = ["in-progress", "review"]Run fp guide from inside the project to see the resolved set. The project context header lists the values and labels them [auto] or [from <tier>], so you can tell whether fp derived the set or your config did.
Lifecycle Hook Payload
Section titled “Lifecycle Hook Payload”The issue:status:changing and issue:status:changed payloads carry from and to as status strings, so hook handlers can compare against any status your workflow registers:
fp.on("issue:status:changing", ({ from, to }) => { if (from === "backlog" && to === "done") { return { code: "NO_SKIP_REVIEW", message: "Issues must pass through review before being marked done.", }; } return undefined;});The hook fires for every status transition regardless of source (CLI, desktop UI, another extension). Return a HookValidationError to block the change; return undefined to allow it.