Skip to main content

@slats/claude-assets-sync

CLI tool to sync Claude commands and skills from npm packages to your project's .claude/ directory.

@slats/claude-assets-sync npm versionlicense
yarn add @slats/claude-assets-sync
Migrated to @slats/agents-assets-sync

This engine was migrated to @slats/agents-assets-sync, which injects one asset tree into Claude Code, Codex, and the vendor-neutral .agents layout. Releases published under this name stay on npm and keep working, but nothing new ships here — new packages declare agents.assetPath and use the current engine. What follows documents the released claude.assetPath contract.

Allows npm package authors to distribute Claude Code commands and skills alongside their packages. When users install these packages, they can sync the assets to their local .claude/ directory for immediate use.

  • Multi-package sync in a single command
  • Version tracking — skips re-sync when version is unchanged
  • Flat file structure with prefixed filenames (default)
  • Interactive add/list UI (ink-based terminal UI)
  • Status monitoring with npm registry update checks
  • Dry-run mode to preview changes before applying
  • Legacy nested structure support and migration tool

Installation

# One-time use (recommended)
npx @slats/claude-assets-sync -p @canard/schema-form

# Global install
npm install -g @slats/claude-assets-sync

Commands

sync (default)

Sync Claude assets from one or more npm packages.

npx @slats/claude-assets-sync [options] -p <package>
OptionDescription
-p, --package <name>Package to sync (repeatable)
-f, --forceForce sync even if version matches
--dry-runPreview changes without writing files
-l, --localRead from local workspace instead of node_modules
-r, --ref <ref>Git ref (branch, tag, commit) to fetch from
--no-flatUse legacy nested directory structure
# Sync a single package
npx @slats/claude-assets-sync -p @canard/schema-form

# Sync multiple packages
npx @slats/claude-assets-sync -p @canard/schema-form -p @lerx/promise-modal

# Preview without writing
npx @slats/claude-assets-sync -p @canard/schema-form --dry-run

# Force re-sync
npx @slats/claude-assets-sync -p @canard/schema-form --force

# Sync from a specific branch
npx @slats/claude-assets-sync -p @canard/schema-form -r main

add

Add a package with interactive file selection (TTY).

npx @slats/claude-assets-sync add -p <package> [options]
OptionDescription
-p, --package <name>Package to add (required)
-l, --localRead from local workspace
-r, --ref <ref>Git ref to fetch from

Keyboard controls in interactive mode:

KeyAction
/ Navigate items
SpaceToggle selection
/ Expand / collapse directory
EnterConfirm and sync
aSelect all
nDeselect all
qCancel
npx @slats/claude-assets-sync add -p @lerx/promise-modal

list

List all synced packages with an interactive tree view.

npx @slats/claude-assets-sync list [--json]

View mode keys: e edit, r refresh, q quit Edit mode keys: d delete file, a add file, Esc exit edit

# Interactive tree view
npx @slats/claude-assets-sync list

# JSON output for scripting
npx @slats/claude-assets-sync list --json
┌─ Synced Packages ─────────────────────────────┐
│ │
│ ▼ @canard/schema-form@1.0.0 │
│ ├─ commands/ │
│ │ └─ @canard-schema-form-my-command.md │
│ └─ skills/ │
│ └─ @canard-schema-form-my-skill.md │
│ │
│ [e] Edit [r] Refresh [q] Quit │
└───────────────────────────────────────────────┘

status

Show sync status and check for available updates.

npx @slats/claude-assets-sync status [--no-remote]
OptionDescription
--no-remoteSkip npm registry check

Status indicators: up-to-date, update available, error

┌─ Package Status ──────────────────────────────┐
│ ✓ @canard/schema-form │
│ Local: 1.0.0 Synced: 1.0.0 Assets: 2 │
│ ⚠ @lerx/promise-modal │
│ Local: 0.6.0 Synced: 0.5.0 │
├─ Summary ────────────────────────────────────┤
│ Total: 2 ✓ 1 ⚠ 1 │
└───────────────────────────────────────────────┘

remove

Remove a synced package and its assets.

npx @slats/claude-assets-sync remove -p <package> [--yes] [--dry-run]
npx @slats/claude-assets-sync remove -p @canard/schema-form --yes

migrate

Migrate from legacy nested structure to flat structure.

npx @slats/claude-assets-sync migrate [--dry-run]

Directory Structure

Flat (default)

your-project/
└── .claude/
├── commands/
│ ├── @canard-schema-form-my-command.md
│ └── @lerx-promise-modal-another-command.md
└── skills/
├── @canard-schema-form-my-skill.md
└── @lerx-promise-modal-another-skill.md

A single .sync-meta.json tracks all packages in each asset directory.

Nested (legacy, --no-flat)

your-project/
└── .claude/
├── commands/
│ └── @canard/schema-form/
│ ├── my-command.md
│ └── .sync-meta.json
└── skills/
└── @lerx/promise-modal/
├── my-skill.md
└── .sync-meta.json

.sync-meta.json

{
"version": "0.0.1",
"syncedAt": "2025-02-05T10:30:00.000Z",
"packages": {
"@canard-schema-form": {
"originalName": "@canard/schema-form",
"version": "1.0.0",
"files": {
"commands": [
{
"original": "my-command.md",
"transformed": "@canard-schema-form-my-command.md"
}
],
"skills": [
{
"original": "my-skill.md",
"transformed": "@canard-schema-form-my-skill.md"
}
]
}
}
}
}

Environment Variables

VariableDescriptionDefault
GITHUB_TOKENGitHub personal access token (raises rate limit to 5,000 req/hr)unauthenticated (60 req/hr)
VERBOSEEnable debug loggingdisabled
GITHUB_TOKEN=ghp_xxxxxxxxxxxx npx @slats/claude-assets-sync -p @package1 -p @package2

For Package Authors

Add a claude field to your package.json and place assets under the declared path:

{
"name": "@your-scope/your-package",
"version": "1.0.0",
"repository": {
"type": "git",
"url": "https://github.com/your-org/your-repo.git",
"directory": "packages/your-package"
},
"claude": {
"assetPath": "docs/claude"
}
}
your-package/
└── docs/claude/
├── commands/
│ └── your-command.md
└── skills/
└── your-skill.md
  • Asset files must be Markdown (.md)
  • repository.type and repository.url are required
  • assetPath is relative to the package root

Sync Flow

1. Read package.json from node_modules (or local workspace)
2. Extract claude.assetPath
3. Parse repository URL → GitHub owner/repo
4. Compare version against .sync-meta.json (skip if unchanged, unless --force)
5. Fetch file list from GitHub API (commands/ and skills/ under assetPath)
6. Download each file from raw.githubusercontent.com
7. Write to .claude/{type}/{prefixed-name}.md
8. Update .sync-meta.json

Programmatic API

import { syncPackage, syncPackages } from '@slats/claude-assets-sync';
import type { CliOptions, SyncResult } from '@slats/claude-assets-sync';

// Sync a single package
const result: SyncResult = await syncPackage('@canard/schema-form', {
force: false,
dryRun: false,
flat: true,
});

// Sync multiple packages
const results = await syncPackages(
['@canard/schema-form', '@lerx/promise-modal'],
{
force: true,
},
);
AI Agent Reference

AI Reference

Package: @slats/claude-assets-sync v0.0.6 Purpose: Claude Code asset synchronization CLI tool.

Exports

import { syncPackage } from '@slats/claude-assets-sync';
import { syncPackages } from '@slats/claude-assets-sync';
import { createProgram } from '@slats/claude-assets-sync';
import { run } from '@slats/claude-assets-sync';
import { migrateToFlat } from '@slats/claude-assets-sync';
import { needsMigration } from '@slats/claude-assets-sync';
import type { MigrationResult } from '@slats/claude-assets-sync';
import type { AssetType } from '@slats/claude-assets-sync';
import type { CliOptions } from '@slats/claude-assets-sync';
import type { ClaudeConfig } from '@slats/claude-assets-sync';
import type { GitHubRepoInfo } from '@slats/claude-assets-sync';
import type { PackageInfo } from '@slats/claude-assets-sync';
import type { SyncMeta } from '@slats/claude-assets-sync';
import type { SyncResult } from '@slats/claude-assets-sync';
import type { UnifiedSyncMeta } from '@slats/claude-assets-sync';
import type { PackageSyncInfo } from '@slats/claude-assets-sync';
import type { FileMapping } from '@slats/claude-assets-sync';