Skills as a git repo you never clone
How Korvai serves a dynamically-generated git repository over HTTP so Claude Code auto-updates your skills as slash commands — no clone, no copy-paste, no manual sync.
Claude Code plugins install from a git repository. That's the whole distribution model: point Claude Code at a repo with a marketplace.json, and it clones the plugin and auto-updates it on launch.
The obvious way to ship user-authored skills into that system is to have each user create and push a real git repo. That's a lot of friction for someone who just wants their SOPs available as /korvai:<slug> slash commands. So we did something different: the git repository doesn't exist on disk. We generate it on the fly, per request, over the HTTP smart protocol.
The problem with a real repo per user
If every user's skills lived in an actual git repository, we'd be running a git host: provisioning repos, handling pushes, storing packfiles, garbage-collecting, managing auth per repo. All so Claude Code can git fetch a handful of Markdown files that already live in our database.
The skills are already structured data in Postgres. Turning them into a checked-out repo, storing that, and keeping it in sync with the database is pure overhead. The repo is a view of the data, not a separate source of truth.
Serving git over HTTP without a git host
Git's "smart HTTP" protocol is just a few endpoints:
GET /info/refs?service=git-upload-pack— advertise the refs (branches) and their commit SHAs.POST /git-upload-pack— the client says what it has and wants; the server responds with a packfile.
You don't need a git binary or a checked-out working tree to answer these. You need to produce two things: the ref advertisement, and a valid packfile containing the objects for the requested commit.
So the endpoint at /api/plugin/[token]/[...gitpath] does exactly that:
- Reads the user's skills from the database (the token in the URL authenticates the request — Claude Code's auto-updater can't send custom headers, so auth rides in the path).
- Renders each skill to a
skills/<slug>/SKILL.mdfile in memory. - Builds git objects — one blob per file, a tree, and a commit — hashing each with
crypto.createHash('sha1'). - Assembles a packfile using Node's built-in
zlib.deflateRaw, and serves it.
No subprocess. No isomorphic-git. No temp directory. The "repository" exists only for the duration of the request.
Why deterministic hashing matters
Git identifies objects by the SHA-1 of their content. If we generate the same skills the same way, we get the same commit SHA — which means Claude Code's git fetch correctly sees "nothing changed" and does no work. Change a skill, and the blob hash changes, which cascades to a new tree and commit SHA, and Claude Code pulls the update automatically on next launch.
That's the payoff: the user edits a skill in a web form, and their Claude Code slash command updates itself — through a git repository that was never cloned, never pushed, and doesn't exist between requests.
The install flow
For the user, none of the above is visible. They run:
claude plugin marketplace add https://www.korvai.com/api/plugin/YOUR_TOKEN/marketplace.json
claude plugin install korvai@korvai-marketplace
Then /korvai:<slug> is a slash command in every Claude Code session, and it stays current with what they've authored on the web — because every launch, Claude Code fetches a freshly-generated repo and diffs it by SHA.
If you're building anything that needs to feed content into Claude Code, this pattern is worth knowing: you can be a git remote without being a git host. The protocol is small enough to implement, and generating the repo from your real data source beats keeping a second copy in sync.
Korvai turns your repeated workflows into Claude Code skills you author once and run as slash commands. Try it free.
Stop starting every AI chat from scratch.
Korvai loads your context, prompts, and skills into every session — Claude, ChatGPT, Gemini, and more. Free to start.
Build your system freeKeep reading
Turn any prompt you've used twice into a template
The prompt you nailed last week is already lost. Here's how to stop rewriting your best work from memory and build a prompt library that compounds.
Context engineering for people who aren't engineers
The reason your AI output is generic isn't your prompting. It's that the model has no idea who you are. Here's how to fix that without writing a single line of code.