# Complete Guide to Issue Statuses in Beads: Built-in and Custom Workflows

> Discover all Beads issue statuses, from built-in open and in_progress to custom workflows. Manage your work queues effectively with a clear overview of your project's progress.

- Repository: [Gas Town Hall/beads](https://github.com/gastownhall/beads)
- Tags: how-to-guide
- Published: 2026-04-27

---

**Beads defines seven built-in issue statuses—`open`, `in_progress`, `blocked`, `deferred`, `closed`, `pinned`, and `hooked`—organized into four behavioral categories that control visibility in work queues, alongside a configurable system for adding custom statuses via the `status.custom` configuration key.**

The `gastownhall/beads` project implements a strict, workflow-driven status model through its `bd` CLI tool. These statuses are not merely labels; they are strongly typed values defined in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go) that determine how issues surface in filtered views like `bd list` and `bd ready`.

## The Seven Built-in Issue Statuses in Beads

According to the source code in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go) (lines 27–34), Beads provides the following built-in statuses, each mapped to a specific behavioral category:

- **`open`** — Category: **active**. The default status for new issues, indicating they are available for work and appear in standard list views.
- **`in_progress`** — Category: **wip** (work in progress). Indicates active development and qualifies the issue for the `bd ready` work-queue.
- **`blocked`** — Category: **wip**. Marks an issue as stalled by external dependencies, remaining in workflow queues but flagged.
- **`deferred`** — Category: **frozen**. Deliberately shelved work that is hidden from default `bd list` and `bd ready` views.
- **`closed`** — Category: **done**. Represents completed or resolved issues, filtered out of active work queues.
- **`pinned`** — Category: **frozen**. A persistent status that stays open indefinitely, excluded from standard workflow automation.
- **`hooked`** — Category: **wip**. An internal status attached to an agent’s hook, typically managed programmatically rather than manually.

The `BuiltInStatusCategory` mapping in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go) drives this categorization logic, ensuring the CLI filters views correctly based on these groupings.

## How Status Categories Drive Workflow Logic

The category assigned to each status determines its visibility and behavior across the Beads interface. The `bd` CLI uses these categories to decide which issues appear in specific contexts:

- **`active`** — Issues appear in default `bd list` output.
- **`wip`** — Issues qualify for the `bd ready` work-queue, representing the pool of actively progressing work.
- **`frozen`** — Issues are hidden from both default lists and the ready queue, effectively paused.
- **`done`** — Issues are treated as resolved and excluded from active workflow views.

This implementation allows the system to maintain clean separation between backlog items, active work, and archived issues without requiring complex query syntax.

## Adding Custom Issue Statuses in Beads

Beyond the built-in set, Beads allows users to define custom statuses through configuration. These are stored in the `status.custom` config key and must follow the strict pattern `name:category`, where the category must be one of the four valid behaviors (`active`, `wip`, `frozen`, `done`).

The [`cmd/bd/statuses.go`](https://github.com/gastownhall/beads/blob/main/cmd/bd/statuses.go) file (lines 13–26) implements the retrieval logic, while `ParseCustomStatusConfig` in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go) handles the parsing of these configuration strings into `CustomStatus` structs. Custom statuses appear alongside built-in ones when running `bd statuses --json` and participate in the same category-based filtering logic.

```bash

# Add a custom status called "in_review" that appears in active lists

bd config set status.custom "in_review:active"

# Verify the custom status appears in the enumerated list

bd statuses --json | jq '.custom_statuses[] | select(.name=="in_review")'

```

## Validating and Using Statuses via the CLI

Beads enforces status validity through the `IsValid` and `IsValidWithCustom` functions in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go). These validators ensure that only recognized built-in statuses or properly configured custom statuses can be assigned to issues, preventing typographical errors or invalid workflow states.

The `bd statuses` command (implemented in [`cmd/bd/statuses.go`](https://github.com/gastownhall/beads/blob/main/cmd/bd/statuses.go)) exposes all available statuses, rendering a human-readable table with icons by default or machine-readable JSON when passed the `--json` flag.

```bash

# Display all statuses in an interactive table

bd statuses

# List statuses as JSON for scripting

bd statuses --json

```

You can apply these statuses when creating or updating issues:

```bash

# Create an issue with a custom status

bd create "Add CI pipeline" --type task --status in_review

# Update an existing issue to closed

bd update bd-1a2b3c --status closed

```

## Summary

- **Seven built-in statuses** (`open`, `in_progress`, `blocked`, `deferred`, `closed`, `pinned`, `hooked`) are defined in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go) and mapped to four behavioral categories (`active`, `wip`, `frozen`, `done`).
- **Category-driven visibility** determines whether issues appear in `bd list`, `bd ready`, or are hidden from view.
- **Custom statuses** can be added via `status.custom` configuration using the `name:category` pattern, parsed by `ParseCustomStatusConfig`.
- **Validation** occurs through `IsValid` and `IsValidWithCustom` to ensure only recognized statuses are assigned.
- **CLI exposure** happens through `bd statuses`, with JSON output available for automation.

## Frequently Asked Questions

### What are the default issue statuses in Beads?

Beads ships with seven built-in statuses defined as constants in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go): `open`, `in_progress`, `blocked`, `deferred`, `closed`, `pinned`, and `hooked`. Each is categorized as `active`, `wip`, `frozen`, or `done` to control its behavior in workflow views.

### How do I create a custom issue status in Beads?

Configure a custom status using the `status.custom` config key with the pattern `name:category`, such as `bd config set status.custom "in_review:active"`. The category must be `active`, `wip`, `frozen`, or `done`, and the status will immediately appear in `bd statuses` output.

### What is the difference between active, wip, and frozen categories?

The `active` category makes issues appear in default `bd list` views; `wip` (work in progress) includes them in the `bd ready` queue; `frozen` hides them from both views, effectively pausing the work. These mappings are handled by `BuiltInStatusCategory` in the types definition.

### How does Beads validate issue status assignments?

Validation occurs through the `IsValid` and `IsValidWithCustom` functions in [`internal/types/types.go`](https://github.com/gastownhall/beads/blob/main/internal/types/types.go), which check assigned statuses against the built-in constants and any user-defined custom statuses loaded from configuration. This prevents invalid or misspelled statuses from being applied to issues.