GitHub as the source of truth for client engagements

How we manage client relationships with the same Goals, Problems, and specs we use to ship code.

Table of Contents

Most consulting engagements have a fragmentation problem. The contract lives in email. The backlog lives in Notion or Linear. Status updates happen in Slack. Time gets logged in a spreadsheet, or not at all. Nobody has the full picture in one place, and nobody agrees on what the full picture even is.

We moved all of it to GitHub — and the same workflow we use to ship code now runs every client relationship we have.

One repo per customer

Each client gets a private repository: customer-{name}. It follows the same Goal → Problem → Solution structure we use in every product repo.

A Goal issue is the top-level object. It represents the business aim: what we are trying to achieve for this customer and by when. Every problem, conversation, and decision lives under it.

Problems are child issues. They describe specific blockers — a contract that hasn't been signed, a team member who's the only developer, an ambiguity about whether the engagement is continuing. Each one gets a proposed solution in the issue body before anyone starts working on it.

The Goal issue body stays minimal: org links, ETA, and a link to the spec.

Specs for context, not just code

In product repos, a spec describes unimplemented behavior — a file that shrinks as features ship, deleted when the Goal is complete. That pattern is described in detail in The Spec That Shrinks.

In a customer repo, the spec serves a different purpose. It is a running record of the engagement: what's happening, what's at risk, what needs to happen next. It does not shrink — it grows as the relationship evolves. Each section maps to an open problem or an active goal. A section about a stalled contract sits next to a section about a team risk. Both are in one file, in one repo, readable by anyone on the account team.

The file lives at docs/specs/{customer}.md, committed via PR so every change is reviewed and versioned. Same location, same discipline — different lifecycle.

Time tracked where the work lives

Work on a client engagement produces pull requests — spec drafts, issue triage, onboarding docs. Time gets submitted on the PR, not in a separate system.

The wizard bot accepts @holdex pr submit-time 2h30m in any PR comment. The format is short: 15m, 1h, 2h30m. No spreadsheet. No end-of-week reconciliation — time is logged on the PR when the work happens, not collected into a separate summary at the end of the week. The log is attached to the artifact that produced it.

Why the same tool matters

The most important property of this setup isn't convenience — it's coherence.

The people doing the client work are the same people using GitHub every day for product development. There's no context switch. When a developer needs to understand the state of the engagement, they open GitHub. When an account manager needs to log a decision, they open GitHub. When a partner needs to see what's at risk, they open GitHub.

A Slack message disappears. A Notion page drifts. A GitHub issue with a linked spec and a comment trail is auditable, searchable, and connected to every PR that touched it.

The engagement has the same shape as the product work: Goals at the top, Problems underneath, Solutions as pull requests. That consistency is not an accident — it's what makes the system usable across roles and across time.

Have a suggestion?Edit this page