@bitkyc08/agent-sync 0.1.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 ADDED
@@ -0,0 +1,61 @@
1
+ # agent-sync
2
+
3
+ > Sync MCP, skills, and AGENTS.md across **all** AI coding agents — one command.
4
+
5
+ Supports: **Claude Code** · **Codex** · **Copilot** · **Gemini CLI** · **Antigravity** · **OpenCode**
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install -g agent-sync
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Interactive wizard — guides you through prompt, skills, and MCP setup
17
+ agent-sync
18
+
19
+ # Individual commands
20
+ agent-sync mcp # Sync MCP config globally (→ 6 CLIs)
21
+ agent-sync skills # Sync skill symlinks in project
22
+ agent-sync agents # Generate AGENTS.md in project
23
+ ```
24
+
25
+ ## What It Does
26
+
27
+ ### 1. AGENTS.md (Project-level)
28
+ Auto-detects prompt files (`AGENTS.md`, `CLAUDE.md`, `COPILOT.md`, etc.) in your project.
29
+ Writes a unified `AGENTS.md` that Codex, Copilot, and OpenCode discover automatically.
30
+
31
+ ### 2. Skills Sync (Project-level)
32
+ Creates symlinks so all agents find the same skills:
33
+ ```
34
+ .agent/skills/ ← source (real files)
35
+ .agents/skills/ → .agent/skills (symlink)
36
+ .claude/skills/ → .agent/skills (symlink)
37
+ ```
38
+
39
+ ### 3. MCP Config (Global)
40
+ One `~/.agent-sync/mcp.json` → synced to all CLI configs:
41
+
42
+ | Target | Path | Format |
43
+ |--------|------|--------|
44
+ | Claude Code | `~/.mcp.json` | JSON `mcpServers` |
45
+ | Codex | `~/.codex/config.toml` | TOML `[mcp_servers.*]` |
46
+ | Gemini CLI | `~/.gemini/settings.json` | JSON `mcpServers` |
47
+ | OpenCode | `~/.config/opencode/opencode.json` | JSON `mcp` |
48
+ | Copilot | `~/.copilot/mcp-config.json` | JSON `mcpServers` |
49
+ | Antigravity | `~/.gemini/antigravity/mcp_config.json` | JSON `mcpServers` |
50
+
51
+ ## Config Location
52
+
53
+ ```
54
+ ~/.agent-sync/
55
+ ├── mcp.json # Unified MCP source of truth
56
+ └── backups/ # Auto-backups on conflict
57
+ ```
58
+
59
+ ## License
60
+
61
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,290 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * agent-sync CLI — Interactive wizard for syncing AI agent configs
4
+ *
5
+ * Usage:
6
+ * agent-sync Run interactive wizard (prompt → skills → MCP → sync)
7
+ * agent-sync mcp MCP sync only (global)
8
+ * agent-sync skills Skills sync only (project)
9
+ * agent-sync agents AGENTS.md sync only (project)
10
+ * agent-sync all Run all without prompts (uses detected defaults)
11
+ */
12
+ import fs from 'node:fs';
13
+ import { join } from 'node:path';
14
+ import { log } from './utils/log.js';
15
+ import { ask, choose } from './utils/prompt.js';
16
+ import { ensureHome, MCP_PATH, AGENT_SYNC_HOME } from './core/config.js';
17
+ import { detectPromptFiles, generateAgentsMd } from './core/agents-md.js';
18
+ import { detectSkillSources, syncSkills, listSkills } from './core/skill-sync.js';
19
+ import { detectMcpConfigs, loadMcpConfig, saveMcpConfig, syncToAll, importFromClaude } from './core/mcp-sync.js';
20
+ const VERSION = '0.1.0';
21
+ const cwd = process.cwd();
22
+ // ─── Subcommand routing ───────────────────────────
23
+ async function main() {
24
+ const args = process.argv.slice(2);
25
+ const cmd = args[0];
26
+ if (cmd === '--version' || cmd === '-v') {
27
+ console.log(`agent-sync v${VERSION}`);
28
+ return;
29
+ }
30
+ if (cmd === '--help' || cmd === '-h') {
31
+ printHelp();
32
+ return;
33
+ }
34
+ ensureHome();
35
+ if (!cmd || cmd === 'all') {
36
+ await wizardFull();
37
+ }
38
+ else if (cmd === 'mcp') {
39
+ await wizardMcp();
40
+ }
41
+ else if (cmd === 'skills') {
42
+ await wizardSkills();
43
+ }
44
+ else if (cmd === 'agents') {
45
+ await wizardAgents();
46
+ }
47
+ else {
48
+ log.err(`Unknown command: ${cmd}`);
49
+ printHelp();
50
+ process.exit(1);
51
+ }
52
+ }
53
+ function printHelp() {
54
+ console.log(`
55
+ agent-sync v${VERSION}
56
+ Sync MCP, skills, and AGENTS.md across all AI coding agents.
57
+
58
+ Usage:
59
+ agent-sync Interactive wizard (all steps)
60
+ agent-sync mcp MCP config sync (global → 6 CLIs)
61
+ agent-sync skills Skills symlink sync (project-level)
62
+ agent-sync agents AGENTS.md generation (project-level)
63
+ agent-sync all Run all with detected defaults
64
+
65
+ Options:
66
+ -h, --help Show this help
67
+ -v, --version Show version
68
+ `);
69
+ }
70
+ // ─── Full wizard ──────────────────────────────────
71
+ async function wizardFull() {
72
+ console.log(`\n agent-sync v${VERSION}\n`);
73
+ // Step 1: AGENTS.md / Prompt
74
+ log.header('Step 1/3 — AGENTS.md (Prompt File)');
75
+ await wizardAgents();
76
+ // Step 2: Skills
77
+ log.header('Step 2/3 — Skills Sync');
78
+ await wizardSkills();
79
+ // Step 3: MCP
80
+ log.header('Step 3/3 — MCP Config Sync (Global)');
81
+ await wizardMcp();
82
+ console.log('');
83
+ log.ok('All done! Your agent configs are synced.');
84
+ }
85
+ // ─── Agents wizard ────────────────────────────────
86
+ async function wizardAgents() {
87
+ const candidates = detectPromptFiles(cwd);
88
+ if (candidates.length === 0) {
89
+ log.choice(1, 'NONE', '(no prompt files detected)');
90
+ const selection = await choose('Select prompt source', 1);
91
+ if (selection === 1) {
92
+ console.log('');
93
+ log.info('Enter your prompt content below.');
94
+ log.info('Press Ctrl+D (EOF) when done, or type "SKIP" to skip this step.\n');
95
+ const content = await readMultiline();
96
+ if (content.trim() === 'SKIP' || content.trim() === '') {
97
+ log.warn('Skipped AGENTS.md generation.');
98
+ return;
99
+ }
100
+ // Confirm no conflict
101
+ const existing = join(cwd, 'AGENTS.md');
102
+ if (fs.existsSync(existing)) {
103
+ const ans = await ask(' AGENTS.md already exists. Overwrite? [y/N]: ');
104
+ if (ans.toLowerCase() !== 'y') {
105
+ log.warn('Skipped (not overwriting).');
106
+ return;
107
+ }
108
+ }
109
+ generateAgentsMd(cwd, content);
110
+ }
111
+ return;
112
+ }
113
+ // Show detected candidates
114
+ for (let i = 0; i < candidates.length; i++) {
115
+ const c = candidates[i];
116
+ log.choice(i + 1, c.label, `(${c.sizeKB}KB)`);
117
+ }
118
+ log.choice(candidates.length + 1, 'NONE', '(enter raw prompt manually)');
119
+ const selection = await choose('Select prompt source', candidates.length + 1);
120
+ if (selection <= candidates.length) {
121
+ // Use selected file
122
+ const chosen = candidates[selection - 1];
123
+ const content = fs.readFileSync(chosen.path, 'utf8');
124
+ log.info(`Using: ${chosen.label}`);
125
+ generateAgentsMd(cwd, content);
126
+ }
127
+ else {
128
+ // Manual input
129
+ log.info('Enter your prompt content (Ctrl+D to finish, "SKIP" to skip):');
130
+ const content = await readMultiline();
131
+ if (content.trim() === 'SKIP' || content.trim() === '') {
132
+ log.warn('Skipped AGENTS.md generation.');
133
+ return;
134
+ }
135
+ generateAgentsMd(cwd, content);
136
+ }
137
+ }
138
+ // ─── Skills wizard ────────────────────────────────
139
+ async function wizardSkills() {
140
+ const candidates = detectSkillSources(cwd);
141
+ if (candidates.length === 0) {
142
+ log.choice(1, 'NONE', '(no skill directories detected)');
143
+ const selection = await choose('Select skill source', 1);
144
+ if (selection === 1) {
145
+ const defaultDir = join(cwd, '.agent', 'skills');
146
+ fs.mkdirSync(defaultDir, { recursive: true });
147
+ console.log('');
148
+ log.info(`Created: ${defaultDir}`);
149
+ log.info('Place your SKILL.md folders here and run agent-sync again.');
150
+ return;
151
+ }
152
+ return;
153
+ }
154
+ // Show detected candidates
155
+ for (let i = 0; i < candidates.length; i++) {
156
+ const c = candidates[i];
157
+ log.choice(i + 1, c.label, `(${c.count} skills)`);
158
+ }
159
+ log.choice(candidates.length + 1, 'NONE', '(create empty skill directory)');
160
+ const selection = await choose('Select skill source', candidates.length + 1);
161
+ if (selection <= candidates.length) {
162
+ const chosen = candidates[selection - 1];
163
+ log.info(`Using: ${chosen.label} (${chosen.count} skills)`);
164
+ console.log(' Syncing...');
165
+ const result = syncSkills(cwd, chosen.path);
166
+ for (const link of result.links) {
167
+ if (link.status === 'ok') {
168
+ log.ok(`${link.name}: ${link.linkPath} → ${link.target}`);
169
+ }
170
+ else if (link.status === 'skip') {
171
+ log.dim(`${link.name}: ${link.action}`);
172
+ }
173
+ else {
174
+ log.err(`${link.name}: ${link.error}`);
175
+ }
176
+ }
177
+ const skills = listSkills(chosen.path);
178
+ log.info(`Active skills: ${skills.join(', ')}`);
179
+ }
180
+ else {
181
+ const defaultDir = join(cwd, '.agent', 'skills');
182
+ fs.mkdirSync(defaultDir, { recursive: true });
183
+ console.log('');
184
+ log.info(`Created: ${defaultDir}`);
185
+ log.info('Place your SKILL.md folders here and run agent-sync again.');
186
+ }
187
+ }
188
+ // ─── MCP wizard ───────────────────────────────────
189
+ async function wizardMcp() {
190
+ const candidates = detectMcpConfigs();
191
+ if (candidates.length === 0) {
192
+ log.choice(1, 'NONE', '(no MCP configs detected)');
193
+ const selection = await choose('Select MCP source', 1);
194
+ if (selection === 1) {
195
+ fs.mkdirSync(AGENT_SYNC_HOME, { recursive: true });
196
+ const defaultConfig = {
197
+ servers: {
198
+ context7: {
199
+ command: 'npx',
200
+ args: ['-y', '@upstash/context7-mcp'],
201
+ },
202
+ },
203
+ };
204
+ saveMcpConfig(defaultConfig);
205
+ console.log('');
206
+ log.info(`Created: ${MCP_PATH}`);
207
+ log.dim(JSON.stringify(defaultConfig, null, 2).split('\n').slice(0, 8).join('\n '));
208
+ log.info('Edit this file to add your MCP servers, then run agent-sync again.');
209
+ return;
210
+ }
211
+ return;
212
+ }
213
+ // Show detected candidates
214
+ for (let i = 0; i < candidates.length; i++) {
215
+ const c = candidates[i];
216
+ log.choice(i + 1, c.label, `(${c.count} servers) ${c.path}`);
217
+ }
218
+ log.choice(candidates.length + 1, 'NONE', '(create default MCP config)');
219
+ const selection = await choose('Select MCP source', candidates.length + 1);
220
+ if (selection <= candidates.length) {
221
+ const chosen = candidates[selection - 1];
222
+ log.info(`Using: ${chosen.label} (${chosen.count} servers)`);
223
+ // Import to unified format if not already agent-sync config
224
+ let config;
225
+ if (chosen.label === 'agent-sync') {
226
+ config = loadMcpConfig();
227
+ }
228
+ else if (chosen.label === 'Claude') {
229
+ config = importFromClaude() ?? { servers: {} };
230
+ saveMcpConfig(config);
231
+ log.ok(`Imported to ${MCP_PATH}`);
232
+ }
233
+ else {
234
+ // For other sources, import from Claude format (similar structure)
235
+ try {
236
+ const raw = JSON.parse(fs.readFileSync(chosen.path, 'utf8'));
237
+ const servers = {};
238
+ const mcpServers = raw.mcpServers || raw.mcp || {};
239
+ for (const [name, srv] of Object.entries(mcpServers)) {
240
+ servers[name] = { command: srv.command, args: srv.args || [] };
241
+ if (srv.env)
242
+ servers[name].env = srv.env;
243
+ }
244
+ config = { servers };
245
+ saveMcpConfig(config);
246
+ log.ok(`Imported to ${MCP_PATH}`);
247
+ }
248
+ catch {
249
+ log.err('Failed to parse selected config');
250
+ return;
251
+ }
252
+ }
253
+ // Sync to all
254
+ console.log(' Syncing to all CLIs...');
255
+ const results = syncToAll(config);
256
+ const synced = Object.values(results).filter(Boolean).length;
257
+ log.info(`Synced to ${synced}/6 CLIs.`);
258
+ }
259
+ else {
260
+ fs.mkdirSync(AGENT_SYNC_HOME, { recursive: true });
261
+ const defaultConfig = {
262
+ servers: {
263
+ context7: {
264
+ command: 'npx',
265
+ args: ['-y', '@upstash/context7-mcp'],
266
+ },
267
+ },
268
+ };
269
+ saveMcpConfig(defaultConfig);
270
+ console.log('');
271
+ log.info(`Created: ${MCP_PATH}`);
272
+ log.info('Edit this file to add your MCP servers, then run agent-sync again.');
273
+ }
274
+ }
275
+ // ─── Helpers ──────────────────────────────────────
276
+ function readMultiline() {
277
+ return new Promise((resolve) => {
278
+ const chunks = [];
279
+ process.stdin.setEncoding('utf8');
280
+ process.stdin.on('data', (chunk) => chunks.push(String(chunk)));
281
+ process.stdin.on('end', () => resolve(chunks.join('')));
282
+ process.stdin.resume();
283
+ });
284
+ }
285
+ // ─── Run ──────────────────────────────────────────
286
+ main().catch((e) => {
287
+ log.err(e.message);
288
+ process.exit(1);
289
+ });
290
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface PromptCandidate {
2
+ label: string;
3
+ path: string;
4
+ sizeKB: number;
5
+ }
6
+ export declare function detectPromptFiles(cwd: string): PromptCandidate[];
7
+ export interface AgentsMdResult {
8
+ targets: string[];
9
+ size: number;
10
+ }
11
+ export declare function generateAgentsMd(cwd: string, content: string): AgentsMdResult;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * core/agents-md.ts — AGENTS.md generation (project-level)
3
+ *
4
+ * Auto-detects prompt template files from project.
5
+ * Writes AGENTS.md to project root for Codex/Copilot/OpenCode discovery.
6
+ */
7
+ import fs from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { log } from '../utils/log.js';
10
+ export function detectPromptFiles(cwd) {
11
+ const candidates = [];
12
+ // Only check files directly in project root (no subdirectory scanning)
13
+ const patterns = [
14
+ 'AGENTS.md',
15
+ 'CLAUDE.md',
16
+ 'COPILOT.md',
17
+ 'INSTRUCTIONS.md',
18
+ 'PROMPT.md',
19
+ 'CODEX.md',
20
+ '.github/copilot-instructions.md',
21
+ ];
22
+ for (const pattern of patterns) {
23
+ const fullPath = join(cwd, pattern);
24
+ try {
25
+ const stat = fs.statSync(fullPath);
26
+ if (stat.isFile() && stat.size > 0) {
27
+ candidates.push({
28
+ label: pattern,
29
+ path: fullPath,
30
+ sizeKB: Math.round(stat.size / 1024),
31
+ });
32
+ }
33
+ }
34
+ catch { /* skip */ }
35
+ }
36
+ return candidates;
37
+ }
38
+ export function generateAgentsMd(cwd, content) {
39
+ const targets = [
40
+ join(cwd, 'AGENTS.md'),
41
+ ];
42
+ for (const target of targets) {
43
+ fs.mkdirSync(join(target, '..'), { recursive: true });
44
+ fs.writeFileSync(target, content);
45
+ log.ok(`Written: ${target}`);
46
+ }
47
+ return { targets, size: content.length };
48
+ }
49
+ //# sourceMappingURL=agents-md.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents-md.js","sourceRoot":"","sources":["../../src/core/agents-md.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAY,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAUtC,MAAM,UAAU,iBAAiB,CAAC,GAAW;IACzC,MAAM,UAAU,GAAsB,EAAE,CAAC;IAEzC,uEAAuE;IACvE,MAAM,QAAQ,GAAG;QACb,WAAW;QACX,WAAW;QACX,YAAY;QACZ,iBAAiB;QACjB,WAAW;QACX,UAAU;QACV,iCAAiC;KACpC,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC;YACD,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBACjC,UAAU,CAAC,IAAI,CAAC;oBACZ,KAAK,EAAE,OAAO;oBACd,IAAI,EAAE,QAAQ;oBACd,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;iBACvC,CAAC,CAAC;YACP,CAAC;QACL,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,UAAU,CAAC;AACtB,CAAC;AASD,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,OAAe;IACzD,MAAM,OAAO,GAAG;QACZ,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC;KACzB,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC3B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,GAAG,CAAC,EAAE,CAAC,YAAY,MAAM,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const HOME: string;
2
+ export declare const AGENT_SYNC_HOME: string;
3
+ export declare const MCP_PATH: string;
4
+ export declare const SKILLS_DIR: string;
5
+ export declare const SKILLS_REF_DIR: string;
6
+ export declare function ensureHome(): void;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * core/config.ts — Configuration & paths
3
+ */
4
+ import { join, resolve } from 'node:path';
5
+ import os from 'node:os';
6
+ import fs from 'node:fs';
7
+ export const HOME = os.homedir();
8
+ export const AGENT_SYNC_HOME = process.env.AGENT_SYNC_HOME
9
+ ? resolve(process.env.AGENT_SYNC_HOME.replace(/^~(?=\/|$)/, HOME))
10
+ : join(HOME, '.agent-sync');
11
+ export const MCP_PATH = join(AGENT_SYNC_HOME, 'mcp.json');
12
+ export const SKILLS_DIR = join(AGENT_SYNC_HOME, 'skills');
13
+ export const SKILLS_REF_DIR = join(AGENT_SYNC_HOME, 'skills_ref');
14
+ export function ensureHome() {
15
+ fs.mkdirSync(AGENT_SYNC_HOME, { recursive: true });
16
+ fs.mkdirSync(SKILLS_DIR, { recursive: true });
17
+ }
18
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;AACjC,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe;IACtD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;AAEhC,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;AAElE,MAAM,UAAU,UAAU;IACtB,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC"}
@@ -0,0 +1,18 @@
1
+ export declare function loadMcpConfig(): Record<string, any>;
2
+ export declare function saveMcpConfig(config: Record<string, any>): void;
3
+ export declare function importFromClaude(): Record<string, any> | null;
4
+ export interface McpCandidate {
5
+ label: string;
6
+ path: string;
7
+ count: number;
8
+ }
9
+ export declare function detectMcpConfigs(): McpCandidate[];
10
+ export interface SyncResults {
11
+ claude: boolean;
12
+ codex: boolean;
13
+ gemini: boolean;
14
+ opencode: boolean;
15
+ copilot: boolean;
16
+ antigravity: boolean;
17
+ }
18
+ export declare function syncToAll(config: Record<string, any>): SyncResults;
@@ -0,0 +1,240 @@
1
+ /**
2
+ * core/mcp-sync.ts — MCP config sync to all AI coding CLIs (global)
3
+ * Extracted from cli-jaw lib/mcp-sync.ts
4
+ *
5
+ * Source of truth: ~/.agent-sync/mcp.json
6
+ * Targets (all global):
7
+ * Claude Code → ~/.mcp.json (JSON, mcpServers)
8
+ * Codex → ~/.codex/config.toml (TOML, [mcp_servers.*])
9
+ * Gemini CLI → ~/.gemini/settings.json (JSON, mcpServers)
10
+ * OpenCode → ~/.config/opencode/opencode.json (JSON, mcp)
11
+ * Copilot → ~/.copilot/mcp-config.json (JSON, mcpServers)
12
+ * Antigravity → ~/.gemini/antigravity/mcp_config.json (JSON, mcpServers)
13
+ */
14
+ import fs from 'node:fs';
15
+ import { join, dirname } from 'node:path';
16
+ import os from 'node:os';
17
+ import { MCP_PATH, ensureHome } from './config.js';
18
+ import { log } from '../utils/log.js';
19
+ const HOME = os.homedir();
20
+ // ─── Load / Save ──────────────────────────────────
21
+ export function loadMcpConfig() {
22
+ try {
23
+ return JSON.parse(fs.readFileSync(MCP_PATH, 'utf8'));
24
+ }
25
+ catch {
26
+ return { servers: {} };
27
+ }
28
+ }
29
+ export function saveMcpConfig(config) {
30
+ ensureHome();
31
+ fs.writeFileSync(MCP_PATH, JSON.stringify(config, null, 4) + '\n');
32
+ }
33
+ // ─── Format converters ────────────────────────────
34
+ function toClaudeMcp(config) {
35
+ const servers = config.servers || {};
36
+ const result = {};
37
+ for (const [name, srv] of Object.entries(servers)) {
38
+ result[name] = { command: srv.command, args: srv.args || [] };
39
+ if (srv.env)
40
+ result[name].env = srv.env;
41
+ }
42
+ return { mcpServers: result };
43
+ }
44
+ function toCodexToml(config) {
45
+ const servers = config.servers || {};
46
+ let toml = '';
47
+ for (const [name, srv] of Object.entries(servers)) {
48
+ toml += `[mcp_servers.${name}]\n`;
49
+ toml += `command = "${srv.command}"\n`;
50
+ if (srv.args?.length) {
51
+ toml += `args = [${srv.args.map((a) => `"${a}"`).join(', ')}]\n`;
52
+ }
53
+ if (srv.env) {
54
+ toml += `[mcp_servers.${name}.env]\n`;
55
+ for (const [k, v] of Object.entries(srv.env)) {
56
+ toml += `${k} = "${v}"\n`;
57
+ }
58
+ }
59
+ toml += '\n';
60
+ }
61
+ return toml;
62
+ }
63
+ function toOpenCodeMcp(config) {
64
+ const servers = config.servers || {};
65
+ const result = {};
66
+ for (const [name, srv] of Object.entries(servers)) {
67
+ result[name] = { command: srv.command, args: srv.args || [] };
68
+ if (srv.env)
69
+ result[name].env = srv.env;
70
+ }
71
+ return result;
72
+ }
73
+ function patchCodexToml(existingToml, newMcpToml) {
74
+ // Remove existing [mcp_servers.*] blocks
75
+ const cleaned = existingToml.replace(/\[mcp_servers\.[^\]]+\][\s\S]*?(?=\n\[(?!mcp_servers)|$)/g, '').trimEnd();
76
+ return cleaned + '\n\n' + newMcpToml;
77
+ }
78
+ function patchJsonFile(filePath, patchObj) {
79
+ let existing = {};
80
+ try {
81
+ existing = JSON.parse(fs.readFileSync(filePath, 'utf8'));
82
+ }
83
+ catch { }
84
+ Object.assign(existing, patchObj);
85
+ fs.writeFileSync(filePath, JSON.stringify(existing, null, 4) + '\n');
86
+ }
87
+ // ─── Import ───────────────────────────────────────
88
+ export function importFromClaude() {
89
+ const p = join(HOME, '.mcp.json');
90
+ try {
91
+ const data = JSON.parse(fs.readFileSync(p, 'utf8'));
92
+ const mcpServers = data.mcpServers || {};
93
+ const servers = {};
94
+ for (const [name, srv] of Object.entries(mcpServers)) {
95
+ servers[name] = { command: srv.command, args: srv.args || [] };
96
+ if (srv.env)
97
+ servers[name].env = srv.env;
98
+ }
99
+ return { servers };
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ export function detectMcpConfigs() {
106
+ const candidates = [];
107
+ const checks = [
108
+ ['agent-sync', MCP_PATH],
109
+ ['Claude', join(HOME, '.mcp.json')],
110
+ ['Codex', join(HOME, '.codex', 'config.toml')],
111
+ ['Gemini', join(HOME, '.gemini', 'settings.json')],
112
+ ['Copilot', join(HOME, '.copilot', 'mcp-config.json')],
113
+ ['Antigravity', join(HOME, '.gemini', 'antigravity', 'mcp_config.json')],
114
+ ['OpenCode', join(HOME, '.config', 'opencode', 'opencode.json')],
115
+ ];
116
+ for (const [label, path] of checks) {
117
+ try {
118
+ const raw = fs.readFileSync(path, 'utf8');
119
+ let count = 0;
120
+ if (path.endsWith('.toml')) {
121
+ count = (raw.match(/\[mcp_servers\./g) || []).length;
122
+ }
123
+ else {
124
+ const data = JSON.parse(raw);
125
+ const servers = data.mcpServers || data.servers || data.mcp || {};
126
+ count = Object.keys(servers).length;
127
+ }
128
+ if (count > 0)
129
+ candidates.push({ label, path, count });
130
+ }
131
+ catch { /* skip */ }
132
+ }
133
+ return candidates;
134
+ }
135
+ export function syncToAll(config) {
136
+ const results = {
137
+ claude: false, codex: false, gemini: false,
138
+ opencode: false, copilot: false, antigravity: false,
139
+ };
140
+ // 1. Claude Code: ~/.mcp.json
141
+ try {
142
+ const p = join(HOME, '.mcp.json');
143
+ const data = toClaudeMcp(config);
144
+ let existing = {};
145
+ try {
146
+ existing = JSON.parse(fs.readFileSync(p, 'utf8'));
147
+ }
148
+ catch { }
149
+ existing.mcpServers = data.mcpServers;
150
+ fs.writeFileSync(p, JSON.stringify(existing, null, 4) + '\n');
151
+ results.claude = true;
152
+ log.ok(`Claude: ${p}`);
153
+ }
154
+ catch (e) {
155
+ log.err(`Claude: ${e.message}`);
156
+ }
157
+ // 2. Codex: ~/.codex/config.toml
158
+ try {
159
+ const p = join(HOME, '.codex', 'config.toml');
160
+ if (fs.existsSync(p)) {
161
+ const existing = fs.readFileSync(p, 'utf8');
162
+ fs.writeFileSync(p, patchCodexToml(existing, toCodexToml(config)));
163
+ results.codex = true;
164
+ log.ok(`Codex: ${p}`);
165
+ }
166
+ else {
167
+ log.dim(`Codex: config.toml not found, skipping`);
168
+ }
169
+ }
170
+ catch (e) {
171
+ log.err(`Codex: ${e.message}`);
172
+ }
173
+ // 3. Gemini CLI: ~/.gemini/settings.json
174
+ try {
175
+ const p = join(HOME, '.gemini', 'settings.json');
176
+ if (fs.existsSync(p)) {
177
+ patchJsonFile(p, { mcpServers: toClaudeMcp(config).mcpServers });
178
+ results.gemini = true;
179
+ log.ok(`Gemini: ${p}`);
180
+ }
181
+ else {
182
+ log.dim(`Gemini: settings.json not found, skipping`);
183
+ }
184
+ }
185
+ catch (e) {
186
+ log.err(`Gemini: ${e.message}`);
187
+ }
188
+ // 4. OpenCode: ~/.config/opencode/opencode.json
189
+ try {
190
+ const p = join(HOME, '.config', 'opencode', 'opencode.json');
191
+ if (fs.existsSync(p)) {
192
+ patchJsonFile(p, { mcp: toOpenCodeMcp(config) });
193
+ results.opencode = true;
194
+ log.ok(`OpenCode: ${p}`);
195
+ }
196
+ else {
197
+ log.dim(`OpenCode: opencode.json not found, skipping`);
198
+ }
199
+ }
200
+ catch (e) {
201
+ log.err(`OpenCode: ${e.message}`);
202
+ }
203
+ // 5. Copilot: ~/.copilot/mcp-config.json
204
+ try {
205
+ const dir = join(HOME, '.copilot');
206
+ const p = join(dir, 'mcp-config.json');
207
+ fs.mkdirSync(dir, { recursive: true });
208
+ let existing = {};
209
+ try {
210
+ existing = JSON.parse(fs.readFileSync(p, 'utf8'));
211
+ }
212
+ catch { }
213
+ existing.mcpServers = toClaudeMcp(config).mcpServers;
214
+ fs.writeFileSync(p, JSON.stringify(existing, null, 4) + '\n');
215
+ results.copilot = true;
216
+ log.ok(`Copilot: ${p}`);
217
+ }
218
+ catch (e) {
219
+ log.err(`Copilot: ${e.message}`);
220
+ }
221
+ // 6. Antigravity: ~/.gemini/antigravity/mcp_config.json
222
+ try {
223
+ const p = join(HOME, '.gemini', 'antigravity', 'mcp_config.json');
224
+ fs.mkdirSync(dirname(p), { recursive: true });
225
+ let existing = {};
226
+ try {
227
+ existing = JSON.parse(fs.readFileSync(p, 'utf8'));
228
+ }
229
+ catch { }
230
+ existing.mcpServers = toClaudeMcp(config).mcpServers;
231
+ fs.writeFileSync(p, JSON.stringify(existing, null, 4) + '\n');
232
+ results.antigravity = true;
233
+ log.ok(`Antigravity: ${p}`);
234
+ }
235
+ catch (e) {
236
+ log.err(`Antigravity: ${e.message}`);
237
+ }
238
+ return results;
239
+ }
240
+ //# sourceMappingURL=mcp-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-sync.js","sourceRoot":"","sources":["../../src/core/mcp-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type SymlinkResult } from './symlink.js';
2
+ export interface SkillCandidate {
3
+ label: string;
4
+ path: string;
5
+ count: number;
6
+ }
7
+ export declare function detectSkillSources(cwd: string): SkillCandidate[];
8
+ export interface SkillSyncResult {
9
+ source: string;
10
+ links: SymlinkResult[];
11
+ }
12
+ export declare function syncSkills(cwd: string, sourcePath: string): SkillSyncResult;
13
+ export declare function listSkills(skillsDir: string): string[];
@@ -0,0 +1,105 @@
1
+ /**
2
+ * core/skill-sync.ts — Skills symlink sync (project-level)
3
+ * Extracted from cli-jaw lib/mcp-sync.ts
4
+ *
5
+ * Creates symlinks so all AI agents can find skills:
6
+ * {cwd}/.agent/skills/ ← source directory (real files)
7
+ * {cwd}/.agents/skills/ → .agent/skills (symlink)
8
+ * {cwd}/.claude/skills/ → .agent/skills (symlink)
9
+ */
10
+ import fs from 'node:fs';
11
+ import { join } from 'node:path';
12
+ import { ensureSymlinkSafe, createBackupContext } from './symlink.js';
13
+ export function detectSkillSources(cwd) {
14
+ const candidates = [];
15
+ // Common locations to check
16
+ const checks = [
17
+ ['Project .agent/skills', join(cwd, '.agent', 'skills')],
18
+ ['Project .agents/skills', join(cwd, '.agents', 'skills')],
19
+ ['Project .claude/skills', join(cwd, '.claude', 'skills')],
20
+ ['Project skills_ref/', join(cwd, 'skills_ref')],
21
+ ];
22
+ // Also walk one level of subdirectories for monorepo patterns
23
+ try {
24
+ for (const entry of fs.readdirSync(cwd, { withFileTypes: true })) {
25
+ if (!entry.isDirectory() || entry.name.startsWith('.'))
26
+ continue;
27
+ const sub = join(cwd, entry.name, 'skills_ref');
28
+ if (fs.existsSync(sub)) {
29
+ checks.push([`${entry.name}/skills_ref`, sub]);
30
+ }
31
+ }
32
+ }
33
+ catch { /* ignore */ }
34
+ for (const [label, path] of checks) {
35
+ try {
36
+ const realPath = fs.realpathSync(path);
37
+ const stat = fs.statSync(realPath);
38
+ if (stat.isDirectory()) {
39
+ const items = fs.readdirSync(realPath).filter((f) => !f.startsWith('.') && f !== 'registry.json');
40
+ const skillCount = items.filter((f) => fs.statSync(join(realPath, f)).isDirectory()).length;
41
+ if (skillCount > 0) {
42
+ // Dedup by realPath
43
+ if (!candidates.some((c) => fs.realpathSync(c.path) === realPath)) {
44
+ candidates.push({ label, path, count: skillCount });
45
+ }
46
+ }
47
+ }
48
+ }
49
+ catch { /* skip broken paths */ }
50
+ }
51
+ return candidates;
52
+ }
53
+ export function syncSkills(cwd, sourcePath) {
54
+ const backupContext = createBackupContext();
55
+ const links = [];
56
+ // Target paths within the project
57
+ const targets = [
58
+ ['agent_skills', join(cwd, '.agent', 'skills')],
59
+ ['agents_skills', join(cwd, '.agents', 'skills')],
60
+ ['claude_skills', join(cwd, '.claude', 'skills')],
61
+ ];
62
+ // Determine canonical location (first real directory or the source itself)
63
+ const canonicalPath = join(cwd, '.agent', 'skills');
64
+ for (const [name, targetPath] of targets) {
65
+ if (targetPath === sourcePath) {
66
+ // Source IS this path — skip
67
+ links.push({
68
+ status: 'skip', action: 'is_source', name, linkPath: targetPath, target: sourcePath,
69
+ });
70
+ continue;
71
+ }
72
+ if (targetPath === canonicalPath && sourcePath !== canonicalPath) {
73
+ // .agent/skills is the canonical target — symlink to source
74
+ links.push(ensureSymlinkSafe(sourcePath, targetPath, {
75
+ onConflict: 'backup', backupContext, name,
76
+ }));
77
+ }
78
+ else {
79
+ // Others → symlink to canonical
80
+ links.push(ensureSymlinkSafe(canonicalPath, targetPath, {
81
+ onConflict: 'backup', backupContext, name,
82
+ }));
83
+ }
84
+ }
85
+ return { source: sourcePath, links };
86
+ }
87
+ // ─── List active skills ───────────────────────────
88
+ export function listSkills(skillsDir) {
89
+ try {
90
+ return fs.readdirSync(skillsDir).filter((f) => {
91
+ if (f.startsWith('.') || f === 'registry.json')
92
+ return false;
93
+ try {
94
+ return fs.statSync(join(skillsDir, f)).isDirectory();
95
+ }
96
+ catch {
97
+ return false;
98
+ }
99
+ });
100
+ }
101
+ catch {
102
+ return [];
103
+ }
104
+ }
105
+ //# sourceMappingURL=skill-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-sync.js","sourceRoot":"","sources":["../../src/core/skill-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAsB,MAAM,cAAc,CAAC;AAW1F,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC1C,MAAM,UAAU,GAAqB,EAAE,CAAC;IAExC,4BAA4B;IAC5B,MAAM,MAAM,GAAuB;QAC/B,CAAC,uBAAuB,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACxD,CAAC,wBAAwB,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC,wBAAwB,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC,qBAAqB,EAAE,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;KACnD,CAAC;IAEF,8DAA8D;IAC9D,IAAI,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YACjE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YAChD,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,aAAa,EAAE,GAAG,CAAC,CAAC,CAAC;YACnD,CAAC;QACL,CAAC;IACL,CAAC;IAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IAExB,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;QACjC,IAAI,CAAC;YACD,MAAM,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACrB,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CACzC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,eAAe,CACrD,CAAC;gBACF,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAClC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAC/C,CAAC,MAAM,CAAC;gBACT,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;oBACjB,oBAAoB;oBACpB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,EAAE,CAAC;wBAChE,UAAU,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;oBACxD,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC;QAAC,MAAM,CAAC,CAAC,uBAAuB,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,UAAU,CAAC;AACtB,CAAC;AASD,MAAM,UAAU,UAAU,CAAC,GAAW,EAAE,UAAkB;IACtD,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAoB,EAAE,CAAC;IAElC,kCAAkC;IAClC,MAAM,OAAO,GAAuB;QAChC,CAAC,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/C,CAAC,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;KACpD,CAAC;IAEF,2EAA2E;IAC3E,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEpD,KAAK,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,OAAO,EAAE,CAAC;QACvC,IAAI,UAAU,KAAK,UAAU,EAAE,CAAC;YAC5B,6BAA6B;YAC7B,KAAK,CAAC,IAAI,CAAC;gBACP,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU;aACtF,CAAC,CAAC;YACH,SAAS;QACb,CAAC;QAED,IAAI,UAAU,KAAK,aAAa,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;YAC/D,4DAA4D;YAC5D,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,UAAU,EAAE,UAAU,EAAE;gBACjD,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI;aAC5C,CAAC,CAAC,CAAC;QACR,CAAC;aAAM,CAAC;YACJ,gCAAgC;YAChC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE;gBACpD,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI;aAC5C,CAAC,CAAC,CAAC;QACR,CAAC;IACL,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACzC,CAAC;AAED,qDAAqD;AAErD,MAAM,UAAU,UAAU,CAAC,SAAiB;IACxC,IAAI,CAAC;QACD,OAAO,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YAC1C,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,eAAe;gBAAE,OAAO,KAAK,CAAC;YAC7D,IAAI,CAAC;gBACD,OAAO,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACzD,CAAC;YAAC,MAAM,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACP,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,CAAC;IACd,CAAC;AACL,CAAC"}
@@ -0,0 +1,24 @@
1
+ interface BackupContext {
2
+ root: string;
3
+ count: number;
4
+ }
5
+ export declare function createBackupContext(): BackupContext;
6
+ export declare function resolveSymlinkTarget(linkPath: string, rawTarget: string): string;
7
+ export interface SymlinkResult {
8
+ status: 'ok' | 'skip' | 'error';
9
+ action: string;
10
+ name: string;
11
+ linkPath: string;
12
+ target: string;
13
+ error?: string;
14
+ }
15
+ export declare function ensureSymlinkSafe(target: string, linkPath: string, opts?: {
16
+ onConflict?: string;
17
+ backupContext?: BackupContext;
18
+ name?: string;
19
+ }): SymlinkResult;
20
+ /**
21
+ * Recursively copy a directory (symlink-safe, error-resilient)
22
+ */
23
+ export declare function copyDirRecursive(src: string, dst: string): void;
24
+ export {};
@@ -0,0 +1,81 @@
1
+ /**
2
+ * core/symlink.ts — Safe symlink creation with conflict resolution
3
+ * Extracted from cli-jaw lib/mcp-sync.ts
4
+ */
5
+ import fs from 'node:fs';
6
+ import { join, dirname, resolve } from 'node:path';
7
+ import { AGENT_SYNC_HOME } from './config.js';
8
+ export function createBackupContext() {
9
+ const root = join(AGENT_SYNC_HOME, 'backups', new Date().toISOString().slice(0, 10));
10
+ return { root, count: 0 };
11
+ }
12
+ export function resolveSymlinkTarget(linkPath, rawTarget) {
13
+ if (rawTarget.startsWith('/'))
14
+ return rawTarget;
15
+ return resolve(dirname(linkPath), rawTarget);
16
+ }
17
+ export function ensureSymlinkSafe(target, linkPath, opts = {}) {
18
+ const onConflict = opts.onConflict ?? 'backup';
19
+ const name = opts.name ?? 'link';
20
+ const context = opts.backupContext ?? createBackupContext();
21
+ try {
22
+ fs.mkdirSync(dirname(linkPath), { recursive: true });
23
+ const stat = fs.lstatSync(linkPath, { throwIfNoEntry: false });
24
+ if (stat) {
25
+ if (stat.isSymbolicLink()) {
26
+ const rawTarget = fs.readlinkSync(linkPath);
27
+ const currentTarget = resolveSymlinkTarget(linkPath, rawTarget);
28
+ if (currentTarget === target) {
29
+ return { status: 'skip', action: 'already_correct', name, linkPath, target };
30
+ }
31
+ // Different target — update
32
+ fs.unlinkSync(linkPath);
33
+ fs.symlinkSync(target, linkPath);
34
+ return { status: 'ok', action: 'replace_symlink', name, linkPath, target };
35
+ }
36
+ // Real directory or file — conflict
37
+ if (onConflict === 'skip') {
38
+ return { status: 'skip', action: 'skip_conflict', name, linkPath, target };
39
+ }
40
+ // Backup and replace
41
+ movePathToBackup(linkPath, context);
42
+ fs.symlinkSync(target, linkPath);
43
+ return { status: 'ok', action: 'backup_and_link', name, linkPath, target };
44
+ }
45
+ // Nothing exists — create
46
+ fs.symlinkSync(target, linkPath);
47
+ return { status: 'ok', action: 'created', name, linkPath, target };
48
+ }
49
+ catch (e) {
50
+ return { status: 'error', action: 'error', name, linkPath, target, error: e.message };
51
+ }
52
+ }
53
+ function movePathToBackup(pathToMove, context) {
54
+ fs.mkdirSync(context.root, { recursive: true });
55
+ const base = pathToMove.replace(/\//g, '__').replace(/^__/, '');
56
+ const dest = join(context.root, `${base}_${context.count++}`);
57
+ fs.renameSync(pathToMove, dest);
58
+ }
59
+ /**
60
+ * Recursively copy a directory (symlink-safe, error-resilient)
61
+ */
62
+ export function copyDirRecursive(src, dst) {
63
+ fs.mkdirSync(dst, { recursive: true });
64
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
65
+ const srcPath = join(src, entry.name);
66
+ const dstPath = join(dst, entry.name);
67
+ try {
68
+ const realStat = fs.statSync(srcPath);
69
+ if (realStat.isDirectory()) {
70
+ copyDirRecursive(srcPath, dstPath);
71
+ }
72
+ else {
73
+ fs.copyFileSync(srcPath, dstPath);
74
+ }
75
+ }
76
+ catch {
77
+ // Skip broken symlinks or permission errors
78
+ }
79
+ }
80
+ }
81
+ //# sourceMappingURL=symlink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symlink.js","sourceRoot":"","sources":["../../src/core/symlink.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * utils/log.ts — Colored console output
3
+ */
4
+ export declare const log: {
5
+ info: (msg: string) => void;
6
+ ok: (msg: string) => void;
7
+ warn: (msg: string) => void;
8
+ err: (msg: string) => void;
9
+ step: (n: number, total: number, msg: string) => void;
10
+ header: (msg: string) => void;
11
+ dim: (msg: string) => void;
12
+ choice: (n: number, label: string, detail?: string) => void;
13
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * utils/log.ts — Colored console output
3
+ */
4
+ const RESET = '\x1b[0m';
5
+ const BOLD = '\x1b[1m';
6
+ const DIM = '\x1b[2m';
7
+ const CYAN = '\x1b[36m';
8
+ const GREEN = '\x1b[32m';
9
+ const YELLOW = '\x1b[33m';
10
+ const RED = '\x1b[31m';
11
+ const BLUE = '\x1b[34m';
12
+ const MAGENTA = '\x1b[35m';
13
+ export const log = {
14
+ info: (msg) => console.log(`${CYAN}ℹ${RESET} ${msg}`),
15
+ ok: (msg) => console.log(`${GREEN}✔${RESET} ${msg}`),
16
+ warn: (msg) => console.log(`${YELLOW}⚠${RESET} ${msg}`),
17
+ err: (msg) => console.error(`${RED}✖${RESET} ${msg}`),
18
+ step: (n, total, msg) => console.log(`${DIM}[${n}/${total}]${RESET} ${msg}`),
19
+ header: (msg) => console.log(`\n${BOLD}${BLUE}▸ ${msg}${RESET}`),
20
+ dim: (msg) => console.log(` ${DIM}${msg}${RESET}`),
21
+ choice: (n, label, detail) => console.log(` ${MAGENTA}${n})${RESET} ${label}${detail ? ` ${DIM}${detail}${RESET}` : ''}`),
22
+ };
23
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/utils/log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,KAAK,GAAG,SAAS,CAAC;AACxB,MAAM,IAAI,GAAG,SAAS,CAAC;AACvB,MAAM,GAAG,GAAG,SAAS,CAAC;AACtB,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,MAAM,KAAK,GAAG,UAAU,CAAC;AACzB,MAAM,MAAM,GAAG,UAAU,CAAC;AAC1B,MAAM,GAAG,GAAG,UAAU,CAAC;AACvB,MAAM,IAAI,GAAG,UAAU,CAAC;AACxB,MAAM,OAAO,GAAG,UAAU,CAAC;AAE3B,MAAM,CAAC,MAAM,GAAG,GAAG;IACf,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;IAC7D,EAAE,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;IAC5D,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;IAC/D,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;IAC7D,IAAI,EAAE,CAAC,CAAS,EAAE,KAAa,EAAE,GAAW,EAAE,EAAE,CAC5C,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG,EAAE,CAAC;IACvD,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,IAAI,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC;IACxE,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,GAAG,GAAG,KAAK,EAAE,CAAC;IAC3D,MAAM,EAAE,CAAC,CAAS,EAAE,KAAa,EAAE,MAAe,EAAE,EAAE,CAClD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,GAAG,CAAC,IAAI,KAAK,IAAI,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;CACnG,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function ask(question: string): Promise<string>;
2
+ export declare function choose(question: string, max: number): Promise<number>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * utils/prompt.ts — Interactive stdin prompting
3
+ */
4
+ import * as readline from 'node:readline';
5
+ export function ask(question) {
6
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
7
+ return new Promise((resolve) => {
8
+ rl.question(question, (answer) => {
9
+ rl.close();
10
+ resolve(answer.trim());
11
+ });
12
+ });
13
+ }
14
+ export async function choose(question, max) {
15
+ while (true) {
16
+ const raw = await ask(`${question} [1-${max}]: `);
17
+ const n = parseInt(raw, 10);
18
+ if (n >= 1 && n <= max)
19
+ return n;
20
+ console.log(` Please enter a number between 1 and ${max}.`);
21
+ }
22
+ }
23
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,MAAM,UAAU,GAAG,CAAC,QAAgB;IAChC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACtF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC3B,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAC7B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,QAAgB,EAAE,GAAW;IACtD,OAAO,IAAI,EAAE,CAAC;QACV,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,QAAQ,OAAO,GAAG,KAAK,CAAC,CAAC;QAClD,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG;YAAE,OAAO,CAAC,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,yCAAyC,GAAG,GAAG,CAAC,CAAC;IACjE,CAAC;AACL,CAAC"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@bitkyc08/agent-sync",
3
+ "version": "0.1.0",
4
+ "description": "Sync MCP, skills, and AGENTS.md across all AI coding agents (Claude, Codex, Copilot, Gemini, Antigravity, OpenCode)",
5
+ "type": "module",
6
+ "bin": {
7
+ "agent-sync": "./dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/lidge-jun/agent-sync.git"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc",
19
+ "dev": "tsx src/cli.ts",
20
+ "test": "vitest run",
21
+ "prepublishOnly": "npm run build"
22
+ },
23
+ "keywords": [
24
+ "ai",
25
+ "agent",
26
+ "mcp",
27
+ "sync",
28
+ "claude",
29
+ "copilot",
30
+ "codex",
31
+ "gemini"
32
+ ],
33
+ "license": "MIT",
34
+ "engines": {
35
+ "node": ">=18"
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "^5.7",
39
+ "tsx": "^4.21",
40
+ "vitest": "^3.0",
41
+ "@types/node": "^22"
42
+ }
43
+ }