Skip to main content
Glama
README.md
# Vibecheck

Vibecheck is a small, passive MCP work ledger for coding agents. It records a shared task plan, session ancestry, claims, work locations, blockers, and commits in SQLite. Agents report changes through nine tools. The board does not run agents, schedule work, execute Git commands, or verify that reported work happened.

## Install the plugin

Use a current Codex or Claude Code client with plugin support. Install `uv` and make it available on the client's `PATH`. The launcher needs Bash on Linux or macOS; Windows users can run it through WSL. Python 3.12 or later is required, and `uv` can provision it. The first launch may download Python and locked dependencies.

For Codex, install the tagged release:

```bash
codex plugin marketplace add mgd34msu/vibecheck --ref v1.0.0
codex plugin add vibecheck@vibecheck
```

These commands use the native [Codex plugin CLI](https://learn.chatgpt.com/docs/developer-commands#codex-plugin).

For Claude Code, install the same tagged release:

```bash
claude plugin marketplace add mgd34msu/vibecheck@v1.0.0
claude plugin install vibecheck@vibecheck
```

Claude supports the `@ref` marketplace shorthand. To follow the repository's default branch instead, omit `@v1.0.0`. See [Claude plugin marketplaces](https://code.claude.com/docs/en/plugin-marketplaces).

Enable the plugin in your client and reload the session if the tools do not appear. The plugin registers its MCP server for the client to start and supplies a shared `vibecheck` skill. There are no startup hooks that register projects or force the skill to run on every first turn.

Ask the agent to use Vibecheck to coordinate a project, report its current work, or recover an earlier plan. Supply a stable project ID and repository identity. The bundled [skill](skills/vibecheck/SKILL.md) guides registration, ownership, status, and recovery when invoked. For a standing project policy, copy [the agent instructions](docs/agent-usage.md) into your project's `AGENTS.md`.

The same repository contains native Codex and Claude plugin manifests and marketplaces. Both clients use the same server and skill. Their local stdio processes share the default database, so using both clients on one machine does not create separate boards.

## Download release assets

The [v1.0.0 release](https://github.com/mgd34msu/vibecheck/releases/tag/v1.0.0) contains:

- `vibecheck-codex-1.0.0.zip`, the Codex plugin bundle.
- `vibecheck-claude-1.0.0.zip`, the Claude plugin bundle.
- `project_board-1.0.0-py3-none-any.whl` and `project_board-1.0.0.tar.gz`, the Python distributions.
- `SHA256SUMS`, checksums for the release artifacts.

Verify downloaded files against `SHA256SUMS` with your platform's SHA-256 utility. Each plugin archive extracts into a `vibecheck` directory with its native manifest and marketplace catalog. For a downloaded Codex archive, register that extracted directory and install:

```bash
codex plugin marketplace add /absolute/path/to/vibecheck
codex plugin add vibecheck@vibecheck
```

For the Claude archive:

```bash
claude plugin marketplace add /absolute/path/to/vibecheck
claude plugin install vibecheck@vibecheck
```

Choose either the GitHub marketplace or the extracted local marketplace for a client. Keep a local marketplace directory available for subsequent plugin management. See [release notes](docs/releases/v1.0.0.md).

## Run from source

```bash
git clone --branch v1.0.0 https://github.com/mgd34msu/vibecheck.git
cd vibecheck
uv sync --locked
uv run vibecheck
```

The Python package remains `project-board`, and the original `project-board` command remains supported. `vibecheck` is an alias for the same server. Existing databases stay compatible.

## Start a local server

For manual MCP client configuration, run from the checkout:

```bash
uv sync --locked
uv run project-board
```

The default transport is stdio. The process waits for an MCP client, so a quiet terminal is expected. Stop it with Ctrl-C when configuring your client.

Use an absolute path to [scripts/run-server.sh](scripts/run-server.sh) as your client's MCP command. Copy [examples/mcp.json](examples/mcp.json) and replace both example paths. This is a generic MCP configuration example; put its command, arguments, and environment into your client's supported configuration format.

All local clients must use the same absolute database path to share a board. Each client may start its own stdio process. Keep SQLite on local disk; use the HTTP server below for clients on different machines. Do not put the database on a network share.

The default database is `$XDG_DATA_HOME/project-board/board.sqlite3`, or `$HOME/.local/share/project-board/board.sqlite3` when `XDG_DATA_HOME` is unset. Set `PROJECT_BOARD_DB` or pass `--database` to choose another file.

## Start a shared HTTP server

Run the server on the machine that holds the local SQLite file:

```bash
read -rsp 'Board bearer token: ' PROJECT_BOARD_TOKEN
printf '\n'
export PROJECT_BOARD_TOKEN
export PROJECT_BOARD_DB="$HOME/.local/share/project-board/board.sqlite3"
export PROJECT_BOARD_PROJECTS='my-project'
uv run --locked project-board --transport streamable-http --host 127.0.0.1 --port 8765
```

Connect an MCP client to `http://127.0.0.1:8765/mcp` with the header `Authorization: Bearer <your token>`. The server requires a token even on loopback. For remote clients, provide HTTPS through your existing reverse proxy and pass `--allowed-host` for its public host. Keep the SQLite file on the server's local disk.

`PROJECT_BOARD_PROJECTS` restricts both transports to the listed comma-separated project IDs. Leave it unset to allow all projects. A configured empty list fails startup. The HTTP token grants access to the configured projects; it does not identify individual agents. Local stdio trusts its caller, and session identities are cooperative self-reports.

## Keep data across upgrades

The plugin launcher uses an isolated `uv` environment in the external uv cache, respecting `UV_CACHE_DIR`. It does not create a `.venv` inside the installed plugin. Ledger data remains in `$XDG_DATA_HOME/project-board/board.sqlite3`, or `$HOME/.local/share/project-board/board.sqlite3`. Plugin replacement or removal does not delete this database. A custom `PROJECT_BOARD_DB` path also remains under your control. Keep the database outside plugin caches.

Pinned marketplace installations stay tied to the selected release. Select the desired release when upgrading. For an unpinned Claude marketplace, refresh the catalog and installed plugin with `claude plugin marketplace update vibecheck` and `claude plugin update vibecheck@vibecheck`, then restart the client. Remove the Claude plugin with `claude plugin uninstall vibecheck@vibecheck`; remove the Codex plugin with `codex plugin remove vibecheck@vibecheck`.

## Tools

| Tool | Purpose |
| --- | --- |
| `project_join` | Register or rejoin a project session with real identity and ancestry. |
| `plan_publish` | Publish the root's complete task inventory. |
| `plan_edit` | Atomically add or update task definitions, dependencies, and lineage. |
| `plan_read` | Retrieve a complete plan revision or compare two revisions. |
| `plan_ack` | Record a session's review of a complete plan revision. |
| `work_claim` | Claim ownership or contribute under a parent's work. |
| `work_update` | Report progress, blockers, integration, release, or handoff. |
| `project_status` | Read compact current state or explicit complete current state. |
| `work_history` | Recover work by task, session, path, branch, or commit. |

## Record work

Copy [the agent instructions](docs/agent-usage.md) into the project's `AGENTS.md`. Give every agent the same project ID and repository identity. The first `project_join` registers that project. Starting the server does not create projects or infer them from its working directory. The root owns and updates the shared plan. Workers claim existing tasks or contribute under their parent's work.

The following examples show MCP `tools/call` parameters. Replace values such as `REAL_VENDOR_SESSION_ID`, `SESSION_ID`, and `WORK_ID` with real runtime identities and IDs returned by the board. Model and effort strings are opaque metadata; use the actual configured values. Revisions below illustrate a fresh board. Always use returned revisions in real calls.

Join the project and retain the returned `session_id` and complete `task_map` from its `snapshot`. If the map is omitted for size, retrieve it with `plan_read`:

```json
{
	"name": "project_join",
	"arguments": {
		"request": {
			"project_id": "my-project",
			"request_id": "join-1",
			"repository": "https://example.com/team/repository.git",
			"vendor": "ACTUAL_VENDOR",
			"runtime": "ACTUAL_RUNTIME",
			"external_session_id": "REAL_VENDOR_SESSION_ID",
			"model": "ACTUAL_MODEL",
			"effort": "ACTUAL_EFFORT"
		}
	}
}
```

Publish the root's task plan:

```json
{
	"name": "plan_publish",
	"arguments": {
		"request": {
			"project_id": "my-project",
			"request_id": "plan-1",
			"session_id": "SESSION_ID",
			"expected_revision": 0,
			"tasks": [{"id": "implement", "label": "Implement the change", "depends_on": []}]
		}
	}
}
```

Claim the task with its current task revision:

```json
{
	"name": "work_claim",
	"arguments": {
		"request": {
			"project_id": "my-project",
			"request_id": "claim-1",
			"session_id": "SESSION_ID",
			"task_id": "implement",
			"expected_revision": 1,
			"location": {
				"checkout": "/absolute/path/to/checkout",
				"branch": "feature/change",
				"target_branch": "main",
				"paths": ["src/change.py"]
			}
		}
	}
}
```

Report a blocker using the work and task revisions returned by the claim:

```json
{
	"name": "work_update",
	"arguments": {
		"request": {
			"project_id": "my-project",
			"request_id": "blocked-1",
			"session_id": "SESSION_ID",
			"updates": [{
				"work_id": "WORK_ID",
				"expected_revision": 1,
				"expected_task_revision": 2,
				"status": "blocked",
				"blocker": "Waiting for the test fixture"
			}]
		}
	}
}
```

Read the shared status with one call:

```json
{
	"name": "project_status",
	"arguments": {"request": {"project_id": "my-project"}}
}
```

Find the task's work attempts and history:

```json
{
	"name": "work_history",
	"arguments": {"request": {"project_id": "my-project", "task_id": "implement"}}
}
```

At natural work boundaries, read `project_status` with your `known_plan_revision`. The response contains fresh operational facts keyed by stable task, work, and session IDs. Reuse the shared definition map instead of repeating the graph on every read. Normal status needs no cursor or page assembly.

Normal status includes active, owned pending, and blocked tasks, work awaiting integration, available unowned pending tasks, and tasks with open contributions. Its complete structured JSON response has a 64 KiB UTF-8 budget. Counts disclose the scope and any omissions. If `limited` is true, `full:true` retrieves all current tasks, current owners, open contributors, all registered sessions, and the complete map. Full status includes no work history.

To recover a lost map, request `include_map:true`. A stale `known_plan_revision` sets `map_changed:true` and requests a replacement map automatically. Maps are all-or-omitted. If `map_omitted` is true, follow `full_hint` with `full:true`, or use `plan_read` for the complete definitions alone.

Edit part of the plan atomically without resending its inventory:

```json
{
	"name": "plan_edit",
	"arguments": {"request": {
		"project_id": "my-project",
		"request_id": "edit-1",
		"session_id": "SESSION_ID",
		"expected_revision": 1,
		"operations": [
			{"op": "update", "task_id": "implement", "label": "Implement and verify the change"},
			{"op": "add", "task": {"id": "review", "label": "Review the change", "depends_on": ["implement"]}}
		]
	}}
}
```

Read a complete definition map at a particular revision. Add `compare_to` to request a diff instead of the map:

```json
{
	"name": "plan_read",
	"arguments": {"request": {"project_id": "my-project", "revision": 2}}
}
```

Only after receiving and reviewing the complete map, acknowledge that revision:

```json
{
	"name": "plan_ack",
	"arguments": {"request": {
		"project_id": "my-project",
		"request_id": "ack-2",
		"session_id": "SESSION_ID",
		"plan_revision": 2
	}}
}
```

The root can change dependencies during work. Each edit validates the resulting graph and retains older definitions in revision history. Optional `supersedes` links record splits or replacements; they do not transfer work or cancel tasks. Acknowledgments record which complete revision each session has reviewed. Reads never acknowledge automatically.

For field rules, retries, handoffs, advanced cursor reads, and history selectors, see [the protocol reference](docs/protocol.md). Status and timestamps describe the latest report, which may be stale. A successful database claim does not prevent another process from editing or committing the same Git files.

## Validate the checkout

```bash
./scripts/verify.sh
uv run --locked python scripts/benchmark.py
```

To build and verify the release artifacts separately:

```bash
uv run --locked python scripts/build_release.py
uv run --locked python scripts/verify_release.py
```

The [release verification record](docs/release-verification.md) covers native
installation, extracted plugin startup, clean wheel installation, all nine MCP
tools, and persistence across restarts.

The [recorded synthetic benchmark](docs/benchmark.json) used 10,000 tasks and 25 sessions through local MCP stdio. Its normal status response was 46,398 structured JSON bytes, with a 56.979 ms median over 20 reads. The complete MCP result was 100,025 bytes because the transport also carries text content. These are measurements from that run, not latency guarantees. See [verification evidence](docs/verification.md) for the combined checks.

The board retains reported metadata, not repository knowledge or conversations. It does not scan the repository to understand code. Session identities and work status are cooperative self-reports; Git commits and actual outcomes require separate verification. Dependencies and `blocking_path` describe the graph without scheduling work or estimating completion time.

TDQS

A3.7/5.0

Scored across 9 tools

Disambiguation5/5

Each tool targets a distinct action within the plan/work lifecycle: joining a session, publishing/editing/acknowledging/reading plans, claiming/updating work, and viewing status/history. There is no genuine overlap that would cause an agent to select the wrong tool.

Naming Consistency4/5

Tool names consistently use lowercase snake_case with an object-first pattern (project_*, plan_*, work_*). Most names follow object_verb, though project_status and work_history are object_noun, creating a minor deviation.

Tool Count5/5

Nine tools is well-scoped for a coordination server covering session joining, plan management, work claiming/updating, and status/history queries. Each tool earns its place without redundancy or bloat.

Completeness4/5

The tool set covers the core plan and work lifecycle: publishing/reading/editing plans, acknowledging revisions, claiming and updating work, and querying status/history. Minor gaps exist, such as no explicit plan deletion or session leave, but agents can work around these in normal workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues