Kickoff
Eleven days. That’s how long it took after April’s persona→harness rename for the idea to jump products.
April 6th: ynh renames its whole world around harnesses. April 17th: my IDE grows a harness sidebar — detect, install, launch, manage. A day after that: a marketplace browser and a creation wizard. Once the concept had its right name, it moved like it had been waiting by the door with its coat on.
7aac3c4 refactor: rename persona → harness across entire codebase
8d4570e0feat(harnesses): YNH harness sidebar — detect, install, launch, manage (#142)The Run
What’s actually in the box
Here’s the idea, concretely. A harness in my world is a versioned package containing everything that turns a bare model into your agent: the skills and rules that steer it, the scripts and binaries it may run, the hooks that fire on lifecycle events, the MCP servers it can call, and the launch profiles that compose them into moods — a planning focus, a gitflow-strict dev focus, a docs focus. ynh install <name> and that whole environment materialises, vendor-neutral, launching Claude or Codex or Cursor alike.
The point isn’t any one feature; it’s the category shift. Prompts are text you share by paste. Environments are software: they get versions, dependencies, forks, publishing — and, the one that matters most at team scale, drift detection. When someone customises a shared harness, that’s not a divergence crisis; it’s a fork with provenance, visible, mergeable, manageable. Every problem your team already knows how to solve with packages replaces a problem nobody knows how to solve with pasted prompts.
One repo, three storefronts
Where did all these packages actually live? In a repo I called assistants, and its history is the packaging story in miniature. Scaffolded mid-March as a home for “plugins, shared skills, and ynh personas” (that word again, three weeks before the rename put it out of a job), it became the proving ground where every idea in this post got exercised against real content. Every plugin in it carries three manifests side by side — one for Claude Code, one for Cursor, one for ynh — so the same GitHub repo serves as a marketplace for all three. Write the skill once, ship it to every storefront.
Initial scaffold: plugins, shared skills, and ynh personas
Add cross-vendor support for Cursor and Codex
feat: migrate from plugin.json + metadata.json to harness.json— one day after the renamefeat(marketplace): add ynh plugin to Claude and Cursor marketplaces (#6)
That repo also kept me honest. Because it tracked ynh’s format from the outside, every breaking change I shipped in ynh had to be absorbed there within days — it was the migration test I couldn’t skip. Eventually I made that official: the assistants content became the fixture corpus for ynh’s end-to-end test suite. The sample repo wasn’t a demo of the system; it was part of the system, quietly doing load-bearing work while I described it, in meetings, as “just some examples.”
The loops close
By May, the loops were closing in ways that told me the model was right. The ynh repo is itself an installable harness — it dogfoods its own format. TermQ, the IDE, is developed inside a termq-dev harness — Swift-aware, gitflow-strict — that TermQ itself installs and launches. I keep a small stable of them now, built from shared skill bundles like dev-skills and gitflow: a planner persona for architecture sessions, per-project dev harnesses, each a composition rather than a copy. My diagnostics exports show the IDE shelling out to ynh at launch — two years of ideas, calling each other in a stack trace, like a family reunion nobody organised on purpose.
And the graduation flow from Post 8 came full circle in June: TermQ gained “Publish to Repository” — take the local harness you’ve been quietly perfecting and promote it to a shared repo, workshop to product, as a feature rather than a discipline.
What the package can’t carry
Back in April, across the AI Weeks, I watched the new-joiner test run for real, on nine or ten people at a time. The work baseline already had the one-command install. It worked. It was also nowhere near the most expensive step.
The expensive steps were outside the package entirely: repository write access, secrets permissions, data-source approvals, a model gateway to request. Half a day here, two days there. And one thing inside the package broke on the way through: installing the skills as a plugin renamed them into a namespace, and every skill that referred to another skill by its old name quietly stopped composing.
So the honest version of the test has two numbers, not one: the steps your package absorbs, and the steps it can’t.
The Debrief
This is the distribution stage:
On The Training Ground
The New-Joiner Test. One number, measured before and after: how many manual steps from a fresh clone to a fully-equipped agent session. Everything in this post — packaging, composition, drift — falls out of trying to make that number smaller.
Info
You’ll need: your team’s main repo, a way to simulate a fresh machine (a new clone in a clean directory is enough; a colleague’s actual laptop is better), and about ninety minutes across two sittings.
Fresh clone, clean directory, and count every manual step until an agent session works the way your team’s best-equipped person’s does:
git clone <repo> /tmp/joiner-test && cd /tmp/joiner-testCount: copy whose CLAUDE.md from where? Which skills folder, from whose dotfiles? Which MCP servers, configured how? Which env vars, documented where? Which access requests, approved by whom, taking how long? Write the number and the list down. Typical honest answer: 8–15 steps, three of which live in one person’s head.
From the list, find the cluster that’s most-copied and least-owned — usually the shared skills/config everyone has slightly different versions of. That’s your first package.
One shared repo, one-command install, using whatever your stack already does — git submodule, npm package, plugin marketplace, or a plain install.sh that symlinks. No new infrastructure; the packaging format matters less than the properties it buys you:
- versioned — “we’re on skills v3” is a sentence people can say
- one command —
./install.shor/plugin install team-skills - owned — the repo has a named maintainer and a review gate
Fresh clone again, count again. The number drops by however many steps your package absorbed. Repeat with the next-worst chunk when you have another half hour — the curve flattens fast toward “clone, install, work”.
Packaging forces the conversations that matter, so have them in the open: what’s shared vs personal (the team package carries no one’s pet aliases), and compose vs copy (thin team-specific layers over shared bundles, never forty forks of everything). Write both decisions into the package README — that’s your drift policy, version one.
Tip
What you just proved: an agent’s environment can be an installable artifact, and the new-joiner number is the metric that keeps everyone honest about it. When someone customises the shared package, that’s not a crisis — it’s a fork with provenance, and now you have the vocabulary and the tooling shape to manage it.
Unrelated, or possibly not: I own three identical black phone chargers, bought independently, on three separate occasions, because I could never remember whether I already owned one. No versioning. No registry. No ynh list. Just a drawer, and my own unshakeable conviction, each time, that this was a gap in my life that needed filling.