Skip to content
bradymholtPublic

About

A (better) GitHub pull request dashboard

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Shipyard


 Would you take a quick second and ⭐️ my repo?


Shipyard is a focused dashboard for staying on top of GitHub pull requests. It brings reviewer state, CI status, stacked PRs, and the work that needs your attention into one place. Use it directly from GitHub Pages, or run it locally to connect PRs to local branches and open them in your preferred app or IDE.

Quick start

In your browser: open the hosted dashboard, add a GitHub token (saved only in your browser's local storage), then add a repository, organization, or username to your views. Nothing needs to be installed.

On Android, open the menu in Chrome and choose Install app (or Add to Home screen) to run Shipyard as a standalone app. Safari on iOS offers the same through Share → Add to Home Screen.

Locally: run Shipyard on your machine to match PRs to your local clones, open them in your preferred app or IDE, and start branches or worktrees. See Local mode for setup.

Screenshots

Board view

See drafts, waiting work, approvals, and recent merges by stage.

Shipyard board view

Review board

Track the PRs you owe a review, split into what's still waiting on you and what you've already reviewed, with counts and pending-review indicators.

Shipyard review board

GitHub token

A fine-grained personal access token limited to the repositories you use is recommended. Pull requests read access is enough for viewing; write access is needed to toggle auto-merge or mark a draft ready for review. A classic token needs the repo scope for private repositories.

Your token and recent dashboard data stay in your browser's local storage. The token is sent only to api.github.com. The hosted and local versions use separate browser storage, so each needs to be configured once.

Features

  • Action-focused views: My PRs and Reviews, with priority, updated, and created sorting.
  • Board layout: reviewer state, new commits since your review, drafts, approvals, and ready-to-merge work at a glance, with lanes that stack and collapse on a phone.
  • Useful context: CI checks, labels, comments, stacked PR relationships, and your three most recently merged PRs.
  • Flexible scope: combine repositories, organizations, and usernames, then filter across titles, authors, branches, and repositories.
  • PR actions: toggle auto-merge and move drafts to ready without leaving the dashboard.
  • Optional local workflow: open existing checkouts in your preferred app or IDE, or start a branch in the main clone or an isolated worktree.

Local mode

Local mode runs shipyard.py, an optional companion process that serves the dashboard, opens checkouts in your preferred app or IDE, and adds branch/worktree actions. It requires Git and Python 3.

git clone https://github.com/bradymholt/shipyard.git
cd shipyard
python3 shipyard.py ~/dev

Then open http://localhost:4321. Replace ~/dev with a folder that directly contains your Git clones; you can pass more than one folder or use --port to choose another port.

On macOS, you can keep it running in the background instead. Copy the example config, set roots to your folders, and install it as a login agent:

cp shipyard.config.example.json shipyard.config.json
./shipyard-launchd.py install

See Run at login (macOS) for details.

The companion matches GitHub PR branches to clones found under your configured folders. It binds to localhost and accepts branch actions only from the dashboard it serves.

Worktree discovery is read-only. Actions you choose can fetch, create, or switch local branches and create worktrees. Shipyard refuses to switch a main clone with tracked changes, opens an existing checkout when one already owns the branch, and never removes existing worktrees. New worktrees are created under <repo>/.claude/worktrees/.

For a persistent setup, copy the example configuration and adjust roots:

cp shipyard.config.example.json shipyard.config.json
python3 shipyard.py
{
  "roots": ["~/dev"],
  "launcher": {
    "name": "VS Code",
    "mode": "url",
    "target": "workspace",
    "url": "vscode://file/{path}",
    "command": ["code", "{path}"]
  },
  "branchPrefix": ""
}

VS Code is the default, but the launcher is app-agnostic. URL mode opens a custom URL scheme in the browser; command mode asks the companion to run a command. Use {path} where the checkout path belongs. target can be folder, or workspace to prefer a .code-workspace file when one exists.

For example, this opens the checkout folder in Xcode on macOS:

{
  "launcher": {
    "name": "Xcode",
    "mode": "command",
    "target": "folder",
    "command": ["open", "-a", "Xcode", "{path}"]
  }
}

Resume a coding agent

When a checkout has a recent coding-agent session, a second icon next to the open icon resumes the latest one. Claude Code is the default:

{
  "agent": {
    "name": "Claude Code",
    "sessions": "claude-code",
    "mode": "url",
    "url": "claude://resume?session={session}",
    "command": ["open", "claude://resume?session={session}"]
  }
}

sessions picks where to look for transcripts: claude-code reads ~/.claude/projects/, and codex reads ~/.codex/sessions/. The companion matches sessions to checkouts by working directory and uses the most recently written one. mode works as it does for the launcher; {session} is the session id and {path} the checkout path. Set "agent": null to hide the icon.

branchPrefix optionally prefills new branch names.

Run at login (macOS)

Keep the companion always running with a launchd agent

shipyard-launchd.py runs the companion as a launchd user agent, so it starts at login and comes back if it exits.

./shipyard-launchd.py install

That installs two agents, using absolute paths taken from this checkout: local.shipyard runs the companion, and local.shipyard-restart watches shipyard.py and shipyard.config.json to reload it when you save. install then confirms the companion actually stayed running rather than crash-looping. Re-run it after moving the repo, upgrading Python, or creating your config.

./shipyard-launchd.py status     # state, pid, restart count, log sizes
./shipyard-launchd.py restart
./shipyard-launchd.py logs -f
./shipyard-launchd.py uninstall

Output goes to ~/Library/Logs/shipyard.out.log and shipyard.err.log. The plists are ordinary launchd agents, so read or tweak them directly if you want different settings. Saving a plist is not enough on its own, though: launchd only picks up changes at login or through install.

If a plist in ~/Library/LaunchAgents is a symlink, something else already owns it (a dotfiles repo, say). install leaves those files alone and just loads them, so it stays useful for starting agents your own setup only symlinked into place, and uninstall stops them without deleting anything it did not write.

Development

There is no build step or dependency installation. Serve index.html with python3 -m http.server, or run python3 shipyard.py ~/dev to exercise local mode. Issues and pull requests are welcome.

License

Shipyard is available under the MIT License.

About

A (better) GitHub pull request dashboard

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages