Releases: hungv47/syncthis
Releases · hungv47/syncthis
v0.15.1
Fixed
- First-run welcome banner now shows the noun-first grammar. The 0.15.0 refactor moved the canonical surface to noun-first verbs but left
welcome.tsx's hardcoded command list on the pre-0.15 spelling (add plugin, baremcp/skills,<from> <to>,rm <server>,plugin list). The banner now listsplugins add,mcp sync,skills update,mcp <from> <to>,mcp rm, andplugins list, matchingsyncthis help.
v0.15.0
Includes everything in 0.14.1 (cross-agent plugin/skill identity hardening), which was never published on its own.
Added
- Noun-first CLI grammar. Three nouns —
plugins,skills,mcp— each with scoped verbs (plugins list|mirror|add|rm,skills update|add|from-plugins|rm,mcp sync|doctor|from|rm, plus directionalmcp <from> <to>), alongside the flagshipsync. This is now the canonical, advertised surface (syncthis help,syncthis <noun> help). The change is additive and non-breaking: every pre-0.15 command still works as an unadvertised alias routing to the same handler (run, baremcp,doctor,mirror,from,<from> <to>,add/rm <skill|plugin|mcp>,plugin list/plugin rm). Bare-noun behavior preserves legacy side effects (mcp→ union sync,skills→ update) while help advertises the explicit verbs; barepluginsprints group help. A collision guard incmdMcpkeeps a future agent id from being shadowed by a verb name. Routing + alias equivalence is pinned bytests/cli-routing.test.ts. - Reproducible terminal demos. VHS tapes (
docs/demos/tapes/) render the GIFs embedded in the README from a sandboxed fixture-$HOMEharness (docs/demos/seed-fixtures.ts,docs/demos/build.sh): pure-file MCP flows are recorded live (showing real mutations + the.syncthis.bakbackup), shell-out plugin/skills flows as dry-run/preview, so no external CLIs are needed and the output is deterministic.
Changed
- Inline TUI walk-through guidance. The interactive picker now renders breadcrumb headers and inline affordances via the existing
note()/tui-stylehelpers (no new mode, no new runtime deps), so each flow shows where you are in source → items → destinations → preview → confirm.
v0.14.0
Changed
- Interactive multiselect picker restyled to match the native prompts. The grouped/flat checkbox picker (plugins, skills, agents, MCP servers) hand-rolled its render with ASCII pipes, a stray backtick footer, and no color, so long lists looked broken next to the clack
select()menus. It now renders with the same treatment as those menus — gray│bars, a└end-cap, a colored◆/◇state glyph,◻/◼checkboxes, and a cyan-highlighted active row — via a new dependency-freesrc/tui-style.tsthat re-derives clack's Unicode/ASCII fallback andNO_COLOR/non-TTY-aware color (zero added runtime deps). Marketplace group rows now carry a◈glyph + bold label over dimmed, indented children, the window height adapts to the terminal, and the row-eating...truncation is replaced by dim↑ N more/↓ N morecounters.
Added
- Type-to-filter in the multiselect picker. On lists longer than one page (e.g. the 200+ plugin catalog), just start typing to incrementally filter — matches collapse to the typed substring with a synthetic
select all (N matches)row, backspace narrows back, and clearing the filter restores the full grouped structure. Selections persist across filter changes. The previous hiddena-selects-all shortcut is retired (the key is now free for typing); the visibleselect allrow remains the discoverable bulk-select mechanism.
v0.13.1
Fixed
syncthis updatenow updates the copy on your PATH — fixing the stale version after update. On a machine with more than one Node prefix (e.g. a Homebrew node on PATH while npm's global prefix points at a version-manager prefix),npm install -ginstalled the new version into a prefix you never run from, so the banner stayed frozen at the old version every release.updatenow derives the global prefix from the running binary (import.meta.url) and pins npm to it with--prefix, so the exact copy you execute is the one refreshed. It then re-reads that copy'spackage.jsonand reports the real result (updated X → Y/now at Y) instead of a blind "updated to latest" that could mask a stale install. New pure, testedsrc/self-update.ts(deriveGlobalPrefix) handles the unixlib/node_modulesvs Windowsnode_moduleslayouts and falls back to npm's default in a dev/source run.
Changed
- Plugin-install status lines reflect the network-free local-marketplace path. The
add pluginapply note now reads "Codex installs from local marketplace clones (offline); Cursor/skills steps use npx (network)", and themirrorprovisioning note clarifies that Codex installs from local clones when available, withnpx plugins addas the fallback — matching the 0.13.0 mechanism instead of overstating npx/network use.
v0.13.0
Changed
- Network-free, idempotent plugin install via the source's local marketplace clone. Transferring a Claude plugin to Codex (
add plugin,mirror, and the interactive plugin sync) now registers the source's on-disk marketplace clone on the target —codex plugin marketplace add <clonePath>(reused when already registered by root or name, never re-added) — thencodex plugin add <name>@<marketplace>. Nonpx pluginsfetch, no network round-trip, and no duplicate marketplace rows in~/.codex/config.toml.npx pluginsprovisioning remains a guarded fallback only when no local clone exists. New pure resolversrc/plugins/marketplace.ts(parseMarketplaceList,readLocalMarketplace,resolveLocalMarketplace); newPluginInstallOpts.sourceClonePath; Claude clone paths resolved fromknown_marketplaces.jsonand threaded throughadd.ts/mirror.ts. A URL-named install id or multi-plugin alias whose manifest name differs from the entry name still falls through to the existing coverage/skills-fallback path, so behavior there is unchanged.
Added
- Discoverable select-all in the interactive picker. The multi-select now renders a visible
select all (N)control row, and — for grouped lists like plugins by marketplace — a per-group<marketplace> (N)select-all row, alongside the existingashortcut. Plugins default to those installed on the source agent, grouped by marketplace, with a toggle to show all available marketplace clones (installed-and-not). New testedsrc/picker-logic.ts(buildRows,nextSelectionForRow,groupPluginsByMarketplace) holds the pure selection/grouping logic, decoupled from the terminal. - Share installed skills agent → agent. A new interactive skills flow picks a source agent, its installed skills, and destination agents, then adds each skill to the destinations using the skill's own on-disk store path as the
npx skills addsource — no dir-copy that would corrupt the shared~/.agents/skills/symlink store.
v0.12.4
Fixed
- Interactive multi-select prompts now use real checkboxes without flooding large lists. Plugin, skill, agent, and MCP pickers use a windowed checkbox prompt with Space to toggle,
ato select all, and Enter to confirm. Large installs stay paged instead of rendering hundreds of rows at once, and empty submits warn/retry without crashing.
v0.12.3
Added
syncthis update. Updates the global@hungv47/syncthisinstall to latest, usingnpm install -g @hungv47/syncthis@latestby default and Bun's global install when the current executable comes from Bun. Supports--dry-run.syncthis version/--version/-v. Prints the installed package version directly.
Fixed
- Version reporting now reads installed package metadata at runtime. The welcome banner and
versioncommand read the installedpackage.jsoninstead of bundling a JSON snapshot, preventing stale version output from a generateddist/syncthis.mjs.
v0.12.2
Fixed
- Claude plugin reads no longer depend on truncated CLI JSON. Large Claude plugin installs can make
claude plugin list --jsonexit 0 with exactly 65 536 bytes of malformed JSON. The Claude plugin adapter now prefers Claude's durable~/.claude/plugins/installed_plugins.jsonstate file, keepingplugin list,add plugin,plugin rm, andmirrorworking on large installs.
Changed
- Interactive plugin management now uses one selected sync flow. The TUI no longer presents a separate "Mirror all" option. Manage plugins → Sync plugins asks for source, plugin selection, and destination agents; selecting all covers the old interactive mirror use case. The
syncthis mirrorCLI command remains as a batch/back-compat shortcut.
v0.12.1
Fixed
- Tolerate Claude
plugin list --jsontruncation. On a machine with many plugins,claude plugin list --jsoncan hit a ~64 KB stdout cap and return malformed JSON, which previously broke every plugin-aware path (plugin list,mirror,plugin rm,add plugin). The Claude plugin adapter now reads~/.claude/plugins/installed_plugins.jsondirectly when the CLI is missing, exits non-zero, or returns unparseable/unexpected JSON (with a hint when stdout is exactly 65 536 bytes — the telltale of a buffer cap).marketplaceSources()gets the same fallback against~/.claude/plugins/known_marketplaces.json, somirror's<name>@<marketplace>resolution and provisioning still work whenclaude plugin marketplace list --jsonis unreadable too. Same shape, same data — just read from Claude's own state files instead of round-tripping the CLI. New exportedparseClaudeInstalledPluginsfor tests. - Skill already-synced guard is now per-agent, not global.
addSkillsFromPluginspreviously skipped a source repo whenever every skill name was globally present innpx skills list -g --json— even if those skills were registered only on some agents and the current sync was targeting agents that didn't have them. After a TUI "Add from repo" that picked a subset of agents, a latersyncthis run(cohort) would falsely report "already synced" and leave the missing agents missing. Now a repo is skipped only when every skill it contributes is already registered on every requested agent.force: true(interactive Add-from-repo / Sync-from-plugins) still bypasses the guard. Defaultrun/syncbehavior unchanged for the common case where the cohort already has everything.
v0.12.0
Added
- Selective MCP sync — share chosen servers from one agent to others. New core
runSelectiveMcpSync(sync.ts): pick a source agent, pick specific MCP server names, pick destination agents, and add just those servers — additive and conflict-safe. A server name already present on a destination with a different config is left untouched and reported (same conflict policy as union sync, sacred element #3); a name missing from the source is reported asnotFound. This is not anadd mcp— it never installs a new server or overwrites one, it only spreads servers an agent already has, so MCP stays sync + remove only. Exposed interactively via the MCP manager's Sync selected flow (source → servers → destinations → preview → confirm).
Changed
- Interactive capability management, simplified. Running
syncthiswith no args now opens a top-level menu of per-capability managers — Manage plugins (sync selected / mirror / list / remove), Manage skills (add from repo / sync from plugins / update / remove), Manage MCPs (sync everything / sync selected / sync all only / remove / doctor), and Check problems — each walking the same source → items → destinations → preview/confirm shape. This replaces 0.11.0's single "Add or remove capabilities" entry. No CLI command behavior changed; the picker is just clearer to navigate. - Skill add gained a
forcemode.addSkillsFromPlugins({ force })bypasses the global already-present guard so the interactive "Add from repo" / "Sync from plugins" flows can re-add chosen plugin skills to chosen agents on demand, instead of being silently skipped when the skill name is already globally present. The default (non-force)run/syncpath is unchanged — it still skips already-synced repos so a repeatrundoesn't re-fetch.