A derived, rebuildable Postgres index of ship artifacts (.reports/**) and lessons across your repos — with a web UI and an MCP server so coding agents can search past runs, decisions, problems, and lessons before implementing.
This is a GitHub template repository: click Use this template to create your own copy, then follow the runbook below. The index is fully derived — you can drop the database and rebuild it from your source repos at any time.
Source repos commit ship artifacts (a report-data.json per shipped run, plus lessons). A GitHub Action in each source repo ingests changed artifacts into Postgres on push to main. This repo serves a web UI over the index and an MCP endpoint at /api/mcp. The artifact format is documented in docs/artifact-format.md, with working examples in packages/core/fixtures/fake-repo.
pnpm install
docker compose up -d # local Postgres (or point DATABASE_URL anywhere)
cp .env.example .env
pnpm shiplog migrate
# ingest the bundled demo fixture to see it working
pnpm shiplog ingest --repo demo --path packages/core/fixtures/fake-repo --lessons-format files
pnpm dev # web UI on http://localhost:3000Without Google OAuth credentials the app runs with auth disabled (fine locally; do not expose a deployment that way).
DATABASE_URL: Postgres connection string. Local docker or a Neon pooled URL. (required)SHIPLOG_MCP_TOKEN: bearer token required by/api/mcp. Generate a long random string. (required for MCP)BETTER_AUTH_SECRET: auth secret, e.g.openssl rand -base64 32. (required in production)BETTER_AUTH_URL: canonical auth origin, e.g.https://shiplog.example.com. (required in production)GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET: Google OAuth credentials. Unset = auth disabled. (optional)ALLOWED_EMAIL_DOMAIN: restrict sign-ups to one email domain, e.g.example.com. Unset = any Google account. (optional)TEST_DATABASE_URL: integration-test DB; DB tests are skipped when unset. (optional)
Copy .env.example (CLI) and apps/web/.env.example (web) as starting points. The CLI also falls back to ~/.shiplog.env when DATABASE_URL is unset.
- Create the repo from this template and clone it.
- Edit
shiplog.repos.jsonto list your source repos (name, local path for backfills, issue-key prefix, lessons format). - Create a Postgres database (e.g. a Neon project) and run
pnpm shiplog migrate. - Backfill history:
pnpm shiplog backfill --allfrom this repo root, with source repos cloned at the paths inshiplog.repos.json. - Deploy
apps/web(e.g. Vercel) withDATABASE_URL,SHIPLOG_MCP_TOKEN,BETTER_AUTH_SECRET,BETTER_AUTH_URL,GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET, and optionallyALLOWED_EMAIL_DOMAIN. - If this repo is private and your source repos are in the same org, enable Settings -> Actions -> General -> Access -> "Accessible from repositories in the organization" so they can use the composite action.
- In each source repo: add secret
SHIPLOG_DATABASE_URLand copyintegration/shiplog-ingest.ymlto.github/workflows/, filling in the placeholders. - Register MCP clients (see below).
If cross-repo action access is unavailable, vendor .github/actions/ingest/action.yml into each source repo instead.
The Next route at /api/mcp uses mcp-handler with static bearer auth (Streamable HTTP). Register it with your MCP client, e.g.:
claude mcp add --transport http shiplog https://<deployment>/api/mcp \
--header "Authorization: Bearer <SHIPLOG_MCP_TOKEN>"Tools:
get_run: one shipped run by issue key with decisions, problems, gates, lessons, filessearch_lessons: lessons by tech/topic, e.g. "branch reset password"search_problems: past problems and resolutions, filterable by statussearch_decisions: architectural choices ranked by text searchsearch_runs: run summaries by topic, issue, or arearuns_touching: runs that touched a path fragmentrecent_runs: newest runs with decision/problem countsgate_stats: gate pass rates, durations, recent failures
pnpm checks # lint + typecheck + tests across the workspaceDB integration tests run only when TEST_DATABASE_URL is set (the bundled docker-compose.yml creates a shiplog_test database for this). Node and pnpm versions are pinned in .nvmrc / package.json (packageManager); workflows read .nvmrc, but the pnpm version in .github/workflows/checks.yml and .github/actions/ingest/action.yml must be kept in sync by hand.
MIT