Colorfield logo

Stackcurious

Published on

Four Claude Code mods: GitHub CI, Lagoon builds, local ports and the session at a glance

Authors
An illustration of a Claude Code terminal with the four mods. On the left, the chat, and a port-guard warning that port 3000 belongs to another project's TanStack Start dev server, with a suggestion to run serve -p 7777. On the right, a CI pane for PR #12 with a failed Playwright check ('expected 3 cookies, found a gingerbread man') and an 'Ask Claude to fix' button, and a Lagoon pane with a branch deploying, production marked in red and a cluster maintenance line. At the bottom, the session status line with context, model, branch, rate limit, cost and CI progress, and in the corner a toast: 'Lagoon · pr-41 built in 4m08s'.

Most of my day now happens in Claude Code, in a terminal, often with a few sessions open on different projects. For me, developer experience is mostly a matter of small interruptions. Switching to the browser to see if CI passed. Opening the Lagoon dashboard to follow a deploy. Wondering how full the context is before a long task. Or finding out that the dev server of another project has just been killed, because it was sitting on the port Claude wanted.

Each of these takes a few seconds, and each one breaks the thread. Claude Code can be extended with mods, small modules that react to the session's events and can draw a pane, a status line or a notification. So I wrote four of them, each with a single job. They are open source (MIT), written in TypeScript, and each one installs from its own repository.

One shape for all four

A mod is a hooks module with a register function that subscribes to events: the start of a session, a slash command, a tool call, the end of a step. The four mods share the same layout. The parsing and the formatting live in small pure files, tested on their own, and only the register file talks to Claude Code.

Two rules came out of writing them. Anything slow, like an API call, runs in the background while Claude keeps working, and the pane updates when the answer comes back. And when something goes wrong in a mod, it steps aside and the original command carries on.

ci-watch: the checks of the current branch

claude-ci-watch watches the GitHub checks of the pull request of the current branch, or its latest workflow runs when there is no pull request yet.

/ci opens a pane with every check, its link and its duration, failures first. While checks run, the status line counts them: CI PR #12 ● 3/5 done. When the run settles, a notification says whether CI passed, or names the checks that failed.

When Claude runs git push, gh pr create or gh run rerun, the mod looks again sooner: every 20 seconds while checks are pending, then every two minutes. It reads the branch straight from .git/HEAD, worktrees included, so polling costs no git process.

When a check fails, the pane offers an Ask Claude to fix button. It fills the prompt with the failed checks, their links and a short instruction: read the failed logs with gh run view --log-failed, find the cause and fix it. The prompt is filled without being sent, so there is room to add a word before pressing Enter.

It needs an authenticated gh.

lagoon-watch: the environments of a Lagoon project

Lagoon is the open-source hosting platform from amazee.io. claude-lagoon-watch shows the environments of the current project next to the chat.

/lagoon opens a pane with the environments: the current branch first, then production, drawn in red, then the most recently built. For the current environment and any environment being built, the pane shows the build step, its duration, a link to the build log and a link to each service. It also remembers the last command Claude ran against an environment, a lagoon … -e or a drush @lagoon.…, with its outcome, in red when it targeted production.

A notification announces each build, and another one its end, with the duration or the failed step, and the link to the log. While a build runs, the status line follows it: Lagoon ● <env> <step> <duration>. After Claude runs git push or lagoon deploy, the pane reads the API every 20 seconds for a quarter of an hour, to catch the build as soon as it starts.

The pane also reads the platform's status page. It shows the cluster the project runs on, its open incidents and its next maintenance window, and the windows of the other regions on demand, in the local time zone.

Finding the project takes a few steps. The mod reads project: in .lagoon.yml, then asks Lagoon which project owns the git remote. Failing that, it collects candidate names from the Drush aliases, LAGOON_PROJECT in the env files or the repository name, and keeps a name only if Lagoon confirms that this repository belongs to it. /lagoon <project> sets the project by hand, remembered per git remote.

The mod has no credentials of its own: it goes through the lagoon CLI and its login, and queries the GraphQL API with lagoon raw.

session-line: the session at a glance

claude-session-line pins a status line under the prompt.

ctx 42% 84k/200k · opus 5.5 · high · ⎇ main (worktree) · 5h 63% · $1.23

From left to right: how full the context is, the model and the effort, the git branch (and whether it is a worktree), the rate-limit windows once they are half used, and the cost of the session. The context gets a ▲ at 70% and a ⚠ at 85%. At 85%, a toast also suggests running /compact now, while there is still room for a good summary.

The line has no polling. It refreshes after each step of a turn, after /model, /effort, /compact, /clear or /resume, and after Claude switches branch.

port-guard: the dev servers of other projects

claude-port-guard is for a machine where several projects live together. Several projects run side by side on my machine, and they all want the same ports: 8888 for drush serve or netlify dev, 3000 for serve or a TanStack Start dev server. When Claude finds a port taken, its first idea is to free it, and the server of another project goes down. Playwright is sneakier: with reuseExistingServer, a test suite happily runs against whatever answers on the port, which can be another site entirely.

Before Claude starts a server, kills a process or runs playwright test, port-guard checks who owns the port. lsof gives the process listening on it and its working directory; when the listener is Docker, docker ps gives the directory of the Compose project. If the port belongs to the current project, the command goes through. If it belongs to another one, starting a server is refused with a hint (drush serve :7777), and killing or testing asks for my explicit yes.

The quoted parts of a command are ignored, so a commit message that mentions serve goes through untouched. If the check itself fails, a toast says the command was not guarded.

Install

Each repository is its own marketplace, so a mod installs in one line from Claude Code:

/plugin install ci-watch --marketplace colorfield/claude-ci-watch
/plugin install lagoon-watch --marketplace colorfield/claude-lagoon-watch
/plugin install session-line --marketplace colorfield/claude-session-line
/plugin install port-guard --marketplace colorfield/claude-port-guard

ci-watch needs gh, lagoon-watch the lagoon CLI, and port-guard lsof (macOS and Linux).

They are small tools, and they fit the way I work. If they fit yours too, or if something is missing, the issues are open on each repository.