# What Is a Bead in Gas Town and How Is It Stored?

> Discover what a Bead is in Gas Town and learn how this fundamental unit of work is stored as plain-text JSONL records within the .beads directory.

- Repository: [Gas Town Hall/gastown](https://github.com/gastownhall/gastown)
- Tags: deep-dive
- Published: 2026-07-07

---

**A Bead in Gas Town is the fundamental unit of work in the Beads issue-tracking system, stored as plain-text JSONL records inside the repository's `.beads` directory rather than an external database.**

In the `gastownhall/gastown` repository, the Bead abstraction serves as the native currency for tracking tasks, agent states, and ephemeral merge requests. All bead data lives directly within the repository filesystem, enabling complete offline portability and version-controlled issue management.

## Types of Beads in Gas Town

A Bead represents a flexible concept that adapts to different workflows within the Gas Town ecosystem. The system distinguishes between several bead types using label conventions:

- **Task / Bug / Feature beads** – Standard development issues tracked through the development lifecycle.
- **Agent beads** (`gt:agent` label) – Persistent state containers for Gas Town agents such as polecats or deacons, stored in the same database but representing autonomous entities rather than human tasks.
- **Merge-request beads** (`gt:merge-request` label) – Lightweight, transient "wisps" that represent merge requests without persisting as permanent issues.
- **Specialized beads** – Additional categories including *rig* beads, *role* beads, and *standing-order* beads, each identified by dedicated labels for infrastructure and automation purposes.

## Storage Architecture and Repository Layout

Gas Town stores all beads **inside the repository**, eliminating dependencies on external issue-tracking services. The storage system utilizes a plain-text JSON Lines (JSONL) format for durability and git compatibility.

### Locating the Beads Database

The system discovers the *town root* by traversing upward from the current working directory until it locates a [`mayor/town.json`](https://github.com/gastownhall/gastown/blob/main/mayor/town.json) file. Once identified, the beads database resides at `<town-root>/.beads`.

The effective storage path is computed by `getResolvedBeadsDir` in [`internal/beads/beads.go`](https://github.com/gastownhall/gastown/blob/main/internal/beads/beads.go) (lines 49-56), which checks for a `BEADS_DIR` environment variable override before defaulting to the standard `.beads` directory.

### File Organization

The `.beads` directory maintains separate files for different bead lifecycles:

- **`.beads/issues.jsonl`** – Contains persistent beads including tasks, bugs, features, and agent states. Each line represents a complete JSON record.
- **`.beads/wisps.jsonl`** – Stores ephemeral beads such as merge-request wisps that do not require long-term persistence.

The Beads CLI (`bd`) and the Go wrapper in `internal/beads` read and write these files either through subprocess calls or directly via the `beadsdk.Storage` interface.

## Go Implementation Details

The core bead logic resides in the `internal/beads` package, specifically within [`internal/beads/beads.go`](https://github.com/gastownhall/gastown/blob/main/internal/beads/beads.go).

### The Issue Struct

The `type Issue` struct (lines 75-96) defines the schema for a bead in memory:

```go
type Issue struct {
    ID          string
    Title       string
    Labels      []string
    Status      string
    Assignee    string
    HookBead    bool        // Marks agent-related beads
    AgentState  string      // Serialized state for agent beads
    // ... additional metadata fields
}

```

### The Beads Wrapper

The `Beads` struct (lines 30-44) provides the high-level API for interacting with the database:

- **`FindTownRoot`** – Locates the repository root by searching for [`mayor/town.json`](https://github.com/gastownhall/gastown/blob/main/mayor/town.json).
- **`ResolveRoutingTarget`** – Handles cross-rig bead routing when beads reference external repositories.
- **Storage abstraction** – Supports both CLI invocation (`bd` binary) and in-process `beadsdk.Storage` access.

## Working with Beads: Code Examples

### Creating a Task Bead

Use the `Beads` wrapper to create standard issues:

```go
b := beads.New(".")  // Initialize wrapper for current working directory
err := b.Create(beads.CreateOptions{
    Title:       "Add user authentication",
    Labels:      []string{"gt:task"},
    Priority:    1,
    Description: "Implement login flow using OIDC",
})

```

### Listing Open Tasks

Filter beads by status and label:

```go
openTasks, _ := b.List(beads.ListOptions{
    Status: "open", 
    Label:  "gt:task",
})
for _, t := range openTasks {
    fmt.Printf("%s – %s\n", t.ID, t.Title)
}

```

### Accessing Agent Bead State

Agent beads bypass standard routing prefixes and expose dedicated state fields:

```go
// Retrieve agent state regardless of ID prefix
agentBead := b.ForAgentBead().Show("gt-abc123")
fmt.Printf("Agent state: %s\n", agentBead.AgentState)

```

### Querying Merge Request Wisps

Ephemeral merge-request beads combine data from both persistent and ephemeral stores:

```go
mrs, _ := b.ListMergeRequests(beads.ListOptions{Status: "open"})
for _, mr := range mrs {
    fmt.Printf("MR %s: %s (assignee %s)\n", mr.ID, mr.Title, mr.Assignee)
}

```

## Summary

- A **Bead in Gas Town** is the fundamental unit of work tracked by the Beads system, capable of representing tasks, agent states, or ephemeral merge requests.
- All beads store data **inside the repository** under the `.beads` directory, not in external databases.
- **Persistent beads** reside in `.beads/issues.jsonl`, while **ephemeral wisps** live in `.beads/wisps.jsonl`.
- The **town root** is discovered by locating [`mayor/town.json`](https://github.com/gastownhall/gastown/blob/main/mayor/town.json), with storage paths resolved by `getResolvedBeadsDir` in [`internal/beads/beads.go`](https://github.com/gastownhall/gastown/blob/main/internal/beads/beads.go).
- The Go API provides the **`Beads` wrapper struct** and **`Issue` type** for programmatic CRUD operations, supporting both CLI and direct storage interfaces.

## Frequently Asked Questions

### What is the difference between issues.jsonl and wisps.jsonl?

The `issues.jsonl` file stores permanent beads including tasks, bugs, and agent states that require long-term tracking and version history. The `wisps.jsonl` file contains ephemeral beads such as merge-request wisps that represent transient workflow states and do not need to persist indefinitely in the repository history.

### How does Gas Town locate the .beads directory?

Gas Town discovers the beads directory by walking up the filesystem from the current working directory until it finds a [`mayor/town.json`](https://github.com/gastownhall/gastown/blob/main/mayor/town.json) file, which marks the town root. The `.beads` folder must reside at this root level. The `FindTownRoot` method in the `Beads` wrapper implements this traversal logic.

### What is an agent bead in Gas Town?

An agent bead is a specialized bead type marked with the `gt:agent` label that stores the persistent state of a Gas Town autonomous agent, such as a polecat or deacon. Unlike task beads, agent beads contain a dedicated `AgentState` field and are accessed through the `ForAgentBead()` method to bypass standard routing prefixes.

### Can beads be stored outside the repository?

While the default behavior stores beads within `.beads` at the town root, the system supports the `BEADS_DIR` environment variable to override the storage location. The `getResolvedBeadsDir` function (lines 49-56 in [`internal/beads/beads.go`](https://github.com/gastownhall/gastown/blob/main/internal/beads/beads.go)) checks for this override before returning the default path, though external storage breaks the version-control integration that makes Gas Town portable.