This page is for users of cc-clip. If you want to cut a new release,
see release.md.
cc-clip does not currently auto-check for updates. Pick whichever of these fits your workflow:
-
Watch the repository on GitHub. Open https://github.com/ShunmeiCho/cc-clip, click Watch -> Custom -> Releases. GitHub will email you whenever a tag ships.
-
Subscribe to the releases Atom feed at https://github.com/ShunmeiCho/cc-clip/releases.atom.
-
Check your current version against the latest:
cc-clip --version curl -fsSL https://api.github.com/repos/ShunmeiCho/cc-clip/releases/latest \ | grep '"tag_name"' | head -1 | cut -d'"' -f4
When a new cc-clip version ships, every machine that runs cc-clip needs the new binary:
| Where cc-clip runs | What it does | Needs upgrade when |
|---|---|---|
| Your local Mac or Linux laptop | Runs the HTTP daemon, hosts the clipboard | Always |
| Your Windows laptop | Runs the hotkey listener, sends files over SSH | Always |
| Each remote host you use with cc-clip | Hosts the xclip/wl-paste shim, Claude Code hook config, and optionally x11-bridge/Xvfb | Whenever the local binary is updated (the remote side and local side share a protocol) |
The remote update is driven from your local machine via
cc-clip connect <host>. You do not SSH in and upgrade remotely by hand.
v0.9.0 introduces per-target setup. One behavior change matters when you upgrade an existing host:
-
--codexis now Codex-only. In v0.8.x,cc-clip connect <host> --codexinstalled Codex support on top of the Claude shim. In v0.9.0 it installs Codex only (Xvfb + x11-bridge, no Claude shim). If you used--codexto get both, switch to--all:# v0.8.x (old): --codex meant Claude shim + Codex cc-clip connect myserver --codex --force # v0.9.0 (new): use --all for the same Claude + Codex result cc-clip connect myserver --all --force
-
New targets:
--opencode,--agy(Antigravity), and an explicit--claude.--allselects every target.
If you opted into a v0.9.0-beta.x prerelease, moving to stable v0.9.0 is a
non-event: stable v0.9.0 ships the same feature set as the beta prereleases.
There is no beta-to-stable breaking change.
-
cc-clip updatemoves you to v0.9.0. The updater compares your installed tag against the latest stable release. Av0.9.0-beta.xtag is not equal tov0.9.0, socc-clip updatetreats stable v0.9.0 as newer and upgrades. -
If you pinned the beta, drop the pin. If you installed with
CC_CLIP_VERSION=v0.9.0-beta.x, run the next install/update without that env var so you track the latest stablev*tag again. -
If
cc-clip updatehits a GitHub API rate limit, use the pinned install one-liner instead (it goes through the install script, which does not need the/releases/latestAPI call):curl -fsSL https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.sh \ | CC_CLIP_VERSION=v0.9.0 sh
Otherwise the upgrade is the normal forward path below: update the local binary,
then redeploy each remote with --force. Downgrading back across the v0.9.0
boundary is not lossless — see
Cross-v0.9 downgrade first.
cc-clip update --check # see what's newer without touching anything
cc-clip update # download, verify checksum, swap binary, restart daemonThis is the native one-shot path. Compared to re-running install.sh, it
additionally:
- Detects port-18339 conflicts before downloading. If another process
(a bundled
cc-clipfrom a different tool, a forgotten stray daemon) is holding the port, the update aborts with an actionable error instead of silently leaving you with a mismatched token on remotes. - Verifies the staged archive's
--versionbefore swapping the binary, so a mislabeled release cannot overwrite a working install. - Rolls the binary and launchd plist back automatically if
GET /healthon the daemon port does not come up on the new binary within 10s of the swap.
--force re-installs even when already at the target version and bypasses
the pre-download conflict check. --to v0.6.0 pins a specific release
instead of the latest (handy for rollback).
Not yet supported: Windows (use the Windows installer path below), and systemd-based Linux services (the updater prints a reminder instead of restarting the service).
curl -fsSL https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.sh | shThis fetches the archive for the latest v* tag, extracts it, replaces the
binary at ~/.local/bin/cc-clip, clears macOS Gatekeeper quarantine, and
re-signs with codesign --sign -. Safe to re-run any time; useful when
cc-clip update is not yet available on your machine (first-time install,
or pre-0.6.2 cc-clip).
Pick the archive matching your OS and arch from https://github.com/ShunmeiCho/cc-clip/releases/latest, then:
V=0.9.0 # latest version without the v prefix
OS=darwin # or linux
ARCH=arm64 # or amd64
cd /tmp
curl -fsSL -o cc-clip.tar.gz \
"https://github.com/ShunmeiCho/cc-clip/releases/download/v${V}/cc-clip_${V}_${OS}_${ARCH}.tar.gz"
tar -xzf cc-clip.tar.gz
install -m 0755 cc-clip ~/.local/bin/cc-clip
# macOS only: clear quarantine + ad-hoc sign so Gatekeeper allows it
[ "$(uname -s)" = "Darwin" ] && xattr -cr ~/.local/bin/cc-clip \
&& codesign --force --sign - --identifier com.cc-clip.cli ~/.local/bin/cc-clip-
Restart the clipboard daemon. If you are running it as a user service:
cc-clip service uninstall cc-clip service install cc-clip service status # should show "running"If you run it in the foreground yourself, just stop the old process (
Ctrl+C) and start it again withcc-clip serve. -
Confirm the upgraded daemon owns the port. If another cc-clip bundle or old helper process is still listening on the daemon port,
connectcan talk to the wrong daemon and sync the wrong token to the remote.launchctl list | grep -i cc-clip lsof -nP -iTCP:18339 -sTCP:LISTEN curl -i -X POST http://127.0.0.1:18339/register-nonceExpected:
launchctlshould show only the cc-clip daemon you intentionally run.lsofshould show the listener path/PID belongs to your upgradedcc-clipbinary, not another bundled copy./register-nonceis aPOST-only endpoint. Without an auth header it should return401or403. A404means an older daemon that does not know about notification nonces is answering; a405(from a GET) just means you forgot-X POST.
-
Redeploy to every remote host you use with cc-clip. This pushes the new binary to the remote and rebuilds the shim / hooks / x11-bridge entries:
# Claude Code only (default): cc-clip connect myserver --force # Claude Code + Codex CLI on that host (v0.9.0: --codex alone is Codex-only): cc-clip connect myserver --all --force
--forceis important when upgrading: it bypasses the hash-based "binary unchanged, skipping" optimization so the new version actually lands on the remote. -
Verify:
cc-clip --version ssh myserver 'cc-clip --version' # optional cross-check of the remote binary
cc-clip update does not support Windows yet. Use the manual zip path for the
latest stable release. The PowerShell installer applies to releases that include
scripts/install.ps1; do not use the latest release installer to test
unreleased direct RemoteForward/shim behavior.
-
Stop any running cc-clip hotkey listener:
cc-clip hotkey --disable-autostart # or kill the tray icon process, or log out of the Windows session
-
For a release that includes the Windows installer, run:
irm https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.ps1 | iex
It downloads
cc-clip_<version>_windows_<arch>.zip, verifieschecksums.txt, and replacescc-clip.exein%USERPROFILE%\.local\binby default. If the feature you want is only in an unreleased branch, build from source or wait for an explicit prerelease tag instead of using the latest stable release.To install a specific version for rollback or pinning:
$env:CC_CLIP_VERSION="v0.5.0"; irm https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.ps1 | iex
If you installed cc-clip somewhere else, pass that directory:
$env:CC_CLIP_INSTALL_DIR="$HOME\bin"; irm https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.ps1 | iex
-
Manual fallback: download the new zip from https://github.com/ShunmeiCho/cc-clip/releases/latest (pick
cc-clip_<version>_windows_amd64.zipor..._arm64.zip), then extractcc-clip.exeon top of your existing install location. -
Restart whichever Windows component you use.
For the default hotkey/send workflow:
cc-clip hotkey # or, to keep auto-start enabled: cc-clip hotkey myserver --enable-autostart cc-clip hotkey --status # confirms the new version is registered
For the experimental direct shim workflow, only after installing a source build or a release that explicitly contains Windows direct clipboard support:
cc-clip service uninstall cc-clip service install cc-clip service status
-
If you opted into the experimental direct shim workflow from a source build or explicit prerelease, redeploy to every remote host from Windows so the remote binary/shim matches the upgraded local daemon:
cc-clip connect myserver --claude --force
If you use only the default hotkey/send workflow (
cc-clip send --paste/cc-clip hotkey) and never installed the remote shim from Windows, there is no remote binary to redeploy for that path.
- Daemon holding a stale binary: macOS launchd keeps the old binary open
until the service is restarted. If
cc-clip --versionon the CLI shows the new version but clipboard paste still behaves like the old one,cc-clip service uninstall && cc-clip service install. - Another daemon owns port 18339: If
cc-clip connectsays the daemon is running but paste still fails, inspectlsof -nP -iTCP:18339 -sTCP:LISTEN. The process must be the upgraded cc-clip daemon you intend to use. Stop any old bundled copy before runningcc-clip connect <host> --forceagain. - Remote cache says "unchanged":
cc-clip connecttracks the remote binary hash in~/.cache/cc-clip/deploy.jsonon the remote. If that file claims the binary is already current,connectwill skip the upload. Use--forceon upgrade runs. (deploy.jsonalso carries aschema_versionthat drives the forward-downgrade guard — see Rollback.) - Token vs binary upgrade: If you only rotated the daemon token and did
not change the binary, run
cc-clip connect myserver --token-onlyinstead — it syncs the token without a full redeploy. - macOS Gatekeeper: the install script re-signs the binary after
download. If you download manually you need to either run the two
xattr -cr+codesign ...commands above, or Gatekeeper will refuse to execute the new binary.
There are two flavours of rollback, and they are not equally safe:
- Same-generation rollback (for example
v0.9.1 -> v0.9.0): the normal, lossless path. Both binaries speak the same deploy-state schema and know the same deployment targets (--codex,--opencode,--agy), so re-runningconnect --forcesimply re-syncs the older binary. This is what the runbook below covers. - Cross-v0.9 downgrade (to a pre-
v0.9.0binary): not lossless — see the Cross-v0.9 downgrade subsection before you attempt it.
-
cc-clip update --to v0.5.0(cc-clip 0.6.2+): same semantics as a forward upgrade — checksum-verify, swap, restart, verify — but against the pinned release tag instead of/latest. -
Via install script, pinned with
CC_CLIP_VERSION(curl-install rollback channel, mirrorscc-clip update --to):install.shfetches/releases/latestby default, but ifCC_CLIP_VERSIONis set it installs that exact tag instead. This is the recommended one-liner for machines that do not yet havecc-clip update:curl -fsSL https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.sh \ | CC_CLIP_VERSION=v0.5.0 shThe env var must be set on the right-hand side of the pipe (the
shthat runs the script), not oncurl.CC_CLIP_VERSION=v0.5.0 curl ... | shwould export the pin only into thecurlprocess and the pipedshwould still install/latest.The value must be a full tag (for example
v0.5.0); a missingvprefix is accepted. An invalid value aborts the install with an actionable error. -
Via install script, the manual way: you can also skip
CC_CLIP_VERSIONand use the Option C manual-download commands above withV=set to the version you want (for exampleV=0.5.0downgrades tov0.5.0). -
Windows PowerShell installer: same pinning model, using the Windows zip asset and
Get-FileHashverification:$env:CC_CLIP_VERSION="v0.5.0"; irm https://raw.githubusercontent.com/ShunmeiCho/cc-clip/main/scripts/install.ps1 | iex
For a same-generation rollback, after the local binary is replaced:
-
Restart the daemon (
cc-clip service uninstall && cc-clip service install) so launchd stops holding the old binary — same as a forward upgrade. -
List the remotes that need re-syncing. The local host registry knows every machine you have deployed to and the version it last received:
cc-clip hosts list # HOST VERSION CODEX LAST CONNECTED # myserver 0.9.1 no 2026-06-01T10:22:04+09:00 # venus 0.9.1 yes 2026-05-30T18:05:11+09:00
-
Re-run
cc-clip connect <host> --forcefor each remote in that list, so the remote side goes back in sync with the downgraded local binary.--forcebypasses the hash-based "binary unchanged, skipping" optimization.Note the new guard (v0.9.0+): if the remote's
deploy.jsonwas last written by a newer cc-clip than the one you just rolled back to,connectrefuses to overwrite it and tells you to upgrade this cc-clip or pass--force. This protects you from a stale local binary silently clobbering a remote that a newer machine deployed. It is a forward guard only — see the caveat below for what it does and does not cover.
Downgrading a remote to a pre-v0.9.0 binary is not lossless, and there
is no automatic guard that will stop you. Two things go wrong:
- A pre-
v0.9.0binary does not understand the v0.9 deployment-target model (--opencode,--agy, and the per-adapterNotify.Adaptersmap indeploy.json). It only knows the original Claude-Code shim + hook layout. - Being a pre-guard binary, it has no
schema_versionawareness. The forward-downgrade guard described above only exists in binaries that ship it (v0.9.0 and later). An older binary will happily overwrite~/.cache/cc-clip/deploy.jsonon the remote, dropping theAdaptersmap and theagy-notify/opencode-notifyentries.
So do not rely on a fail-closed here — the protection is forward-only by design. If you must cross the v0.9 boundary downward, expect to clean up and redeploy those adapters by hand:
-
Manually tear down the v0.9-only adapters on the remote you are about to downgrade, so no orphaned plugin / hook entries are left behind. There is no
cc-clip uninstall <host> --opencode/--agycommand today — symmetric uninstall for those targets is not yet implemented (cc-clip uninstallcurrently supports only--codexand--host). Clean them up over SSH by hand, only for whichever adapters you actually enabled:# opencode notify plugin (the dropped .js is removed by hand): ssh <host> 'rm -f "$HOME/.config/opencode/plugins/cc-clip-notify.js"' # Antigravity (agy) notify plugin (use agy's own uninstall on the remote; # agy's managed plugins dir is version-specific, so let the CLI find it): ssh <host> 'agy plugin uninstall cc-clip-notify'
(Future cc-clip versions may add
cc-clip uninstall --opencode/--agyto automate this; until then the manual cleanup above is the supported path.) -
Roll the remote back by deploying the pre-v0.9 binary from the older local cc-clip (
connect --force), accepting thatdeploy.jsonwill be rewritten in the old format. -
When you later move forward across v0.9 again, re-enable the adapters you want (
connect <host> --opencode/--agy/--all); v0.9.0+ will re-stampdeploy.jsonwith the currentschema_version.
If a release was published in error by the maintainer, they will mark it
prerelease on GitHub. install.sh will then skip it automatically and
fall back to the previous stable v* tag on the next run.