@vikasagarwal101/skill-sync 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +206 -0
- package/bin/skill-sync.js +38 -0
- package/bin/skill-sync.sh +1250 -0
- package/install.sh +516 -0
- package/lib/authoring.sh +200 -0
- package/lib/core.sh +221 -0
- package/lib/health.sh +136 -0
- package/lib/inspect.sh +210 -0
- package/lib/sync.sh +281 -0
- package/lib/targets.sh +73 -0
- package/package.json +42 -0
- package/rules/skill-sync.md +96 -0
- package/scripts/bundle.sh +28 -0
- package/skill-sync +131 -0
package/README.md
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# skill-sync
|
|
2
|
+
|
|
3
|
+
Manage AI agent skills across multiple directories. Auto-discovers skill locations, maintains a manifest, and provides create/edit/sync/validate/deploy/doctor commands.
|
|
4
|
+
|
|
5
|
+
## The problem
|
|
6
|
+
|
|
7
|
+
Different AI coding agents look for skills in different directories:
|
|
8
|
+
|
|
9
|
+
| Agent | Scans |
|
|
10
|
+
|-------|-------|
|
|
11
|
+
| OpenCode | `~/.agents/skills/`, `~/.config/opencode/skills/`, `~/.claude/skills/` |
|
|
12
|
+
| Codex | `~/.agents/skills/`, `~/.codex/skills/` |
|
|
13
|
+
| Claude Code | `~/.claude/skills/` only |
|
|
14
|
+
|
|
15
|
+
No single directory is scanned by all three. Skills end up duplicated across locations, versions drift, and symlinks don't work reliably (Claude Code's skill discovery breaks on symlinks).
|
|
16
|
+
|
|
17
|
+
## The solution
|
|
18
|
+
|
|
19
|
+
`skill-sync` treats `~/.agents/skills/` as the canonical source and syncs real copies to agents that need them (currently Claude Code). A manifest tracks what syncs where. A config file allows custom sources and targets.
|
|
20
|
+
|
|
21
|
+
## Quick start
|
|
22
|
+
|
|
23
|
+
### Via npm (recommended)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g @vikasagarwal101/skill-sync # global install
|
|
27
|
+
skill-sync doctor # verify health
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Or one-off without installing:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx @vikasagarwal101/skill-sync doctor
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Via git clone
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git clone https://github.com/vikasagarwal101/skill-sync ~/dev/skill-sync
|
|
40
|
+
cd ~/dev/skill-sync
|
|
41
|
+
./install.sh
|
|
42
|
+
skill-sync doctor # verify health
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Commands
|
|
46
|
+
|
|
47
|
+
### Core
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
sync [name] Sync all manifest skills, or just one
|
|
51
|
+
add <name> [--to T] Deploy a skill to a target (default: claude)
|
|
52
|
+
remove <name> [--from T] Remove from target(s) — use --purge to also delete source
|
|
53
|
+
status Show sync state for all tracked skills
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Authoring
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
create <name> [--scope S] Scaffold new skill with valid frontmatter (default: agents)
|
|
60
|
+
edit <name> Open SKILL.md in $EDITOR, offer sync on exit
|
|
61
|
+
rename <old> <new> Rename a skill across source + all targets + manifest
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Inspection
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
info <name> Show source, sync state, health for one skill
|
|
68
|
+
list [--all] List synced skills, or --all for every skill everywhere
|
|
69
|
+
search <query> Find skills by keyword in name or description
|
|
70
|
+
diff <name> Show content diff between source and target copies
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Health
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
validate [name] Check frontmatter + naming (one or all)
|
|
77
|
+
doctor Full health check across all locations
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Target management
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
target list Show all configured sources and targets
|
|
84
|
+
target add <label> <path> Add a new sync target (persists to config)
|
|
85
|
+
target remove <label> Remove a target (directories untouched)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Maintenance
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
init Rebuild manifest from current state
|
|
92
|
+
pull <name> [--from T] Reverse sync: copy target edits back to source
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Global flags
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
--dry-run Preview any command without making changes
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
### Config file
|
|
104
|
+
|
|
105
|
+
`~/.config/skill-sync/config` is auto-generated when you use `target add/remove`. It's a sourceable bash file that overrides the defaults at startup. You can also edit it manually:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Example: add a project-local target
|
|
109
|
+
declare -A TARGETS=(
|
|
110
|
+
[claude]="$HOME/.claude/skills"
|
|
111
|
+
[work-project]="/path/to/project/.claude/skills"
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Environment variables
|
|
116
|
+
|
|
117
|
+
All paths have env var overrides (checked before the config file):
|
|
118
|
+
|
|
119
|
+
| Variable | Default | Description |
|
|
120
|
+
|----------|---------|-------------|
|
|
121
|
+
| `SKILLSYNC_BIN_DIR` | `~/.local/bin` | Where the CLI is installed |
|
|
122
|
+
| `SKILLSYNC_CONFIG_DIR` | `~/.config/skill-sync` | Manifest and config storage |
|
|
123
|
+
| `SKILLSYNC_AGENTS_DIR` | `~/.agents/skills` | Shared canonical source |
|
|
124
|
+
| `SKILLSYNC_OPENCODE_DIR` | `~/.config/opencode/skills` | OpenCode-only source |
|
|
125
|
+
| `SKILLSYNC_CODEX_DIR` | `~/.codex/skills` | Codex-curated source |
|
|
126
|
+
| `SKILLSYNC_CLAUDE_DIR` | `~/.claude/skills` | Claude Code sync target |
|
|
127
|
+
|
|
128
|
+
## Architecture
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Canonical sources (where skills live — auto-discovered)
|
|
132
|
+
~/.agents/skills/ ← shared (scanned by OpenCode + Codex)
|
|
133
|
+
~/.config/opencode/skills/ ← opencode-only
|
|
134
|
+
~/.codex/skills/ ← codex-curated
|
|
135
|
+
|
|
136
|
+
Sync targets (real copies, pushed from sources)
|
|
137
|
+
~/.claude/skills/ ← Claude Code (can't follow symlinks)
|
|
138
|
+
|
|
139
|
+
Config file (sourced at startup, overrides defaults)
|
|
140
|
+
~/.config/skill-sync/config
|
|
141
|
+
|
|
142
|
+
Manifest (tracks which skills sync to which targets)
|
|
143
|
+
~/.config/skill-sync/manifest
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Nested skills
|
|
147
|
+
|
|
148
|
+
Skills with no root `SKILL.md` but subdirectories containing `SKILL.md` are detected as nested skills with `parent/child` naming (e.g., `greptile/check-pr`). This matches Codex's depth-6 scanning behavior.
|
|
149
|
+
|
|
150
|
+
## YAML frontmatter support
|
|
151
|
+
|
|
152
|
+
The parser handles all common YAML scalar styles:
|
|
153
|
+
- Inline: `description: My skill`
|
|
154
|
+
- Quoted: `description: "My skill"`
|
|
155
|
+
- Folded: `description: >` (multi-line, joined with spaces)
|
|
156
|
+
- Literal: `description: |-` (multi-line)
|
|
157
|
+
|
|
158
|
+
## Supported agents (8)
|
|
159
|
+
|
|
160
|
+
| Agent | Detection path | Registration method |
|
|
161
|
+
|-------|---------------|-------------------|
|
|
162
|
+
| **OpenCode** | `~/.config/opencode/` | Rule file + `opencode.json` instructions array |
|
|
163
|
+
| **Claude Code** | `~/.claude/` | Rule file + `@import` in `CLAUDE.md` |
|
|
164
|
+
| **Codex** | `~/.codex/` | Marker section in `AGENTS.md` |
|
|
165
|
+
| **Kilo Code** | `~/.config/kilo/` | Rule file + `kilo.jsonc` instructions array |
|
|
166
|
+
| **Gemini CLI** | `~/.gemini/` | Rule file + `@import` in `GEMINI.md` |
|
|
167
|
+
| **Auggie** | `~/.augment/` | Rule file (auto-discovered in `~/.augment/rules/`) |
|
|
168
|
+
| **Devin** | `~/.devin/` | Marker section in `AGENTS.md` |
|
|
169
|
+
| **Antigravity** | `~/.gemini/antigravity/` | No registration needed (reads `AGENTS.md` + scans `~/.agents/skills/`) |
|
|
170
|
+
|
|
171
|
+
## Install
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
git clone https://github.com/vikasagarwal101/skill-sync ~/dev/skill-sync
|
|
175
|
+
cd ~/dev/skill-sync
|
|
176
|
+
./install.sh
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Interactive mode detects all installed agents and prompts for each:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
Detected agents: opencode, claude, codex, kilo, gemini, auggie, antigravity
|
|
183
|
+
|
|
184
|
+
Register with opencode (rule file + opencode.json)? [Y/n]
|
|
185
|
+
Register with claude (rule file + CLAUDE.md import)? [Y/n]
|
|
186
|
+
Register with codex (AGENTS.md section)? [Y/n]
|
|
187
|
+
Register with kilo (rule file + kilo.jsonc instructions)? [Y/n]
|
|
188
|
+
Register with gemini (rule file + GEMINI.md import)? [Y/n]
|
|
189
|
+
Register with auggie (rule file, auto-discovered)? [Y/n]
|
|
190
|
+
Antigravity: automatic — no registration needed
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Non-interactive options:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
./install.sh --with-rules all # register with all detected agents
|
|
197
|
+
./install.sh --with-rules opencode,claude,kilo # specific agents only
|
|
198
|
+
./install.sh --no-rules # CLI only, no agent registration
|
|
199
|
+
./install.sh --uninstall # remove everything (prompts per agent)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Requirements
|
|
203
|
+
|
|
204
|
+
- Bash 4.0+ (associative arrays)
|
|
205
|
+
- `awk`, `find`, `md5sum`, `du`
|
|
206
|
+
- Linux or macOS
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* skill-sync — thin Node.js wrapper that spawns the bundled bash script.
|
|
7
|
+
*
|
|
8
|
+
* This file exists so that `npm install -g skill-sync` puts `skill-sync` on PATH.
|
|
9
|
+
* It simply forwards all arguments to the bash implementation.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { spawn } = require("child_process");
|
|
13
|
+
const path = require("path");
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
|
|
16
|
+
// Find the bundled bash script (next to this JS file)
|
|
17
|
+
const scriptPath = path.join(__dirname, "skill-sync.sh");
|
|
18
|
+
|
|
19
|
+
if (!fs.existsSync(scriptPath)) {
|
|
20
|
+
process.stderr.write("Error: bundled script not found at " + scriptPath + "\n");
|
|
21
|
+
process.stderr.write("Run: bash scripts/bundle.sh\n");
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Spawn bash with the script, forwarding all arguments
|
|
26
|
+
const child = spawn("bash", [scriptPath, ...process.argv.slice(2)], {
|
|
27
|
+
stdio: "inherit",
|
|
28
|
+
env: process.env,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
child.on("close", (code) => {
|
|
32
|
+
process.exit(code ?? 1);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
child.on("error", (err) => {
|
|
36
|
+
process.stderr.write("Error: " + err.message + "\n");
|
|
37
|
+
process.exit(1);
|
|
38
|
+
});
|