perf: do per-run work once in update instead of once per plugin - #2
Merged
Conversation
updateAll re-installed each recorded plugin through the full install path, so for every plugin it re-read the marketplace registry, re-cloned the whole marketplace repository, and re-registered the marketplace with Claude Code. That work is identical for every plugin from the same repo, so a run cost O(plugins installed x marketplace size) - and got slower as the marketplace grew, even with nothing new installed. Introduce a per-run session holding the registry, an open repo handle, and the Claude registration, keyed by repo@ref because manifest entries carry their own. updateAll creates one and passes it to every plugin; a lone install gets a throwaway session, so that path is unchanged. openRepo clones (or fetches the API tree) once and checks plugin folders out of it on demand, replacing one clone per plugin. The API path now reuses a single tree response, which also cuts unauthenticated requests against the 60/hour limit. Measured on 4 plugins into a sandboxed Cursor + VS Code: 23.6s -> 11.5s. The Claude Code path saves two CLI invocations and a fetch per plugin on top. Refs apimatic/contextmatic-crawler#31 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
alifsayalee
force-pushed
the
alifsayalee/faster-update
branch
from
July 30, 2026 10:05
e746ecd to
0a683fd
Compare
Alishahzad1903
approved these changes
Jul 30, 2026
|
🎉 This PR is included in version 0.4.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes apimatic/contextmatic-crawler#31.
The problem
updateAllre-installs each recorded plugin by calling the full install path. That meant per plugin:marketplace.jsongit clonethe entire marketplace repo into a temp dir, sparse-check out one folder, then delete itclaude plugin marketplace list+claude plugin marketplace update— two CLI invocations and another network fetchSteps 1–3 are identical for every plugin from the same repository. Only step 4 is genuinely per-plugin.
The compounding part the issue doesn't name: the clone in step 2 is proportional to the whole marketplace (1,850 files, 29 plugins, 1,368 skills), not to the one plugin you want. So the real cost is
plugins installed × marketplace size— per-plugin time gets worse as the marketplace grows even if you install nothing new. That's consistent with the reporter measuring 9.6s/plugin on macOS against the original 6.5s: same code, bigger repo.The fix
A per-run session (
src/session.js) holding the three shared things: the registry, an open repo handle, and the Claude marketplace registration. All keyed byrepo@ref, because manifest entries each record their own and an update may legitimately span more than one marketplace.updateAllcreates one session and passes it to every plugin.installgets a throwaway session, so that path is behaviourally unchanged.openRepoclones once and checks plugin folders out on demand viasparse-checkout add, replacing one clone per plugin.Measured
4 plugins, sandboxed Cursor + VS Code, same machine and state directory,
mainvs this branch:mainThat's the registry + clone savings only — these targets don't touch Claude Code. Runs including Claude save two CLI invocations and a fetch per plugin on top.
Tests
144 pass (136 existing, unchanged, + 8 new). New coverage:
updatereads the registry once for a two-plugin runReview notes
deps.materializeis preserved as the injection seam and still runs per plugin, so existing tests and any caller relying on it behave as before. Only the real path uses the shared clone.openReponow honoursdeps.envfor thegitlookup. That's what makes the API path testable on a machine that has git installed, and it matches howdeps.envis already used elsewhere.resolvePlugintakes an optional pre-loadedcatalog.undefinedmeans "not supplied";nullis a valid answer meaning the repo has no registry, so it deliberately does not trigger a second fetch.add, notset. A--sparseclone starts with only root files, so for the first path the two are equivalent — butaddlets later plugins join the same working tree instead of replacing it.pool()already exists, but concurrentclaude plugin installcalls mutate Claude's shared config, and concurrent VS Code installs all rewrite the samesettings.json— that's a lost-update race. Worth doing deliberately in its own change rather than smuggled in here.There is still a floor:
claude plugin installmust run once per plugin. That part is irreducible.🤖 Generated with Claude Code