# How Town-Level Beads Are Organized and Prefixed in Gas Town: A Complete Guide

> Discover how town-level beads are organized and prefixed in Gas Town. Learn about hidden directories, route prefixes, and root resolution for efficient management.

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

---

**Town-level beads in Gas Town are stored in a hidden `.beads` directory, identified by the prefix defined in `routes.jsonl` (typically `"hq-"`), and resolved to the town root when the route path is set to `"."`.**

In the `gastownhall/gastown` repository, understanding how town-level beads are organized and prefixed is essential for working with the Mayor, Deacon, and role beads that define a town's configuration. The architecture uses a dedicated database location and a prefix-based routing system to distinguish town-wide beads from rig-specific ones. This design allows Gas Town to maintain a single source of truth for town-level state while supporting distributed rig configurations.

## Understanding the Town-Level Bead Architecture

A **town** in Gas Town represents the top-level workspace, identified by the presence of [`mayor/town.json`](https://github.com/gastownhall/gastown/blob/main/mayor/town.json) at its root. All beads belonging to the town itself—including Mayor, Deacon, and role beads—are stored in a single Beads database located in the town's hidden `.beads` directory.

This centralized storage model ensures that town-wide configuration remains atomic and portable. Unlike rig-specific beads that may reside in separate database files, town-level beads consolidate authority data in one location relative to the town root.

## The routes.jsonl Prefix Mapping System

The mapping between a bead-ID prefix and the physical database location is defined in `routes.jsonl`, a JSON-lines file stored inside the `.beads` directory. For town-level beads, the entry follows this structure:

```json
{ "prefix":"hq-", "path":"." }

```

- **prefix**: The string that appears at the start of every town-level bead ID, including the trailing hyphen (e.g., `"hq-"`).
- **path**: When set to `"."`, it indicates that the database resides at the town root itself—the `.beads` directory at the town level.

This configuration allows Gas Town to resolve bead IDs like `hq-1234` to the correct physical storage without hardcoding paths throughout the codebase.

## Key Functions in internal/beads/routes.go

The [`internal/beads/routes.go`](https://github.com/gastownhall/gastown/blob/main/internal/beads/routes.go) file implements the core logic for prefix extraction and path resolution.

### Resolving the Town Beads Directory

The `GetTownBeadsPath` function returns the absolute path to the town-level beads database:

```go
// GetTownBeadsPath returns the path to the town's .beads directory
// Located at routes.go:65-70
func GetTownBeadsPath(townRoot string) string {
    return filepath.Join(townRoot, ".beads")
}

```

This simple utility ensures consistent path construction across the application.

### Extracting Prefixes from Bead IDs

The `ExtractPrefix` function parses any bead ID to isolate its prefix component:

```go
// ExtractPrefix extracts the prefix including the trailing hyphen
// Located at routes.go:52-63
func ExtractPrefix(beadID string) string {
    // Implementation extracts "hq-" from "hq-abc123"
}

```

For example, passing `"hq-abc123"` returns `"hq-"`, enabling the routing system to categorize beads correctly.

### Mapping Prefixes to Physical Paths

The `GetRigPathForPrefix` function performs the critical lookup that connects a prefix to its storage location:

```go
// Located at routes.go:68-82
func GetRigPathForPrefix(townRoot, prefix string) (string, error) {
    // Looks up prefix in loaded routes
    // Returns townRoot when route.Path == "."
}

```

When this function encounters a route with `Path` set to `"."`, it returns the `townRoot` directly, effectively routing the bead ID to the town-level `.beads` database.

## Fallback Logic for Unregistered Rigs

If a rig lacks an entry in `routes.jsonl`, the system falls back to static configuration. The `GetPrefixForRig` function (located at `routes.go:72-80`) queries the `config` package for a default prefix, typically `"gt"`. This ensures that new or unconfigured rigs can still participate in the bead ecosystem without explicit registration.

## Practical Code Examples

To resolve the directory containing town-level beads:

```go
townRoot := "/home/user/gt"               // the Gas Town root
beadsDir := beads.GetTownBeadsPath(townRoot)
// beadsDir == "/home/user/gt/.beads"

```

To extract a prefix and locate the corresponding database:

```go
id := "hq-abc123"
prefix := beads.ExtractPrefix(id) // => "hq-"
rigPath := beads.GetRigPathForPrefix(townRoot, prefix)
// rigPath == "/home/user/gt" (town root) because the route has path="."

```

To programmatically add a town-level route (typically handled automatically by Gas Town commands):

```go
route := beads.Route{Prefix: "hq-", Path: "."}
_ = beads.AppendRoute(townRoot, route)

```

## Summary

- **Storage**: Town-level beads reside in the `.beads` directory immediately beneath the town root, as returned by `GetTownBeadsPath`.
- **Identification**: The `routes.jsonl` file maps a dedicated prefix (commonly `"hq-"`) to the town-level database via the `prefix` field.
- **Resolution**: `GetRigPathForPrefix` interprets a `path` value of `"."` as the town root, routing bead IDs to the centralized town database.
- **Fallback**: Unregistered rigs default to the `"gt"` prefix through the `GetPrefixForRig` configuration fallback.

## Frequently Asked Questions

### What is the default prefix for town-level beads in Gas Town?

While the specific prefix is configurable in `routes.jsonl`, town-level beads typically use the `"hq-"` prefix. This is defined in the town's `routes.jsonl` entry with `"path": "."`, distinguishing them from rig-specific beads that use different prefixes.

### How does Gas Town locate the database for town-level beads?

The system uses `GetTownBeadsPath` in [`internal/beads/routes.go`](https://github.com/gastownhall/gastown/blob/main/internal/beads/routes.go) to construct the path by joining the town root with the `.beads` directory name. This function ensures that all town-level bead operations target the correct database location consistently.

### What happens if a rig is not defined in routes.jsonl?

Gas Town implements fallback logic in `GetPrefixForRig` that queries the static configuration from the `config` package. If no route exists for a rig, the system defaults to the `"gt"` prefix, allowing the rig to function with default settings while maintaining compatibility with the broader bead ecosystem.

### Where is the town root determined in the codebase?

The town root is identified by the presence of [`mayor/town.json`](https://github.com/gastownhall/gastown/blob/main/mayor/town.json), as implemented in [`internal/workspace/find.go`](https://github.com/gastownhall/gastown/blob/main/internal/workspace/find.go). This file serves as the primary marker that distinguishes a valid Gas Town workspace from a standard directory, establishing the boundary for town-level bead storage.