Evidence Every claim on this site is backed by a test or a recorded run in the repository. What is proven, and what is still unverified, is listed in docs/VERIFICATION.md.

Install a Claude Code plugin from GitHub · Synchrobuilder

Prerequisites

Three things on the machine. Nothing to host, nothing to sign up for.

StatusSynchrobuilder 0.1.0 is published on npm as synchrobuilder, and the marketplace is in the public repository RyanNorouzi/synchrobuilder. Every command on this page is available. What each claim rests on is in docs/VERIFICATION.md.
RequirementWhy
Claude Code, a current versionThe docs we read describe Claude Code up to 2.1.276. Our experiments ran on 2.1.218 on macOS. The /plugin command needs a release that has it; the docs say to upgrade with brew upgrade claude-code or npm install -g @anthropic-ai/claude-code@latest.
Node.js 20 or newer on PATHEvery hook is declared in exec form as the node executable plus a script path, with no shell. Claude Code resolves node from the PATH it inherited. If node is missing, every hook shows a non-blocking error notice and the plugin does nothing (experiment E3). Node 20 is the floor. CI runs the suite on Node 20 and Node 24.
git on PATHThe docs say Claude Code clones a git-hosted marketplace onto your machine, so adding one needs git. The multiplayer transport publishes state through your existing git remote, so the background worker needs git too. The hooks themselves never spawn git.

The Node requirement is the one to check first. A hook cannot fix a missing node from inside itself, because Claude Code resolves the executable before any of our code runs. The /synchrobuilder:doctor checks node and git on PATH and reports the fix for your OS.

macOSWindowsLinuxexperiment E3 · 2026-09-18 · claude 2.1.218
$ env -i HOME=… PATH=/usr/bin:/bin claude -p "…" --plugin-dir …/plugin --output-format stream-json …
# every hook_response event:
"stderr":"Error occurred while executing hook command: Executable not found in $PATH: \"node\"","exit_code":1,"outcome":"error"
# result event:
exit 0, is_error: false   the file was still created; Claude saw no hook context

Recorded with the Phase 0 experiment plugin rather than the shipped hooks. The same fail-open contract is now covered by tests/hooks/replay.test.mjs, which asserts exit 0 on malformed stdin, an unknown verb and outside a git repository.

Install

Two commands inside Claude Code, or the same two in a terminal.

One command, from any terminal works now
npx synchrobuilder@latest install
This prints the exact Claude Code commands it is about to run, asks before running them, and does nothing if you say no. Add --scope project to install it for one repository, --plan to see the plan and stop, or --uninstall to reverse it. Running it twice changes nothing the second time. It writes only to your Claude Code settings and plugin cache.

Everything below is the same install done by hand, which is what the one-liner runs for you.

Inside a Claude Code session works now
/plugin marketplace add RyanNorouzi/synchrobuilder
/plugin install synchrobuilder@synchrobuilder
The repository is public, so these commands work for anyone. The second command opens the plugin's details, where you choose user, project or local scope.
From a terminal, no interactive step works now
claude plugin marketplace add RyanNorouzi/synchrobuilder
claude plugin install synchrobuilder@synchrobuilder
Installs to user scope unless you pass --scope project or --scope local. A terminal install loads the next time you start Claude Code, or after /reload-plugins.
Machines without an SSH key for github.com works now
claude plugin marketplace add https://github.com/RyanNorouzi/synchrobuilder.git
On Claude Code 2.1.218 the owner/repo shorthand notices when SSH is not configured and clones over HTTPS by itself, which we verified on macOS. Use this full HTTPS URL if your machine has an SSH key that cannot read the repository, or set CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1. Either way the clone uses your git credential helpers.

What the names mean

The part after @ is the name field inside the marketplace's marketplace.json, not the repository name. Ours is synchrobuilder, so the install id is synchrobuilder@synchrobuilder. The part before @ is the plugin name, which also prefixes every command: /synchrobuilder:audit.

Adding a marketplace registers a catalog and installs nothing. Installing a named plugin@marketplace refreshes that catalog first on Claude Code 2.1.232 and later. Since 2.1.221 an in-session install activates in the current session; before that, the docs say nothing took effect until /reload-plugins or a restart.

Plugins run with your user privileges, as the Claude Code docs state. The plugin is plain JavaScript with no build step and no dependencies, so what you read in the repository is what runs. Read the Security page before installing on a shared machine.

Testing from a checkout

A clone of the repository can be loaded without any marketplace: claude --plugin-dir ./plugins/synchrobuilder. claude plugin validate --strict passes on both plugins/synchrobuilder and the marketplace manifest, and a CI job runs it on every push. The validator reads the manifest only, not the hook or skill files.

First run

Three commands. All of them ship in 0.1.0.

In the project you want to keep portable available
/synchrobuilder:init
/synchrobuilder:audit
/init belongs to Claude Code, so init needs the full form. The docs say the bare /audit also invokes the skill because no built-in owns that name; we have not tried it interactively.

init inspects the project and writes synchrobuilder.json: required runtimes with exact versions, the package manager, services, environment variable names (never values), install, migrate, seed and start commands, and a health check. The format is on the Manifest page. It never writes extraKnownMarketplaces or enabledPlugins into your settings by default; it can offer to, and shows the exact JSON first.

audit scans for OS-specific assumptions and prints a report with a rule id, severity, location and fix for each finding, plus a JSON report and a score from 0 to 100. It exits non-zero only with --strict. The full list is on the Commands page.

For a team available
/synchrobuilder:iam handle
Needed when the email in git config user.email is not listed in .synchrobuilder/team.json, or when two people share one git email on one machine. Handles match ^[a-z0-9][a-z0-9-]{0,31}$.

Teammates are identified by a handle, not an account. Handles live in a committed file, .synchrobuilder/team.json, which maps each handle to the email addresses already visible in the repository's git history. init offers to seed it from git log authors, with confirmation. Commit it. A developer whose email is not in the file is not blocked: they get a provisional handle derived from the email's local part, and /synchrobuilder:status labels it "not in team.json" and suggests iam.

iam writes the override to ~/.synchrobuilder/checkouts/<key>/identity.json, never inside your repository or its .git, so it cannot be committed by accident. Your email never leaves the machine; only the handle is pushed. Identity is a claim, not authentication: anyone with push access to the remote can write any handle, which is why everything from another machine is treated as untrusted data. Details are on the How it works and Security pages.

Update and uninstall

Updates are manual for third-party marketplaces. Uninstall leaves one directory for you to remove.

Update works now
/plugin update synchrobuilder@synchrobuilder
claude plugin update synchrobuilder@synchrobuilder
The Claude Code docs say auto-update is disabled by default for third-party marketplaces, so run this yourself. /plugin marketplace update synchrobuilder refreshes the catalog.

Claude Code keys plugin updates on the version field in plugin.json. Every release bumps that field and CHANGELOG.md; if the string does not change, existing users keep the cached copy.

Uninstall works now
/plugin uninstall synchrobuilder@synchrobuilder
npx synchrobuilder clean
The first command opens Claude Code's plugin panel and leaves it open; press Esc to close it. Use claude plugin uninstall synchrobuilder@synchrobuilder for scripts.

The docs say that uninstalling from the last scope where the plugin is installed also deletes its data directory under ~/.claude/plugins/data; the /plugin panel asks first, and the CLI deletes it unless you pass --keep-data. It does not touch ~/.synchrobuilder/, where the plugin keeps its hidden bare repositories, per-checkout state and logs (override the location with SYNCHROBUILDER_HOME). npx synchrobuilder clean removes that directory. Removing the marketplace itself (/plugin marketplace remove synchrobuilder) also uninstalls every plugin you installed from it.

Troubleshooting

Per OS. The test suite runs on all three in CI; what is still unverified per OS is called out below.

macOS hooks verified on 2.1.218

Exec-form Node hooks fire for session start, prompt submit, pre-edit, post-edit, stop and session end in a real headless session, and their context reaches Claude in the same turn (experiment E2). The only failure we have seen is the one above: node not on the PATH Claude Code inherited.

If you installed Node through a version manager, check that the shell that launches Claude Code has it on PATH; the experiment used /usr/local/bin/node. The PATH a Desktop-app session gives to hooks is listed in the plan as a risk and as unverified, not something we have measured. If it turns out to be minimal, the fix the plan records is a user-level PATH setting or a symlink into a standard location, which doctor would offer with consent. We will not add a shell wrapper that searches for Node, because that reintroduces the shell the design forbids.

Windows tests pass on Windows CI

Native Windows without Git Bash runs Claude's shell commands through PowerShell and does not register the Bash tool at all. Synchrobuilder's hooks never use a shell: exec form on Windows requires a real executable, and node.exe is one, while the .cmd shims npm installs are not. Because no shell runs an exec-form hook, the docs' notes about Git Bash profiles and PowerShell placeholders, which describe shell-form hooks, do not apply to them.

File paths in hook input arrive with backslashes (C:\project\src\index.ts). The hook library normalizes separators before comparing, compares case-insensitively on Windows and macOS, and reads the home directory from os.homedir() rather than HOME. The Windows CI jobs cover this; the first run found and fixed an 8.3 short-path mismatch. ~/.claude in the docs means %USERPROFILE%\.claude.

On macOS a machine with no SSH key installs fine: the shorthand falls back to HTTPS on its own, which we ran and recorded. Whether Windows behaves the same is still untested, so the HTTPS form above is the safe one there. The suite passes on the Windows CI jobs, including the end-to-end test that spawns the real detached worker and follows it past the end of a session. Hook timings are still recorded only on macOS.

Linux tests pass on ubuntu CI

The same PATH rule applies. The ubuntu CI jobs run the whole suite, including the case-sensitive-disk rule that macOS has to skip and the end-to-end test that spawns the real detached worker and follows it past the end of a session.

Modes where the plugin does nothing

  • claude --bare (or CLAUDE_CODE_SIMPLE=1) disables discovery of plugins, hooks and skills. Safe mode (CLAUDE_CODE_SAFE_MODE=1) does not load plugins or hooks either. In both, Synchrobuilder is silent by design.
  • DISABLE_TELEMETRY or CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, set to any value including 0, makes the Monitor tool unavailable, so plugin monitors are skipped. Monitors are an optional accelerator that only makes teammate delivery sooner; the baseline is the hooks plus a detached worker, and it keeps working. Monitors also run only in interactive CLI sessions and not on Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry.
  • Plugin git operations have a 120-second timeout; CLAUDE_CODE_PLUGIN_GIT_TIMEOUT_MS changes it. Offline, an install reads the cached catalog; the docs' fix for a background refresh that keeps failing is CLAUDE_CODE_PLUGIN_KEEP_MARKETPLACE_ON_FAILURE=1.

Questions: open an issue at github.com/RyanNorouzi/synchrobuilder.