Skip to content

feat: add lock file for reproducible remote plugin syncs #335

@christso

Description

@christso

Summary

Allagents fetches plugins from remote Git repos (GitHub, marketplaces) but has no version tracking. Every sync pulls latest from the default branch. This means:

  • Not auditable — no record of what version was actually synced
  • Silent updates — plugin changes are invisible in code review; teammates don't see what changed
  • No rollback — if a plugin update breaks things, there's no way to know what commit you were on before

Proposal

Add a plugins-lock.json that records which Git commit was fetched for each remote plugin. The lock file is a side effect of sync — it records what happened, it doesn't change sync behavior.

Behavior

allagents sync (and its alias allagents update) continues to work exactly as today — always fetches latest from remote. The only addition is that after fetching, the commit SHA is written to plugins-lock.json.

Command Current behavior New behavior
allagents sync / update Fetches latest Fetches latest + writes lock file
allagents sync --offline Uses cache Uses cache + writes lock file
plugin install Fetches + installs Fetches + installs + writes lock entry
plugin uninstall Removes plugin Removes plugin + removes lock entry

Zero breaking changes. sync and update remain identical aliases. No lock file present → no change. The lock file is purely additive output.

Proposed schema

{
  "version": 1,
  "plugins": {
    "anthropics/claude-plugins-official/plugins/code-review": {
      "source": "https://github.com/anthropics/claude-plugins-official",
      "subpath": "plugins/code-review",
      "commit": "a1b2c3d4e5f6...",
      "branch": "main",
      "lockedAt": "2026-03-26T10:30:00Z"
    },
    "my-plugin@custom-marketplace": {
      "source": "https://github.com/org/marketplace",
      "resolvedPath": "plugins/my-plugin",
      "commit": "f6e5d4c3b2a1...",
      "branch": "main",
      "lockedAt": "2026-03-26T10:30:00Z"
    }
  }
}

Local plugins (e.g., ./my-plugin) are skipped — no locking needed.

What the lock file gives you

  • Auditabilitygit diff plugins-lock.json shows exactly what changed between syncs
  • Rollback — previous commit SHAs are in git history
  • Visibility — plugin updates appear in PRs, making changes reviewable

Future extensions (out of scope)

Reproducibility and pinning can be layered on top of the lock file later:

  • allagents sync --frozen — fail if remote doesn't match lock file (CI use case)
  • allagents sync --locked — checkout pinned commits instead of pulling latest
  • Content hash alongside commit SHA for integrity verification

These are separate features built on the lock file foundation, not part of the initial implementation.

Relationship to sync-state.json

The lock file and sync-state.json serve complementary but distinct purposes:

The lock file does NOT replace sync-state.json.

Prior art

npx skills (vercel-labs/skills)

Two lock files (project skills-lock.json v1 + global ~/.agents/.skill-lock.json v3). Pins via content hash of skill folder. Content hashes verify integrity but can't reproduce a specific revision. Lock file is append-only on remove (entries persist after uninstall — likely a bug). Repo clones cached at ~/.cache/plugins/. Agent dirs are symlinks → ~/.agents/skills/.

npx plugins (Anthropic's open-plugin format)

Single global state file (~/.claude/plugins/installed_plugins.json v2). Pins via git commit SHA — stronger than content hash, enables exact reproduction. Keeps version history on disk (multiple versioned dirs per plugin in cache). Claude Code-native, no project-level lock file. Marketplace registry in separate known_marketplaces.json.

Comparison

npx skills npx plugins allagents (proposed)
Pin mechanism Content hash Git commit SHA Git commit SHA
Project-level lock Yes No Yes
Behavior change None None None (additive)
Version history on disk No (overwrites) Yes (multi-version cache) No (not needed)

Git commit SHA chosen over content hash because allagents already clones repos — capturing the SHA is free and enables future git checkout reproduction.

Tasks

  • Define lock file Zod schema
  • Capture commit SHA after fetchPlugin() succeeds
  • Write plugins-lock.json alongside sync-state.json at end of sync
  • Remove lock entries on plugin uninstall
  • Add lock entry on plugin install
  • Skip local-path plugins in lock file
  • Update docs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions