shiplog

Log what you ship.

A single-binary CLI that crawls your repos, summarizes the work in your own voice with the AI of your choice, and stores it where you own the data.

# a typical scan $ shiplog scan --since=7d shiplog scan — 6 repo(s), model=claude-sonnet-4-6, sinks=[local + r2:my-bucket] (since 2026-04-28 09:00) == ~/code/storefront == -- 2026-W18 · you@example.com -- Shipped a complete password reset flow, including "forgot password" and "reset password" pages. Wired up a captcha on the auth forms. Migrated several type definitions from numbers to strings to support UUIDs, and refreshed the marketing page above the fold. == ~/code/notes-app == -- 2026-05-04 · you@example.com -- Cleaned up the search index so deleted notes drop out of results immediately instead of waiting for the nightly rebuild. Added keyboard shortcuts for the sidebar.

what it is

shiplog watches your code directory, groups commits into bundles (per‑day, per‑week, per‑commit — your call), runs each bundle through an AI to write a short, human summary in your voice, and stores the result as a changelog.json in ~/.shiplog/. Sinks publish copies elsewhere — Cloudflare R2, S3, a CSV mirror for spreadsheets — but the local file is the source of truth.

It’s a single Go binary. No daemon required (though one is included). No SaaS, no telemetry, no account. Bring your own AI key (Anthropic, Gemini, OpenAI, or Ollama for local).

install

$ curl -fsSL https://shiplog.life/install.sh | sh

macOS & Linux, amd64 & arm64. Drops shiplog in ~/.local/bin (or /usr/local/bin with sudo). The script verifies a sha256 against the published checksums before installing. macOS binaries are signed and notarized so Gatekeeper doesn’t prompt.

Pin a version with SHIPLOG_VERSION=v0.1.0, change the install dir with SHIPLOG_PREFIX=/path. Confirm with shiplog --version.

first run

One wizard. Pick your identity (the git email that counts as “you”), the directory shiplog should crawl, and the AI provider it should call.

$ shiplog setup identity you@example.com code roots ~/code AI provider anthropic · claude-sonnet-4-6 schedule every 1h (daemon) · Paste your Anthropic API key. Stored in macOS Keychain, never in config.json. ********************************** setup complete. try shiplog scan --dry-run to see what it’ll crawl.

the four commands you’ll actually use

shiplog scan

Walks every tracked repo since the last scan, groups new commits, summarizes them, writes to ~/.shiplog/changelog.json, and fans out to any configured sinks. Cursor-driven by default — only new work gets summarized.

$ shiplog scan shiplog scan — 6 repo(s), model=claude-sonnet-4-6, sinks=[local only] · ~/code/storefront (main, 2 commit(s), 1 bundle(s)) · ~/code/notes-app (main, 7 commit(s), 1 bundle(s)) · ~/code/portfolio (main, 0 commit(s)) — up to date == ~/code/notes-app == -- 2026-05-04 · you@example.com -- Cleaned up the search index so deleted notes drop out of results immediately instead of waiting for the nightly rebuild. Added keyboard shortcuts for the sidebar. 2 entries written. cursor advanced.

Useful flags:

shiplog log

Browse what you’ve shipped. Interactive on a TTY, flat list when piped.

Ship log 40 total ▸ 1w Notes App Search now drops deleted notes immediately. 2w Storefront Password reset flow shipped 3w Notes App Sidebar keyboard shortcuts 4w Storefront Previously, an abrupt checkout error was silent… 1mo Portfolio Refreshed the marketing page above the fold. 1mo Portfolio Site now adapts to your system's light or dark… ↑↓ Move Enter Open E Edit D Delete / Filter ? Help Esc Back

Highlight a row and press e to edit, d to delete. / filters by project, tag, or note text.

shiplog add

Manual entry — for shipping things that aren’t commits (a launch, a talk, a write-up). Same shape as the AI-generated entries, written to the same changelog.

$ shiplog add · Project Notes App · Note Wrote up the search-index rewrite for the team blog. · Tags writing, milestone · Media (none) entry written. published to: local, r2:my-bucket

shiplog status

What does shiplog know about right now? One row per tracked repo, with last-scan age and pending work.

$ shiplog status AGE REPO ENTRIES PENDING SOURCE 2h ~/code/notes-app 18 — roots 2h ~/code/storefront 7 — roots 2h ~/code/portfolio 12 — roots 1d ~/code/cli-tool 24 3 roots never ~/code/sandbox 0 — roots

configuration

Everything lives in ~/.shiplog/:

shiplog ai

Pick your provider, paste your key. Keys go to the macOS Keychain — never to config.json.

$ shiplog ai setup · Provider [anthropic] gemini openai ollama · Model claude-sonnet-4-6 · API key ********************************** stored in Keychain as shiplog:ai:anthropic test call returned 27 tokens in 0.9s

shiplog sink

Sinks publish your changelog elsewhere. The local file is always written; sinks are extras.

$ shiplog sink add r2 · Cloudflare account id aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa · Bucket my-bucket · Public host data.example.com · R2 access key id ********** · R2 secret access key ********** added r2 sink (bucket=my-bucket) credentials in Keychain as sink:r2:my-bucket:*

Supported today: file, csv, r2, s3. CSV writes a UTF-8 BOM + CRLF Excel-friendly mirror. Webhook + SFTP are planned.

shiplog repo

Decide what gets crawled. Anything under your roots is auto-discovered; repo add tracks something outside, repo ignore excludes one.

$ shiplog repo list REPO GRAN TRIGGER LAST ~/code/storefront per-week any-commit 2h ~/code/portfolio per-week any-commit 2h ~/code/notes-app per-day any-commit 2h ~/code/cli-tool per-day merge-to-main 1d

what shiplog won’t do

operating it

Run shiplog daemon to scan on a schedule (default every hour). Or run it as a launchd / systemd unit. Or wire it into a git post-push hook if you only want manual triggers. The CLI is the same in every mode.

$ shiplog daemon shiplog daemon — every 1h, pid 47213 ── 2026-05-05 09:00:01 ── shiplog scan — 6 repo(s), model=claude-sonnet-4-6, sinks=[local + r2:my-bucket] · ~/code/notes-app (main, 3 commit(s), 1 bundle(s)) · 5 other repos — up to date 1 entry written.

If anything looks off, shiplog doctor checks the lot — config, AI key, Keychain, git, sinks — and tells you exactly what’s broken.