I closed a production client ticket from a repo that did not own it, and I did it deliberately. I had wrapped morning passes on a pair of tickets, moved on, and one came back approved. No grand architecture exercise planned.

But I was already in the middle of something that had been surfacing a problem for several weeks. Work on a content-system handoff and a multi-agent architecture sketch had made a gap visible: every time I moved between repos, the agent was re-deriving context. The skills I had built inside a specific git checkout lived at the checkout level. So did the runbooks, the incident prompts, the close sequence. Take the work to a different machine or open a fresh session in a different tool, and none of it came along.

I had been setting up a new station repo on the desktop machine to act as the personal agent layer sitting above any single project. That day I found out whether the idea held.

the first failure was a path problem

I tried to add a working directory to an active Claude Code session using /add-dir. In the CLI it worked. In Cursor’s Claude Code panel it did not. The skills wired to one checkout did not transfer to the new session context.

I had assumed the skill surface was portable because it felt portable from inside the session where I built it. It was not. Skills attached to a repo checkout travel exactly as far as that checkout. If the session starts somewhere else, or the agent hands off between tools, the runbook is gone. What remains is whatever the agent can re-derive from the conversation, which is slower, noisier, and prone to small divergences from the real sequence.

That constraint forced the architecture decision.

the architecture that came out of it

Shared operational skills belong at a higher tier than any single repo. The operator surface, the thing that knows how to open a JIRA ticket, cut a branch, close a ticket, and write the session log entry, should live above any individual checkout, above the knowledge store, above whatever repo the actual work happens to be in.

The station repo became that layer. It is a Python package installed editable on the desktop, with a CLI that dispatches to skill modules. A session started here can reach any project checkout without pulling in their per-repo runbook history.

The constraint I imposed: nothing in the station repo duplicates what lives in the target repos. The runbooks for the production app stay in their own checkout. The station invokes them. It does not own them. That line is easy to violate when you are moving fast, and violating it is how you end up with two slightly different versions of the same procedure with no canonical source.

closing the ticket from the wrong repo

Once the layer was in place, I wanted to run a real ticket through it. The approved ticket was waiting. I ran the full close sequence from a station session: JIRA API to transition the ticket state, git CLI to verify branch and merge state, a knowledge-store write for the session log.

I never opened a native Claude Code session inside the repo that owned the ticket. The work finishing from outside was the whole point.

The JIRA transition went through. The session log landed. The ticket closed clean. The proof was not that it was faster or cheaper than the old way. The proof was that the operation was not coupled to the repo anymore.

what got built on top

Once the close worked, the follow-on was obvious. I built the first real skill family: a skill to open a session on a ticket with the right context preloaded, another to finish one with JIRA transition plus knowledge-store write, one to reconcile dashboard state, one to write a work entry, one to surface what should happen next. Each skill is a markdown file that orchestrates calls through the station CLI.

Then I wired the station reachable from the phone over Tailscale SSH. The same CLI surface that runs in VS Code also runs over a mobile terminal. Not because I needed it that day, but because if the station is the thing that finishes production work, it needs to be reachable from wherever the work surfaces.

By evening, operational primacy had shifted. The content pipeline still runs on a separate box. The thing that tracks work, routes decisions, and closes tickets runs on the desktop station now.

what I had wrong before

I had been treating per-repo Claude Code sessions as the natural unit of AI work. Open a session inside the repo you are touching, context is right there, everything is inline. That model holds until you have three repos in flight, a knowledge store that needs updating, and JIRA state that neither repo knows about.

The problem is not per-repo sessions. The problem is that the orchestration logic kept leaking into them. Every session was re-learning the ticket numbering conventions, the branch naming rules, the close sequence, the field names. None of that belongs in any individual checkout. It belongs one level up, in a stable location that every session can call instead of re-derive.

Here is the test I would run before trusting any shared operator layer: close one real ticket without opening the repo that owns it. If the close sequence can verify the git merge state, fire the actual JIRA transition, and write the session log, all from outside that repo, the layer is real. If any one of those three steps still needs you inside the checkout, it is not done yet.