Skip to main content
Glama

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:

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

These commands use the native Codex plugin CLI.

For Claude Code, install the same tagged release:

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.

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 guides registration, ownership, status, and recovery when invoked. For a standing project policy, copy the agent instructions 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 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:

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

For the Claude archive:

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.

Run from source

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:

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 as your client's MCP command. Copy 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:

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 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:

{
	"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:

{
	"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:

{
	"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:

{
	"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:

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

Find the task's work attempts and history:

{
	"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:

{
	"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:

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

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

{
	"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. 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

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

To build and verify the release artifacts separately:

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

The release verification record covers native installation, extracted plugin startup, clean wheel installation, all nine MCP tools, and persistence across restarts.

The recorded synthetic benchmark 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 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.