@tengx5383/aitool-sync-cli 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.
Files changed (153) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/README.md +203 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +87 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/add.d.ts +2 -0
  8. package/dist/commands/add.d.ts.map +1 -0
  9. package/dist/commands/add.js +24 -0
  10. package/dist/commands/add.js.map +1 -0
  11. package/dist/commands/doctor.d.ts +2 -0
  12. package/dist/commands/doctor.d.ts.map +1 -0
  13. package/dist/commands/doctor.js +89 -0
  14. package/dist/commands/doctor.js.map +1 -0
  15. package/dist/commands/init.d.ts +7 -0
  16. package/dist/commands/init.d.ts.map +1 -0
  17. package/dist/commands/init.js +105 -0
  18. package/dist/commands/init.js.map +1 -0
  19. package/dist/commands/list.d.ts +2 -0
  20. package/dist/commands/list.d.ts.map +1 -0
  21. package/dist/commands/list.js +22 -0
  22. package/dist/commands/list.js.map +1 -0
  23. package/dist/commands/pull.d.ts +6 -0
  24. package/dist/commands/pull.d.ts.map +1 -0
  25. package/dist/commands/pull.js +52 -0
  26. package/dist/commands/pull.js.map +1 -0
  27. package/dist/commands/push.d.ts +6 -0
  28. package/dist/commands/push.d.ts.map +1 -0
  29. package/dist/commands/push.js +60 -0
  30. package/dist/commands/push.js.map +1 -0
  31. package/dist/commands/remove.d.ts +2 -0
  32. package/dist/commands/remove.d.ts.map +1 -0
  33. package/dist/commands/remove.js +20 -0
  34. package/dist/commands/remove.js.map +1 -0
  35. package/dist/commands/status.d.ts +2 -0
  36. package/dist/commands/status.d.ts.map +1 -0
  37. package/dist/commands/status.js +46 -0
  38. package/dist/commands/status.js.map +1 -0
  39. package/dist/config/config-file.d.ts +22 -0
  40. package/dist/config/config-file.d.ts.map +1 -0
  41. package/dist/config/config-file.js +86 -0
  42. package/dist/config/config-file.js.map +1 -0
  43. package/dist/config/schema.d.ts +101 -0
  44. package/dist/config/schema.d.ts.map +1 -0
  45. package/dist/config/schema.js +24 -0
  46. package/dist/config/schema.js.map +1 -0
  47. package/dist/core/backup.d.ts +8 -0
  48. package/dist/core/backup.d.ts.map +1 -0
  49. package/dist/core/backup.js +50 -0
  50. package/dist/core/backup.js.map +1 -0
  51. package/dist/core/checksum.d.ts +14 -0
  52. package/dist/core/checksum.d.ts.map +1 -0
  53. package/dist/core/checksum.js +23 -0
  54. package/dist/core/checksum.js.map +1 -0
  55. package/dist/core/exclusions.d.ts +8 -0
  56. package/dist/core/exclusions.d.ts.map +1 -0
  57. package/dist/core/exclusions.js +29 -0
  58. package/dist/core/exclusions.js.map +1 -0
  59. package/dist/core/file-collector.d.ts +16 -0
  60. package/dist/core/file-collector.d.ts.map +1 -0
  61. package/dist/core/file-collector.js +104 -0
  62. package/dist/core/file-collector.js.map +1 -0
  63. package/dist/core/manifest.d.ts +18 -0
  64. package/dist/core/manifest.d.ts.map +1 -0
  65. package/dist/core/manifest.js +42 -0
  66. package/dist/core/manifest.js.map +1 -0
  67. package/dist/core/path-expander.d.ts +6 -0
  68. package/dist/core/path-expander.d.ts.map +1 -0
  69. package/dist/core/path-expander.js +25 -0
  70. package/dist/core/path-expander.js.map +1 -0
  71. package/dist/core/sync-engine.d.ts +24 -0
  72. package/dist/core/sync-engine.d.ts.map +1 -0
  73. package/dist/core/sync-engine.js +206 -0
  74. package/dist/core/sync-engine.js.map +1 -0
  75. package/dist/core/sync-package.d.ts +12 -0
  76. package/dist/core/sync-package.d.ts.map +1 -0
  77. package/dist/core/sync-package.js +95 -0
  78. package/dist/core/sync-package.js.map +1 -0
  79. package/dist/crypto/encryptor.d.ts +15 -0
  80. package/dist/crypto/encryptor.d.ts.map +1 -0
  81. package/dist/crypto/encryptor.js +77 -0
  82. package/dist/crypto/encryptor.js.map +1 -0
  83. package/dist/crypto/key-resolver.d.ts +28 -0
  84. package/dist/crypto/key-resolver.d.ts.map +1 -0
  85. package/dist/crypto/key-resolver.js +62 -0
  86. package/dist/crypto/key-resolver.js.map +1 -0
  87. package/dist/gist/client.d.ts +18 -0
  88. package/dist/gist/client.d.ts.map +1 -0
  89. package/dist/gist/client.js +58 -0
  90. package/dist/gist/client.js.map +1 -0
  91. package/dist/gist/mock-client.d.ts +19 -0
  92. package/dist/gist/mock-client.d.ts.map +1 -0
  93. package/dist/gist/mock-client.js +61 -0
  94. package/dist/gist/mock-client.js.map +1 -0
  95. package/dist/index.d.ts +3 -0
  96. package/dist/index.d.ts.map +1 -0
  97. package/dist/index.js +3 -0
  98. package/dist/index.js.map +1 -0
  99. package/dist/presets/claude-code.d.ts +3 -0
  100. package/dist/presets/claude-code.d.ts.map +1 -0
  101. package/dist/presets/claude-code.js +27 -0
  102. package/dist/presets/claude-code.js.map +1 -0
  103. package/dist/presets/hermes.d.ts +3 -0
  104. package/dist/presets/hermes.d.ts.map +1 -0
  105. package/dist/presets/hermes.js +27 -0
  106. package/dist/presets/hermes.js.map +1 -0
  107. package/dist/presets/index.d.ts +15 -0
  108. package/dist/presets/index.d.ts.map +1 -0
  109. package/dist/presets/index.js +42 -0
  110. package/dist/presets/index.js.map +1 -0
  111. package/dist/presets/openclaw.d.ts +3 -0
  112. package/dist/presets/openclaw.d.ts.map +1 -0
  113. package/dist/presets/openclaw.js +27 -0
  114. package/dist/presets/openclaw.js.map +1 -0
  115. package/dist/types/config.d.ts +45 -0
  116. package/dist/types/config.d.ts.map +1 -0
  117. package/dist/types/config.js +2 -0
  118. package/dist/types/config.js.map +1 -0
  119. package/dist/types/gist.d.ts +25 -0
  120. package/dist/types/gist.d.ts.map +1 -0
  121. package/dist/types/gist.js +2 -0
  122. package/dist/types/gist.js.map +1 -0
  123. package/dist/types/index.d.ts +4 -0
  124. package/dist/types/index.d.ts.map +1 -0
  125. package/dist/types/index.js +2 -0
  126. package/dist/types/index.js.map +1 -0
  127. package/dist/types/sync.d.ts +78 -0
  128. package/dist/types/sync.d.ts.map +1 -0
  129. package/dist/types/sync.js +2 -0
  130. package/dist/types/sync.js.map +1 -0
  131. package/dist/utils/diff.d.ts +7 -0
  132. package/dist/utils/diff.d.ts.map +1 -0
  133. package/dist/utils/diff.js +99 -0
  134. package/dist/utils/diff.js.map +1 -0
  135. package/dist/utils/env.d.ts +13 -0
  136. package/dist/utils/env.d.ts.map +1 -0
  137. package/dist/utils/env.js +29 -0
  138. package/dist/utils/env.js.map +1 -0
  139. package/dist/utils/logger.d.ts +14 -0
  140. package/dist/utils/logger.d.ts.map +1 -0
  141. package/dist/utils/logger.js +39 -0
  142. package/dist/utils/logger.js.map +1 -0
  143. package/dist/utils/table.d.ts +5 -0
  144. package/dist/utils/table.d.ts.map +1 -0
  145. package/dist/utils/table.js +59 -0
  146. package/dist/utils/table.js.map +1 -0
  147. package/package.json +41 -0
  148. package/tests/integration/encryption-flow.test.ts +142 -0
  149. package/tests/integration/init-flow.test.ts +69 -0
  150. package/tests/integration/push-pull-flow.test.ts +183 -0
  151. package/tests/integration/status-flow.test.ts +149 -0
  152. package/tsconfig.json +19 -0
  153. package/vitest.config.ts +10 -0
@@ -0,0 +1,8 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(node -e \"const p = require\\('./package-lock.json'\\); p.name = '@tengx5383/aitool-sync-cli'; p.packages[''].name = '@tengx5383/aitool-sync-cli'; require\\('fs'\\).writeFileSync\\('package-lock.json', JSON.stringify\\(p, null, 2\\) + '\\\\n'\\)\")",
5
+ "Bash(npm run *)"
6
+ ]
7
+ }
8
+ }
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # aitool-sync
2
+
3
+ 跨设备同步 AI 智能体工具配置(Claude Code、Hermes、OpenClaw),通过 GitHub Gist API 实现。
4
+
5
+ ## 安装
6
+
7
+ ```bash
8
+ npm install -g aitool-sync
9
+ ```
10
+
11
+ 或者本地开发运行:
12
+
13
+ ```bash
14
+ git clone <repo>
15
+ cd AIToolSynchronizer
16
+ npm install
17
+ npm run build
18
+ ```
19
+
20
+ ## 快速开始
21
+
22
+ ```bash
23
+ # 1. 设置 GitHub Token
24
+ export GITHUB_TOKEN=ghp_xxxxxxxx
25
+
26
+ # 2. 初始化配置(自动检测已安装的工具)
27
+ aitool-sync init
28
+
29
+ # 3. 推送配置到 Gist
30
+ aitool-sync push
31
+
32
+ # 4. 在另一台设备上拉取配置
33
+ aitool-sync pull
34
+ ```
35
+
36
+ ## 命令说明
37
+
38
+ | 命令 | 说明 |
39
+ |------|------|
40
+ | `aitool-sync init` | 创建 `.aitoolsync.json` 配置文件,自动检测已安装的工具预设 |
41
+ | `aitool-sync status` | 查看本地与远程的差异 |
42
+ | `aitool-sync push` | 将本地配置上传到 Gist |
43
+ | `aitool-sync pull` | 从 Gist 下载配置到本地 |
44
+ | `aitool-sync push --force` | 强制推送(忽略冲突) |
45
+ | `aitool-sync pull --force` | 强制拉取(忽略冲突) |
46
+ | `aitool-sync add <名称> <路径>` | 添加一个同步路径 |
47
+ | `aitool-sync remove <名称>` | 移除一个同步路径 |
48
+ | `aitool-sync list` | 查看所有已跟踪的路径 |
49
+ | `aitool-sync doctor` | 诊断配置和连接状态 |
50
+
51
+ ## 配置文件
52
+
53
+ 所有配置保存在 `.aitoolsync.json` 中。示例:
54
+
55
+ ```json
56
+ {
57
+ "version": 1,
58
+ "gistId": "abc123def456...",
59
+ "syncPaths": [
60
+ { "name": "claude-code-settings", "path": "~/.claude/settings.json", "enabled": true },
61
+ { "name": "claude-code-mcp", "path": "~/.claude/mcp.json", "enabled": true }
62
+ ],
63
+ "exclusions": [
64
+ { "pattern": "**/node_modules/**" },
65
+ { "pattern": "**/.git/**" }
66
+ ],
67
+ "encryption": [
68
+ { "pattern": "**/token*" },
69
+ { "pattern": "**/credentials*" }
70
+ ],
71
+ "lastKnownManifest": null,
72
+ "lastPushAt": null,
73
+ "lastPullAt": null
74
+ }
75
+ ```
76
+
77
+ ### syncPaths
78
+
79
+ 要同步的文件或目录路径,支持 `~` 和 `$HOME` 展开。每个条目包含:
80
+ - `name`: 显示名称
81
+ - `path`: 文件或目录路径
82
+ - `enabled`: 是否启用同步
83
+
84
+ ### exclusions
85
+
86
+ 排除规则,使用 glob 模式匹配文件路径。以 `!` 开头的模式表示强制包含。
87
+
88
+ ### encryption
89
+
90
+ 加密规则,使用 glob 模式匹配需要加密的文件。启用加密需要设置 `AITOOLSYNC_PASSWORD` 环境变量。
91
+
92
+ ## 文件加密
93
+
94
+ 匹配加密模式的文件会在上传前使用 AES-256-GCM 加密:
95
+
96
+ ```bash
97
+ # 设置加密密码
98
+ export AITOOLSYNC_PASSWORD=my-secret-password
99
+ ```
100
+
101
+ 加密文件在 Gist 中存储为密文,只有在拉取时提供正确密码才能解密恢复。
102
+
103
+ ## 支持的 AI 工具预设
104
+
105
+ | 工具 | 预设 ID | 同步内容 |
106
+ |------|---------|----------|
107
+ | Claude Code | `claude-code` | `~/.claude/settings.json`, `mcp.json`, `claude.json` |
108
+ | Hermes | `hermes` | `~/.hermes/config.yaml`, `tools/`, `prompts/` |
109
+ | OpenClaw | `openclaw` | `~/.openclaw/config.json`, `tools/`, `profiles/` |
110
+
111
+ 初始化时会自动检测已安装的工具并应用对应预设。
112
+
113
+ ## 环境变量
114
+
115
+ | 变量 | 说明 |
116
+ |------|------|
117
+ | `GITHUB_TOKEN` | GitHub 个人访问令牌(push/pull 必需) |
118
+ | `AITOOLSYNC_PASSWORD` | 加密密码(可选,设置后启用文件加密) |
119
+
120
+ ## 工作流程
121
+
122
+ ```
123
+ 本地文件系统 GitHub Gist
124
+ ──────────── ───────────
125
+ ~/.claude/ push ──→ aitool-sync-package.json
126
+ ~/.hermes/ ←── pull (包含所有文件的
127
+ ~/.openclaw/ 包和清单)
128
+ 自定义路径
129
+ ```
130
+
131
+ ### 三方合并冲突检测
132
+
133
+ 系统保存上次成功同步时的远程清单(`lastKnownManifest`),通过比较本地、远程和上次已知状态来判断冲突:
134
+
135
+ - **仅本地变更** → 安全推送/拉取
136
+ - **仅远程变更** → 安全推送/拉取
137
+ - **双方均变更** → 冲突,需使用 `--force` 覆盖
138
+
139
+ ### 备份保护
140
+
141
+ 执行 `pull` 操作前会自动在临时目录创建带时间戳的备份,防止意外覆盖。
142
+
143
+ ## 开发
144
+
145
+ ```bash
146
+ # 安装依赖
147
+ npm install
148
+
149
+ # 运行测试
150
+ npm test
151
+
152
+ # 开发模式运行
153
+ npx tsx src/index.ts <command>
154
+
155
+ # 构建
156
+ npm run build
157
+ ```
158
+
159
+ ## 项目结构
160
+
161
+ ```
162
+ src/
163
+ ├── index.ts # 入口
164
+ ├── cli.ts # Commander CLI 设置
165
+ ├── commands/ # 命令实现
166
+ │ ├── init.ts # 初始化向导
167
+ │ ├── status.ts # 状态差异
168
+ │ ├── push.ts # 上传
169
+ │ ├── pull.ts # 下载
170
+ │ ├── add.ts # 添加路径
171
+ │ ├── remove.ts # 移除路径
172
+ │ ├── list.ts # 列出路径
173
+ │ └── doctor.ts # 诊断
174
+ ├── core/ # 核心同步逻辑
175
+ │ ├── sync-engine.ts # 同步编排器
176
+ │ ├── manifest.ts # 清单管理
177
+ │ ├── checksum.ts # SHA-256 哈希
178
+ │ ├── file-collector.ts # 文件收集
179
+ │ ├── backup.ts # 备份
180
+ │ ├── path-expander.ts # 路径展开
181
+ │ ├── exclusions.ts # 排除规则
182
+ │ └── sync-package.ts # 同步包构建/解析
183
+ ├── gist/ # Gist API 客户端
184
+ │ ├── client.ts # Octokit 封装
185
+ │ └── mock-client.ts # 测试用模拟客户端
186
+ ├── crypto/ # 加密模块
187
+ │ ├── encryptor.ts # AES-256-GCM
188
+ │ └── key-resolver.ts # 密码解析
189
+ ├── config/ # 配置文件
190
+ │ ├── config-file.ts # 读写 .aitoolsync.json
191
+ │ └── schema.ts # Zod 校验
192
+ ├── presets/ # 工具预设
193
+ │ ├── index.ts # 注册表和检测
194
+ │ ├── claude-code.ts # Claude Code
195
+ │ ├── hermes.ts # Hermes
196
+ │ └── openclaw.ts # OpenClaw
197
+ ├── types/ # 类型定义
198
+ └── utils/ # 工具函数
199
+ ```
200
+
201
+ ## License
202
+
203
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,87 @@
1
+ import { Command } from 'commander';
2
+ import { setLogLevel, LogLevel } from './utils/logger.js';
3
+ import { initCommand } from './commands/init.js';
4
+ import { statusCommand } from './commands/status.js';
5
+ import { pushCommand } from './commands/push.js';
6
+ import { pullCommand } from './commands/pull.js';
7
+ import { addCommand } from './commands/add.js';
8
+ import { removeCommand } from './commands/remove.js';
9
+ import { listCommand } from './commands/list.js';
10
+ import { doctorCommand } from './commands/doctor.js';
11
+ const program = new Command();
12
+ program
13
+ .name('aitool-sync')
14
+ .description('Sync AI agent tool configs across devices via GitHub Gist')
15
+ .version('0.1.0')
16
+ .option('--debug', 'Enable debug logging')
17
+ .hook('preAction', (thisCommand) => {
18
+ const opts = thisCommand.opts();
19
+ if (opts.debug) {
20
+ setLogLevel(LogLevel.DEBUG);
21
+ }
22
+ });
23
+ // init
24
+ program
25
+ .command('init')
26
+ .description('Initialize aitool-sync configuration')
27
+ .option('--gist-id <id>', 'Use existing Gist ID instead of creating one')
28
+ .option('--preset <preset>', 'Add a specific preset (claude-code, hermes, openclaw)')
29
+ .action(async (options) => {
30
+ await initCommand(options);
31
+ });
32
+ // status
33
+ program
34
+ .command('status')
35
+ .description('Show differences between local and remote')
36
+ .action(async () => {
37
+ await statusCommand();
38
+ });
39
+ // push
40
+ program
41
+ .command('push')
42
+ .description('Upload local configs to Gist')
43
+ .option('--force', 'Force push despite conflicts')
44
+ .action(async (options) => {
45
+ await pushCommand(options);
46
+ });
47
+ // pull
48
+ program
49
+ .command('pull')
50
+ .description('Download configs from Gist to local')
51
+ .option('--force', 'Force pull despite conflicts')
52
+ .action(async (options) => {
53
+ await pullCommand(options);
54
+ });
55
+ // add
56
+ program
57
+ .command('add')
58
+ .description('Add a path to the sync configuration')
59
+ .argument('<name>', 'Display name for this path')
60
+ .argument('<path>', 'File or directory path to sync')
61
+ .action(async (name, pathArg) => {
62
+ await addCommand(name, pathArg);
63
+ });
64
+ // remove
65
+ program
66
+ .command('remove')
67
+ .description('Remove a path from the sync configuration')
68
+ .argument('<name>', 'Name of the path to remove')
69
+ .action(async (name) => {
70
+ await removeCommand(name);
71
+ });
72
+ // list
73
+ program
74
+ .command('list')
75
+ .description('List all tracked sync paths')
76
+ .action(async () => {
77
+ await listCommand();
78
+ });
79
+ // doctor
80
+ program
81
+ .command('doctor')
82
+ .description('Diagnose configuration and connectivity issues')
83
+ .action(async () => {
84
+ await doctorCommand();
85
+ });
86
+ program.parse(process.argv);
87
+ //# 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,2 @@
1
+ export declare function addCommand(name: string, rawPath: string): Promise<void>;
2
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAGA,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB7E"}
@@ -0,0 +1,24 @@
1
+ import { readConfig, writeConfig } from '../config/config-file.js';
2
+ import { success, error, warn } from '../utils/logger.js';
3
+ export async function addCommand(name, rawPath) {
4
+ const config = readConfig();
5
+ if (!config) {
6
+ error('No configuration found. Run `aitool-sync init` first.');
7
+ return;
8
+ }
9
+ // Check for duplicate name
10
+ const existing = config.syncPaths.find((p) => p.name === name);
11
+ if (existing) {
12
+ warn(`Path with name "${name}" already exists: ${existing.path}`);
13
+ warn('Use `aitool-sync remove` first if you want to replace it.');
14
+ return;
15
+ }
16
+ config.syncPaths.push({
17
+ name,
18
+ path: rawPath,
19
+ enabled: true,
20
+ });
21
+ writeConfig(config);
22
+ success(`Added "${name}" -> ${rawPath}`);
23
+ }
24
+ //# sourceMappingURL=add.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,OAAe;IAC5D,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IAC/D,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC,mBAAmB,IAAI,qBAAqB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,2DAA2D,CAAC,CAAC;QAClE,OAAO;IACT,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QACpB,IAAI;QACJ,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,CAAC,UAAU,IAAI,QAAQ,OAAO,EAAE,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function doctorCommand(): Promise<void>;
2
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAQA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAmFnD"}
@@ -0,0 +1,89 @@
1
+ import fs from 'node:fs';
2
+ import { readConfig } from '../config/config-file.js';
3
+ import { resolveGithubToken, getEncryptionPassword } from '../utils/env.js';
4
+ import { detectInstalledPresets, getAllPresets } from '../presets/index.js';
5
+ import { expandPath } from '../core/path-expander.js';
6
+ import { GistClient } from '../gist/client.js';
7
+ import { info, success, warn, error } from '../utils/logger.js';
8
+ export async function doctorCommand() {
9
+ console.log('🔍 aitool-sync Doctor');
10
+ console.log('====================\n');
11
+ // 1. Check config
12
+ const config = readConfig();
13
+ if (config) {
14
+ success('Config file: found (.aitoolsync.json)');
15
+ info(` Version: ${config.version}`);
16
+ info(` Gist ID: ${config.gistId || '(not set)'}`);
17
+ info(` Sync paths: ${config.syncPaths.length}`);
18
+ info(` Exclusions: ${config.exclusions.length}`);
19
+ info(` Encryption rules: ${config.encryption.length}`);
20
+ }
21
+ else {
22
+ error('Config file: not found');
23
+ warn(' Run `aitool-sync init` to create one.');
24
+ }
25
+ // 2. Check environment
26
+ console.log('');
27
+ const token = resolveGithubToken(config);
28
+ if (token) {
29
+ const source = config?.githubToken ? 'config' : 'environment';
30
+ success(`GitHub token: set (from ${source}, ${token.slice(0, 4)}...)`);
31
+ }
32
+ else {
33
+ warn('GitHub token: not set');
34
+ warn(' Run `aitool-sync init` to configure it, or set GITHUB_TOKEN environment variable.');
35
+ }
36
+ const password = getEncryptionPassword();
37
+ if (password) {
38
+ success('AITOOLSYNC_PASSWORD: set');
39
+ }
40
+ else {
41
+ info('AITOOLSYNC_PASSWORD: not set (encryption disabled)');
42
+ }
43
+ // 3. Check connectivity
44
+ if (token) {
45
+ console.log('');
46
+ info('Checking GitHub API connectivity...');
47
+ try {
48
+ const client = new GistClient(token);
49
+ // A simple API call to verify the token works
50
+ const gist = await client.createGist('aitool-sync-doctor-check', {
51
+ 'doctor-check.txt': { content: 'connectivity test' },
52
+ });
53
+ await client.deleteGist(gist.gistId);
54
+ success('GitHub API: connected');
55
+ }
56
+ catch (e) {
57
+ error(`GitHub API: unreachable (${e.message})`);
58
+ }
59
+ }
60
+ // 4. Check paths
61
+ if (config && config.syncPaths.length > 0) {
62
+ console.log('');
63
+ info('Checking sync paths...');
64
+ for (const p of config.syncPaths) {
65
+ const expanded = expandPath(p.path);
66
+ const exists = fs.existsSync(expanded);
67
+ const icon = exists ? '✓' : '✗';
68
+ const color = exists ? success : warn;
69
+ color(` ${icon} ${p.name}: ${p.path}`);
70
+ if (!exists) {
71
+ warn(` Expanded path not found: ${expanded}`);
72
+ }
73
+ }
74
+ }
75
+ // 5. Check presets
76
+ console.log('');
77
+ info('Available presets:');
78
+ const allPresets = getAllPresets();
79
+ const installed = detectInstalledPresets();
80
+ for (const preset of allPresets) {
81
+ const isInstalled = installed.some((p) => p.id === preset.id);
82
+ const icon = isInstalled ? '✓' : ' ';
83
+ const label = isInstalled ? success : info;
84
+ label(` ${icon} ${preset.id}: ${preset.description}`);
85
+ }
86
+ console.log('');
87
+ info('Doctor check complete.');
88
+ }
89
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ interface InitOptions {
2
+ gistId?: string;
3
+ preset?: string;
4
+ }
5
+ export declare function initCommand(options: InitOptions): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AASA,UAAU,WAAW;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsFrE"}
@@ -0,0 +1,105 @@
1
+ import inquirer from 'inquirer';
2
+ import { readConfig, createDefaultConfig, writeConfig } from '../config/config-file.js';
3
+ import { detectInstalledPresets, getPreset, getAllPresets } from '../presets/index.js';
4
+ import { info, success, warn, error } from '../utils/logger.js';
5
+ import { getGithubToken } from '../utils/env.js';
6
+ export async function initCommand(options) {
7
+ // Check for existing config
8
+ const existing = readConfig();
9
+ if (existing) {
10
+ warn('Configuration already exists (.aitool-sync.json found).');
11
+ warn('To re-initialize, delete the config file and run init again.');
12
+ return;
13
+ }
14
+ const config = createDefaultConfig();
15
+ // Apply presets
16
+ if (options.preset) {
17
+ const presetId = options.preset;
18
+ const preset = getPreset(presetId);
19
+ if (!preset) {
20
+ error(`Unknown preset: ${presetId}`);
21
+ error(`Available presets: ${getAllPresets().map((p) => p.id).join(', ')}`);
22
+ return;
23
+ }
24
+ applyPreset(config, preset);
25
+ success(`Applied preset: ${preset.name}`);
26
+ }
27
+ else {
28
+ // Auto-detect installed presets
29
+ const installed = detectInstalledPresets();
30
+ if (installed.length > 0) {
31
+ info(`Detected ${installed.length} tool(s): ${installed.map((p) => p.name).join(', ')}`);
32
+ for (const preset of installed) {
33
+ applyPreset(config, preset);
34
+ }
35
+ success('Auto-detected and applied presets.');
36
+ }
37
+ else {
38
+ info('No supported tools detected. You can add paths manually with `aitool-sync add`.');
39
+ info(`Supported presets: ${getAllPresets().map((p) => p.id).join(', ')}`);
40
+ info('Use --preset <name> to apply a specific preset.');
41
+ }
42
+ }
43
+ // Gist setup
44
+ if (options.gistId) {
45
+ config.gistId = options.gistId;
46
+ info(`Using existing Gist: ${options.gistId}`);
47
+ }
48
+ // GitHub token setup
49
+ const existingToken = getGithubToken();
50
+ if (!existingToken) {
51
+ info('');
52
+ info('A GitHub personal access token is required for push/pull operations.');
53
+ info('Create one at: https://github.com/settings/tokens (need "gist" scope).');
54
+ const answer = await inquirer.prompt([
55
+ {
56
+ type: 'password',
57
+ name: 'githubToken',
58
+ message: 'Enter GitHub token (leave blank to skip, you can set GITHUB_TOKEN env var later):',
59
+ mask: '*',
60
+ },
61
+ ]);
62
+ if (answer.githubToken.trim()) {
63
+ config.githubToken = answer.githubToken.trim();
64
+ success('GitHub token saved to config.');
65
+ }
66
+ else {
67
+ info('Token skipped. Set GITHUB_TOKEN environment variable before running push/pull.');
68
+ }
69
+ }
70
+ else {
71
+ // Token already in env, store it in config too for portability
72
+ config.githubToken = existingToken;
73
+ info('GitHub token found from GITHUB_TOKEN environment variable and saved to config.');
74
+ }
75
+ // Write config
76
+ writeConfig(config);
77
+ success('Configuration created: .aitool-sync.json');
78
+ if (!config.gistId) {
79
+ info('');
80
+ info('Next steps:');
81
+ if (!config.githubToken) {
82
+ info(' 1. Set GITHUB_TOKEN in your environment or re-run init to configure it');
83
+ info(' 2. Run `aitool-sync push` to create a Gist and upload your configs');
84
+ }
85
+ else {
86
+ info(' 1. Run `aitool-sync push` to create a Gist and upload your configs');
87
+ }
88
+ info(' (A Gist will be created automatically on first push)');
89
+ }
90
+ }
91
+ function applyPreset(config, preset) {
92
+ for (const p of preset.defaultPaths) {
93
+ const exists = config.syncPaths.some((sp) => sp.name === p.name);
94
+ if (!exists) {
95
+ config.syncPaths.push({ ...p });
96
+ }
97
+ }
98
+ for (const e of preset.defaultExclusions) {
99
+ const exists = config.exclusions.some((ex) => ex.pattern === e.pattern);
100
+ if (!exists) {
101
+ config.exclusions.push({ ...e });
102
+ }
103
+ }
104
+ }
105
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function listCommand(): Promise<void>;
2
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAmBjD"}
@@ -0,0 +1,22 @@
1
+ import { readConfig } from '../config/config-file.js';
2
+ import { renderPathList } from '../utils/table.js';
3
+ import { error } from '../utils/logger.js';
4
+ export async function listCommand() {
5
+ const config = readConfig();
6
+ if (!config) {
7
+ error('No configuration found. Run `aitool-sync init` first.');
8
+ return;
9
+ }
10
+ if (config.syncPaths.length === 0) {
11
+ console.log('No paths configured. Use `aitool-sync add <name> <path>` to add one.');
12
+ return;
13
+ }
14
+ console.log(`Gist ID: ${config.gistId || '(not set)'}`);
15
+ console.log(`Last push: ${config.lastPushAt || 'never'}`);
16
+ console.log(`Last pull: ${config.lastPullAt || 'never'}`);
17
+ console.log(`Encryption rules: ${config.encryption.length > 0 ? config.encryption.map((r) => r.pattern).join(', ') : '(none)'}`);
18
+ console.log('');
19
+ console.log('Tracked paths:');
20
+ renderPathList(config.syncPaths);
21
+ }
22
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;QACpF,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,IAAI,OAAO,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,UAAU,IAAI,OAAO,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC9B,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,6 @@
1
+ interface PullOptions {
2
+ force?: boolean;
3
+ }
4
+ export declare function pullCommand(options: PullOptions): Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAQA,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAgDrE"}