Metadata-Version: 2.4
Name: local-board
Version: 0.0.2
Summary: Repository-local issue tracker with MCP and a lightweight web UI
Keywords: coding-agents,issue-tracker,local-first,mcp
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Environment :: Web Environment
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Software Development :: Bug Tracking
Requires-Python: >=3.11
Description-Content-Type: text/markdown

# Local Board

Local Board is a lightweight issue tracker installed inside a repository. It gives autonomous agents and humans a shared SQLite-backed board, an MCP interface, and a local web UI without requiring a hosted service.

## Is Local Board a fit?

Local Board is most useful when multiple agents, or humans and agents, work concurrently on the same local repository and need atomic claims, explicit handoffs, workflow rules, and an audit trail. It can replace an ad-hoc `TODO.md` for that local coordination loop while keeping project configuration and agent instructions in Git.

It is probably unnecessary for a single short-lived agent task, and it is not a replacement for a hosted tracker used by a distributed team. Issues, comments, identities, and activity live in the ignored SQLite database: Git clones receive the board configuration and instructions, **not** the operational board. Agents in other worktrees must connect to the one server that owns the common Git repository's database. Agents on other machines need a deliberately operated shared host (with appropriate network security) or a separate board; Local Board does not synchronize databases between machines.

## Product scope

The first release includes:

- projects and milestones;
- `task`, `bug`, `feature`, `chore`, and `epic` issues;
- a separately configurable workflow for every issue type;
- Markdown descriptions and comments;
- priorities, ordering, assignees, and reviewers;
- checklists, labels, attachment references, and issue dependencies;
- branch/commit/PR/MR references and issue-key matching for local branches;
- authenticated human and agent identities;
- an immutable append-only activity audit log;
- MCP over Streamable HTTP at `/mcp`;
- a repository-local web board.

Local Board deliberately does not reproduce Linear's entire product or API. Linear's MCP design was used as a product reference: expose focused, discoverable issue-management tools rather than leaking the database schema. The implementation uses standard MCP `initialize`, `tools/list`, and `tools/call` methods. Live verification against Linear's official documentation could not be completed in the development environment because outbound access returned HTTP 401/403; consequently this project claims MCP protocol interoperability, not tool-for-tool Linear compatibility.

## Architecture

```text
Agents ── Streamable HTTP MCP ─┐
Browser ─────── HTTP API ──────┼── Local Board server ── SQLite (WAL mode)
                               └── Web UI
```

Each command opens a short SQLite transaction. WAL mode, a busy timeout, foreign keys, and uniqueness constraints provide the storage foundation for multiple local agent processes. Tokens are generated from cryptographic randomness and stored only as SHA-256 digests. The plaintext token is shown once.

The single Local Board server owns `.local-board/state/board.db` in the repository by default. The runtime directory is ignored by Git; future project configuration and agent instructions in `.local-board/` remain trackable. `--db` and `LOCAL_BOARD_DB` override the database location. Agents never open SQLite directly: every worktree connects to the same server URL. Attachments are repository-local path references; Local Board does not copy arbitrary files into its database.

## Install in a repository

Requires Python 3.11 or newer.

```bash
python -m pip install -e /path/to/local-board
cd /path/to/your/repository
local-board init
local-board config validate
local-board config plan
local-board actor alice --kind human
local-board actor coding-agent --kind agent
local-board status
local-board doctor --offline
```

An automated coordinator can request machine-readable bootstrap credentials with `local-board actor coordinator --kind agent --json`. After the server starts, an authenticated admin coordinator can provision a separate least-privilege identity for every subagent through the MCP `create_actor` tool and invalidate/reissue credentials with `rotate_actor_token`. Both commands return plaintext tokens once; capture them without logging and pass them through the orchestrator's secret/environment channel, never through issue comments or tracked files.

Save each displayed token securely. Start the UI and HTTP MCP endpoint:

```bash
local-board serve
```

`init` creates `.local-board/project.toml`, applies it to SQLite, and adds runtime-only paths to the target repository's `.gitignore`. Open <http://127.0.0.1:8765> and enter an actor token. Projects may also be created imperatively through MCP or HTTP when needed:

```bash
curl -X POST http://127.0.0.1:8765/api/projects \
  -H "Authorization: Bearer $LOCAL_BOARD_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"key":"APP","name":"Application"}'
```

## Connect an MCP agent

Start one server for the repository and configure every agent to use its HTTP MCP endpoint:

```text
URL: http://127.0.0.1:8765/mcp
Authorization: Bearer <actor token>
```

Every agent should receive its own token so activity and authorship remain attributable. MCP clients send JSON-RPC to `POST /mcp` with `Authorization: Bearer <token>`, `Content-Type: application/json`, and `Accept: application/json, text/event-stream`. Local Board is sessionless and returns JSON responses; notifications receive HTTP 202.

Available tools cover project and issue discovery, creation and update, workflow transitions, milestones, comments, checklists, labels, dependencies, attachment references, Git links, and activity. Use MCP `tools/list` for the authoritative schemas.

`local-board init` also installs `.local-board/AGENT.md`, a repository-local skill at `.agents/skills/local-board/`, and a root `AGENTS.md` discovery bridge when that file does not exist. It never overwrites existing root instructions, including with `--force`; merge [the provided bridge instructions](examples/AGENTS.md.example) manually when the repository already has an `AGENTS.md`. `local-board doctor` warns when that bridge is not discoverable. Separate onboarding is available in [the human guide](docs/human-guide.md), [the agent guide](docs/agent-guide.md), and [the operations guide](docs/operations.md).

## Human web UI

The local UI renders columns from the selected project's configured workflows rather than a fixed status list. Humans can filter issue types, open complete issue context, claim or release work, assign assignees and reviewers, change priority, complete checklist items, comment, and perform only policy-aware transitions. Project and activity views provide repository-level oversight.

The UI uses stable issue routes such as `/api/issues/APP-12`. REST mutations honor optimistic revisions and return HTTP `409` for stale writes. The same `Board` domain methods back REST and MCP, so workflow, blocking dependency, assignment, and revision rules remain consistent across human and agent clients.

### Agent MCP workflow

The MCP contract is self-discovering and uses stable references instead of requiring agents to know SQLite IDs:

1. Call `whoami`, then `list_projects` and `get_project_context` to discover identities, workflows, labels, milestones, defaults, and agent policy.
2. Search with `list_issues`; fetch the complete Markdown description, discussion, checklist, blockers, attachments, Git links, activity, and allowed transitions with `get_issue_context` using an identifier such as `APP-12`.
3. Call `claim_issue` with the current `revision`, update checklist items and comments while working, and attach dependencies or Git references as needed.
4. Call `transition_issue` with the latest `revision`; stale mutations return a machine-readable `conflict` error and should be retried only after reading fresh context.
5. Call `release_issue` if abandoning work.

Tool input schemas include enums, defaults, constraints, and stable-reference descriptions. Tool errors expose `conflict`, `not_found`, or `invalid_request` codes in `structuredContent.error` instead of requiring agents to parse prose.

## Project as code

`.local-board/project.toml` is the versioned desired state for project metadata, labels, defaults, and per-type workflows. Issues, comments, actors, tokens, activity, and Git links remain operational data in the ignored SQLite database.

```toml
schema_version = 1

[project]
key = "APP"
name = "Application"
description = ""

[defaults]
issue_type = "task"
priority = "medium"

[agent_policy]
require_assignee_before_start = true
require_reviewer_for = ["feature", "bug"]
branch_pattern = "{issue_key}-{slug}"

[[labels]]
key = "backend"
name = "Backend"
color = "#64748b"

[workflows.task]
initial = "backlog"
terminal = ["done", "cancelled"]
states = ["backlog", "todo", "in_progress", "in_review", "done", "cancelled"]
transitions = [
  ["backlog", "todo"],
  ["todo", "in_progress"],
  ["in_progress", "in_review"],
  ["in_review", "in_progress"],
  ["in_review", "done"],
]
```

Use `local-board config validate` for syntax and semantic validation, `config plan` to inspect drift, and `config apply` to reconcile it atomically. Apply is non-destructive: entities omitted from TOML are not deleted. Config-managed workflows and labels have stable keys and every effective apply is recorded with its digest and diff. Removing a workflow state that is used by an issue is rejected.

The configuration schema and SQLite schema are versioned independently. Commit `project.toml` to Git, but never commit `.local-board/state`, `backups`, `attachments`, or `secrets`.

## Workflows

New projects get the following states for each issue type:

```text
backlog → todo → in_progress → in_review → done
   └────────────── any active state ──────────→ cancelled
```

Manual projects may replace states and allowed directed transitions with `set_workflow`. Config-managed workflows must be changed in `project.toml` and reapplied; direct mutation is rejected. Invalid or skipped transitions are rejected transactionally.

## Concurrent agents

Issues carry a monotonically increasing `revision`. Mutation and transition tools accept `expected_revision`; a stale writer receives a conflict instead of silently overwriting another agent's work. Issue identifiers and board positions use transactional counters rather than `MAX(...) + 1`, so concurrent threads and server requests cannot allocate the same value.

Agents should call `claim_issue` before starting work. Claiming atomically assigns the authenticated actor and creates a renewable lease (30 minutes by default); only one actor can claim a given revision. Use `release_issue` to clear a claim. Projects whose `agent_policy.require_assignee_before_start` is enabled reject transitions into `in_progress` until an issue is claimed or assigned.

SQLite still serializes writes internally. Local Board uses WAL mode and a busy timeout, while optimistic revisions protect domain data from lost updates. The concurrency suite exercises simultaneous threads and independent processes and finishes with SQLite integrity and foreign-key checks.

## Git branch linking

Include an issue identifier such as `APP-12` in the branch name and run:

```bash
LOCAL_BOARD_TOKEN=... local-board sync-branch
```

This records the current branch against every matching issue. PR/MR URLs can later be associated through the `add_git_link` MCP tool without granting Local Board access to GitHub or GitLab.

## Security boundaries

The server binds to `127.0.0.1` by default. Every actor has an `admin`, `member`, or read-only `viewer` role; the first actor is the bootstrap admin and later actors default to member. Admins can change roles with `set_actor_role`, and the last admin cannot be demoted. Tokens are still local bearer credentials, so do not expose the server to an untrusted network. Activity is append-only and protected by SQLite triggers as well as the domain API.

## Releases and recovery

Project releases follow `planned → active → released` or may be cancelled before release. Agents can use `list_releases`, `create_release`, and `transition_release`; transitions use optimistic revisions just like issues. A release can be associated with issues through its local `release_id`.

Create a consistent online SQLite snapshot with `local-board backup [path]`. Each backup receives a JSON manifest containing its format, schema version, byte size, and SHA-256 checksum. Restore validates the checksum, SQLite integrity, and required Local Board tables before atomically replacing state:

```bash
local-board backup
local-board restore .local-board/backups/board-20260818T120000Z.db --force
```

Restore automatically writes a pre-restore safety backup when current state exists.
Stop `local-board serve` before restoring so no process retains a connection to the replaced database.

## Development

The runtime has no third-party dependencies.

```bash
python -m unittest discover -s tests/unit -v
python -m unittest discover -s tests/integration -v
python -m unittest discover -s tests/e2e -v
python -m compileall -q local_board tests
```
