xling 0.0.2 → 0.2.4

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 (92) hide show
  1. package/README.md +229 -1
  2. package/dist/base-BlaKDtDu.d.ts +43 -0
  3. package/dist/base-BlaKDtDu.d.ts.map +1 -0
  4. package/dist/base-Cm9xh6sW.js +69 -0
  5. package/dist/base-Cm9xh6sW.js.map +1 -0
  6. package/dist/claude-l3zomoHg.js +209 -0
  7. package/dist/claude-l3zomoHg.js.map +1 -0
  8. package/dist/claudeDefault-Fk1-kHLE.js +19 -0
  9. package/dist/claudeDefault-Fk1-kHLE.js.map +1 -0
  10. package/dist/codex-CR8xqNrZ.js +85 -0
  11. package/dist/codex-CR8xqNrZ.js.map +1 -0
  12. package/dist/commands/settings/get.d.ts +24 -0
  13. package/dist/commands/settings/get.d.ts.map +1 -0
  14. package/dist/commands/settings/get.js +118 -0
  15. package/dist/commands/settings/get.js.map +1 -0
  16. package/dist/commands/settings/inspect.d.ts +19 -0
  17. package/dist/commands/settings/inspect.d.ts.map +1 -0
  18. package/dist/commands/settings/inspect.js +88 -0
  19. package/dist/commands/settings/inspect.js.map +1 -0
  20. package/dist/commands/settings/list.d.ts +25 -0
  21. package/dist/commands/settings/list.d.ts.map +1 -0
  22. package/dist/commands/settings/list.js +147 -0
  23. package/dist/commands/settings/list.js.map +1 -0
  24. package/dist/commands/settings/set.d.ts +22 -0
  25. package/dist/commands/settings/set.d.ts.map +1 -0
  26. package/dist/commands/settings/set.js +83 -0
  27. package/dist/commands/settings/set.js.map +1 -0
  28. package/dist/commands/settings/switch.d.ts +27 -0
  29. package/dist/commands/settings/switch.d.ts.map +1 -0
  30. package/dist/commands/settings/switch.js +164 -0
  31. package/dist/commands/settings/switch.js.map +1 -0
  32. package/dist/dispatcher-JXm3OqRQ.js +76 -0
  33. package/dist/dispatcher-JXm3OqRQ.js.map +1 -0
  34. package/dist/domain/interfaces.d.ts +3 -0
  35. package/dist/domain/interfaces.js +1 -0
  36. package/dist/domain/types.d.ts +2 -0
  37. package/dist/domain/types.js +1 -0
  38. package/dist/domain/validators.d.ts +82 -0
  39. package/dist/domain/validators.d.ts.map +1 -0
  40. package/dist/domain/validators.js +58 -0
  41. package/dist/domain/validators.js.map +1 -0
  42. package/dist/editor-D4qoje1V.js +32 -0
  43. package/dist/editor-D4qoje1V.js.map +1 -0
  44. package/dist/errors-CAZ5k5YT.js +89 -0
  45. package/dist/errors-CAZ5k5YT.js.map +1 -0
  46. package/dist/format-Cqecj3RS.js +229 -0
  47. package/dist/format-Cqecj3RS.js.map +1 -0
  48. package/dist/fsStore-i-3731TM.js +122 -0
  49. package/dist/fsStore-i-3731TM.js.map +1 -0
  50. package/dist/gemini-aNNm-QGE.js +52 -0
  51. package/dist/gemini-aNNm-QGE.js.map +1 -0
  52. package/dist/interfaces-CriQW6hF.d.ts +41 -0
  53. package/dist/interfaces-CriQW6hF.d.ts.map +1 -0
  54. package/dist/run.d.ts +1 -0
  55. package/dist/run.js +15 -0
  56. package/dist/run.js.map +1 -0
  57. package/dist/services/settings/adapters/base.d.ts +4 -0
  58. package/dist/services/settings/adapters/base.js +5 -0
  59. package/dist/services/settings/adapters/claude.d.ts +43 -0
  60. package/dist/services/settings/adapters/claude.d.ts.map +1 -0
  61. package/dist/services/settings/adapters/claude.js +9 -0
  62. package/dist/services/settings/adapters/codex.d.ts +45 -0
  63. package/dist/services/settings/adapters/codex.d.ts.map +1 -0
  64. package/dist/services/settings/adapters/codex.js +6 -0
  65. package/dist/services/settings/adapters/gemini.d.ts +32 -0
  66. package/dist/services/settings/adapters/gemini.d.ts.map +1 -0
  67. package/dist/services/settings/adapters/gemini.js +6 -0
  68. package/dist/services/settings/dispatcher.d.ts +36 -0
  69. package/dist/services/settings/dispatcher.d.ts.map +1 -0
  70. package/dist/services/settings/dispatcher.js +12 -0
  71. package/dist/services/settings/fsStore.d.ts +46 -0
  72. package/dist/services/settings/fsStore.d.ts.map +1 -0
  73. package/dist/services/settings/fsStore.js +4 -0
  74. package/dist/services/settings/templates/claudeDefault.d.ts +20 -0
  75. package/dist/services/settings/templates/claudeDefault.d.ts.map +1 -0
  76. package/dist/services/settings/templates/claudeDefault.js +3 -0
  77. package/dist/types-BfNSo2rs.d.ts +71 -0
  78. package/dist/types-BfNSo2rs.d.ts.map +1 -0
  79. package/dist/utils/editor.d.ts +6 -0
  80. package/dist/utils/editor.d.ts.map +1 -0
  81. package/dist/utils/editor.js +4 -0
  82. package/dist/utils/errors.d.ts +61 -0
  83. package/dist/utils/errors.d.ts.map +1 -0
  84. package/dist/utils/errors.js +3 -0
  85. package/dist/utils/format.d.ts +20 -0
  86. package/dist/utils/format.d.ts.map +1 -0
  87. package/dist/utils/format.js +3 -0
  88. package/dist/utils/logger.d.ts +32 -0
  89. package/dist/utils/logger.d.ts.map +1 -0
  90. package/dist/utils/logger.js +46 -0
  91. package/dist/utils/logger.js.map +1 -0
  92. package/package.json +66 -6
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ # xling
2
+
3
+ Unified CLI for managing AI tool settings across Claude Code, Codex, and Gemini CLI.
4
+
1
5
  ## What's in a Name? The Story of `xling`
2
6
 
3
7
  The name `xling` was carefully chosen to represent the project's philosophy, blending modern tech symbolism with a rich, dual-meaning core.
@@ -16,4 +20,228 @@ At the heart of the name is `ling`, a concept with two harmonious faces rooted i
16
20
  1. **令 (lìng)**: This means "command" or "order." It represents the tool's heritage as a command-line interface—unwavering, precise, and powerful.
17
21
  2. **灵 (líng)**: This translates to "intelligence," "spirit," or "agility." It embodies the AI engine that gives `xling` its smarts, allowing it to understand natural language, anticipate intent, and perform complex tasks with a touch of magic.
18
22
 
19
- Together, `xling` is more than just a tool; it's an intelligent partner that amplifies your ability to command your digital world.
23
+ Together, `xling` is more than just a tool; it's an intelligent partner that amplifies your ability to command your digital world.
24
+
25
+ ## Features
26
+
27
+ - **Unified Interface**: Manage settings for multiple AI CLI tools with a single command
28
+ - **Multiple Scopes**: Support for user, project, local, and system-level configurations
29
+ - **Profile Switching**: Switch between different configuration profiles (Codex)
30
+ - **Dry Run Mode**: Preview changes before applying them
31
+ - **JSON Output**: Machine-readable output for scripting
32
+ - **Type Safe**: Built with TypeScript for reliability
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ # Install dependencies
38
+ bun install
39
+
40
+ # Build the project
41
+ bun run build
42
+
43
+ # Link globally (optional)
44
+ npm link
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ ### List Settings
50
+
51
+ ```bash
52
+ # List all settings for Claude Code (user scope)
53
+ xling settings:list --tool claude --scope user
54
+
55
+ # List Codex settings in table format
56
+ xling settings:list --tool codex --table
57
+ ```
58
+
59
+ > Claude-specific: `settings:list --tool claude` now enumerates every
60
+ > `settings*.json` file (for example `settings.hxi.json`) in the selected scope
61
+ > so you can quickly discover switchable variants.
62
+ >
63
+ > Codex-specific: `settings:list --tool codex` surfaces only the `model_providers`
64
+ > block from `~/.codex/config.toml`, helping you audit provider names, base URLs,
65
+ > and env key bindings at a glance.
66
+
67
+ `settings:list` 默认输出 YAML 风格的简洁概览;如需表格/JSON,请加 `--table` 或
68
+ `--json`。其余命令仍以 JSON 为默认输出,可通过 `--no-json` 获取文本格式。
69
+
70
+ ### Get Settings File
71
+
72
+ ```bash
73
+ # Show Claude user settings (plain text default)
74
+ xling settings:get --tool claude --scope user
75
+
76
+ # Inspect a Claude variant (settings.hxi.json)
77
+ xling settings:get hxi --tool claude --scope user
78
+
79
+ # Show Codex config (plain text)
80
+ xling settings:get --tool codex
81
+ ```
82
+
83
+ ### Edit Settings (Claude)
84
+
85
+ ```bash
86
+ # Create/edit settings.hxi.json in VS Code (default)
87
+ xling settings:set --tool claude --scope user --name hxi
88
+
89
+ # Open default settings in Cursor
90
+ xling settings:set --tool claude --scope project --name default --ide cursor --no-json
91
+ ```
92
+
93
+ `settings:set` 现专注于整文件编辑:传 `--name`(默认 `default`)即可创建/打开
94
+ `settings.<name>.json`,并使用 `--ide` 指定编辑器(默认 VS Code 的 `code`)。
95
+
96
+ > Note: 所有 `settings:*` 命令仅依赖 `--tool`、`--scope`、`--name` 等 flag;不再提供
97
+ > `developerShortcuts.runCommand` 这类键级参数。
98
+
99
+ ### Switch Profiles or Claude Variants
100
+
101
+ ```bash
102
+ # Switch to a different profile
103
+ xling settings:switch oss --tool codex
104
+
105
+ # Activate settings.hxi.json for Claude user scope
106
+ xling settings:switch hxi --tool claude --scope user
107
+
108
+ # Apply without prompt (Claude)
109
+ xling settings:switch hxi --tool claude --scope user --force
110
+
111
+ # Force and keep a .bak backup
112
+ xling settings:switch hxi --tool claude --scope user --force --backup
113
+ ```
114
+
115
+ Claude switches现在默认进行交互式 diff 预览:命令会先打印彩色统一 diff,
116
+ 然后提示 `overwrite / backup / cancel`。若要非交互执行,使用 `--force`,并可
117
+ 通过 `--backup` 强制保留 `.bak`。Codex 保持原行为,直接切换 profile。
118
+
119
+ ### Inspect Configuration
120
+
121
+ ```bash
122
+ # View configuration file information
123
+ xling settings:inspect --tool claude --scope user
124
+ ```
125
+
126
+ ## Supported Tools
127
+
128
+ ### Claude Code
129
+
130
+ - **Scopes**: user, project, local
131
+ - **Config Files**:
132
+ - User: `~/.claude/settings.json`
133
+ - Project: `.claude/settings.json`
134
+ - Local: `.claude/settings.local.json`
135
+
136
+ ### Codex
137
+
138
+ - **Scopes**: user
139
+ - **Config Files**:
140
+ - User: `~/.codex/config.toml`
141
+ - **Features**: Profile switching
142
+
143
+ ### Gemini CLI
144
+
145
+ - **Scopes**: user, project, system
146
+ - **Config Files**:
147
+ - User: `~/.gemini/settings.json`
148
+ - Project: `.gemini/settings.json`
149
+ - System: Platform-dependent
150
+
151
+ ## Architecture
152
+
153
+ The project follows SOLID principles:
154
+
155
+ - **Single Responsibility**: Each adapter handles one tool
156
+ - **Open/Closed**: Easy to add new tools without modifying existing code
157
+ - **Liskov Substitution**: All adapters implement the same interface
158
+ - **Interface Segregation**: Clean, focused interfaces
159
+ - **Dependency Inversion**: Commands depend on abstractions, not implementations
160
+
161
+ ### Directory Structure
162
+
163
+ ```
164
+ xling/
165
+ ├── bin/
166
+ │ └── run.js # CLI entry point
167
+ ├── src/
168
+ │ ├── commands/ # oclif commands
169
+ │ │ └── settings/
170
+ │ ├── domain/ # Types and interfaces
171
+ │ ├── services/ # Business logic
172
+ │ │ └── settings/
173
+ │ │ ├── adapters/ # Tool adapters
174
+ │ │ ├── fsStore.ts # File system operations
175
+ │ │ └── dispatcher.ts
176
+ │ └── utils/ # Utilities
177
+ └── test/ # Tests and fixtures
178
+ ```
179
+
180
+ ## Development
181
+
182
+ ```bash
183
+ # Install dependencies
184
+ bun install
185
+
186
+ # Build (using tsdown)
187
+ bun run build
188
+
189
+ # Watch mode (tsdown --watch)
190
+ bun run dev
191
+
192
+ # Code quality
193
+ bun run lint # Lint with oxlint
194
+ bun run lint:fix # Auto-fix lint issues
195
+ bun run format # Format with oxfmt
196
+ bun run format:check # Check formatting
197
+ bun run typecheck # Type check with tsc
198
+
199
+ # Run tests
200
+ bun test
201
+ bun test:watch
202
+ bun test:coverage
203
+ ```
204
+
205
+ ### Toolchain
206
+
207
+ **Build System**
208
+
209
+ This project uses [tsdown](https://tsdown.vercel.app/) for fast TypeScript compilation and bundling:
210
+
211
+ - **Fast builds**: Powered by rolldown (Rust-based bundler)
212
+ - **ESM output**: Generates `.js` files for modern Node.js
213
+ - **Type definitions**: Automatically generates `.d.ts` files
214
+ - **Source maps**: Includes source maps for debugging
215
+ - **Tree shaking**: Optimized bundle size
216
+
217
+ **Code Quality**
218
+
219
+ - **Linting**: [oxlint](https://oxc.rs/) - Rust-based linter, 50-100x faster than ESLint
220
+ - **Formatting**: [oxfmt](https://oxc.rs/) - Fast formatter compatible with Prettier config
221
+ - **Type Checking**: TypeScript compiler for strict type safety
222
+
223
+ ## Testing
224
+
225
+ ```bash
226
+ # Run all tests
227
+ bun test
228
+
229
+ # Run with coverage
230
+ bun test:coverage
231
+ ```
232
+
233
+ ## Contributing
234
+
235
+ 1. Fork the repository
236
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
237
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
238
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
239
+ 5. Open a Pull Request
240
+
241
+ ## License
242
+
243
+ Apache-2.0
244
+
245
+ ## Author
246
+
247
+ Kingsword <kingsword09@gmail.com>
@@ -0,0 +1,43 @@
1
+ import { d as ToolId, i as Scope, l as SettingsResult, n as InspectResult, s as SettingsListData, t as EditOptions, u as SwitchOptions } from "./types-BfNSo2rs.js";
2
+ import { t as SettingsAdapter } from "./interfaces-CriQW6hF.js";
3
+
4
+ //#region src/services/settings/adapters/base.d.ts
5
+
6
+ /**
7
+ * 抽象基类
8
+ */
9
+ declare abstract class BaseAdapter implements SettingsAdapter {
10
+ abstract readonly toolId: ToolId;
11
+ /**
12
+ * 子类必须实现的方法
13
+ */
14
+ abstract resolvePath(scope: Scope): string;
15
+ abstract validateScope(scope: Scope): boolean;
16
+ /**
17
+ * 列出所有配置
18
+ */
19
+ list(scope: Scope): Promise<SettingsListData>;
20
+ /**
21
+ * 默认 switchProfile 会抛出,子类可覆盖
22
+ */
23
+ switchProfile(_scope: Scope, _profile: string, _options?: SwitchOptions): Promise<SettingsResult>;
24
+ /**
25
+ * 检查配置文件
26
+ */
27
+ inspect(scope: Scope): Promise<InspectResult>;
28
+ /**
29
+ * 默认 edit 会抛出,子类可覆盖
30
+ */
31
+ edit(scope: Scope, _options: EditOptions): Promise<SettingsResult>;
32
+ /**
33
+ * 读取配置文件(子类可覆盖)
34
+ */
35
+ protected readConfig(path: string): Record<string, unknown>;
36
+ /**
37
+ * 写入配置文件(子类可覆盖)
38
+ */
39
+ protected writeConfig(path: string, data: Record<string, unknown>, backup?: boolean): void;
40
+ }
41
+ //#endregion
42
+ export { BaseAdapter as t };
43
+ //# sourceMappingURL=base-BlaKDtDu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-BlaKDtDu.d.ts","names":[],"sources":["../src/services/settings/adapters/base.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAiCoC,uBAZd,WAAA,YAAuB,eAYT,CAAA;EAAR,kBAAA,MAAA,EAXA,MAWA;EAmBhB;;;EAGP,SAAA,WAAA,CAAA,KAAA,EA5ByB,KA4BzB,CAAA,EAAA,MAAA;EAOkB,SAAA,aAAA,CAAA,KAAA,EAlCS,KAkCT,CAAA,EAAA,OAAA;EAAgB;;;EA8BF,IAAA,CAAA,KAAA,EA3DjB,KA2DiB,CAAA,EA3DT,OA2DS,CA3DD,gBA2DC,CAAA;EAAsB;;;EAgBjD,aAAA,CAAA,MAAA,EAxDE,KAwDF,EAAA,QAAA,EAAA,MAAA,EAAA,QAAA,CAAA,EAtDK,aAsDL,CAAA,EArDL,OAqDK,CArDG,cAqDH,CAAA;EAvFmC;;;iBAyCtB,QAAQ,QAAQ;;;;cA8BnB,iBAAiB,cAAc,QAAQ;;;;sCAOrB;;;;4CAS5B"}
@@ -0,0 +1,69 @@
1
+ import { a as InvalidScopeError } from "./errors-CAZ5k5YT.js";
2
+ import { a as readJSON, c as writeJSON, i as getFileInfo, r as fileExists } from "./fsStore-i-3731TM.js";
3
+
4
+ //#region src/services/settings/adapters/base.ts
5
+ /**
6
+ * 抽象基类
7
+ */
8
+ var BaseAdapter = class {
9
+ /**
10
+ * 列出所有配置
11
+ */
12
+ async list(scope) {
13
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
14
+ const path = this.resolvePath(scope);
15
+ return {
16
+ type: "entries",
17
+ entries: this.readConfig(path),
18
+ filePath: path
19
+ };
20
+ }
21
+ /**
22
+ * 默认 switchProfile 会抛出,子类可覆盖
23
+ */
24
+ async switchProfile(_scope, _profile, _options) {
25
+ throw new Error(`Tool ${this.toolId} does not support profile switching`);
26
+ }
27
+ /**
28
+ * 检查配置文件
29
+ */
30
+ async inspect(scope) {
31
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
32
+ const path = this.resolvePath(scope);
33
+ if (!fileExists(path)) return {
34
+ path,
35
+ exists: false
36
+ };
37
+ const fileInfo = getFileInfo(path);
38
+ const config = this.readConfig(path);
39
+ return {
40
+ path,
41
+ exists: true,
42
+ content: JSON.stringify(config, null, 2),
43
+ size: fileInfo?.size,
44
+ lastModified: fileInfo?.lastModified
45
+ };
46
+ }
47
+ /**
48
+ * 默认 edit 会抛出,子类可覆盖
49
+ */
50
+ async edit(scope, _options) {
51
+ throw new Error(`Tool ${this.toolId} does not support edit for ${scope}`);
52
+ }
53
+ /**
54
+ * 读取配置文件(子类可覆盖)
55
+ */
56
+ readConfig(path) {
57
+ return readJSON(path);
58
+ }
59
+ /**
60
+ * 写入配置文件(子类可覆盖)
61
+ */
62
+ writeConfig(path, data, backup = true) {
63
+ writeJSON(path, data, backup);
64
+ }
65
+ };
66
+
67
+ //#endregion
68
+ export { BaseAdapter as t };
69
+ //# sourceMappingURL=base-Cm9xh6sW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-Cm9xh6sW.js","names":["fsStore.fileExists","fsStore.getFileInfo","fsStore.readJSON"],"sources":["../src/services/settings/adapters/base.ts"],"sourcesContent":["/**\n * 适配器抽象基类\n * 实现通用逻辑,减少重复代码(DRY 原则)\n */\n\nimport type { SettingsAdapter } from \"@/domain/interfaces.ts\";\nimport type {\n ToolId,\n Scope,\n InspectResult,\n SettingsListData,\n SettingsResult,\n EditOptions,\n SwitchOptions,\n} from \"@/domain/types.ts\";\nimport { InvalidScopeError } from \"@/utils/errors.ts\";\nimport * as fsStore from \"@/services/settings/fsStore.ts\";\n\n/**\n * 抽象基类\n */\nexport abstract class BaseAdapter implements SettingsAdapter {\n abstract readonly toolId: ToolId;\n\n /**\n * 子类必须实现的方法\n */\n abstract resolvePath(scope: Scope): string;\n abstract validateScope(scope: Scope): boolean;\n\n /**\n * 列出所有配置\n */\n async list(scope: Scope): Promise<SettingsListData> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const path = this.resolvePath(scope);\n const config = this.readConfig(path);\n\n return {\n type: \"entries\",\n entries: config,\n filePath: path,\n };\n }\n\n /**\n * 默认 switchProfile 会抛出,子类可覆盖\n */\n async switchProfile(\n _scope: Scope,\n _profile: string,\n _options?: SwitchOptions,\n ): Promise<SettingsResult> {\n throw new Error(`Tool ${this.toolId} does not support profile switching`);\n }\n\n /**\n * 检查配置文件\n */\n async inspect(scope: Scope): Promise<InspectResult> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const path = this.resolvePath(scope);\n const exists = fsStore.fileExists(path);\n\n if (!exists) {\n return {\n path,\n exists: false,\n };\n }\n\n const fileInfo = fsStore.getFileInfo(path);\n const config = this.readConfig(path);\n\n return {\n path,\n exists: true,\n content: JSON.stringify(config, null, 2),\n size: fileInfo?.size,\n lastModified: fileInfo?.lastModified,\n };\n }\n\n /**\n * 默认 edit 会抛出,子类可覆盖\n */\n async edit(scope: Scope, _options: EditOptions): Promise<SettingsResult> {\n throw new Error(`Tool ${this.toolId} does not support edit for ${scope}`);\n }\n\n /**\n * 读取配置文件(子类可覆盖)\n */\n protected readConfig(path: string): Record<string, unknown> {\n return fsStore.readJSON(path);\n }\n\n /**\n * 写入配置文件(子类可覆盖)\n */\n protected writeConfig(\n path: string,\n data: Record<string, unknown>,\n backup = true,\n ): void {\n fsStore.writeJSON(path, data, backup);\n }\n}\n"],"mappings":";;;;;;;AAqBA,IAAsB,cAAtB,MAA6D;;;;CAY3D,MAAM,KAAK,OAAyC;AAClD,MAAI,CAAC,KAAK,cAAc,MAAM,CAC5B,OAAM,IAAI,kBAAkB,MAAM;EAGpC,MAAM,OAAO,KAAK,YAAY,MAAM;AAGpC,SAAO;GACL,MAAM;GACN,SAJa,KAAK,WAAW,KAAK;GAKlC,UAAU;GACX;;;;;CAMH,MAAM,cACJ,QACA,UACA,UACyB;AACzB,QAAM,IAAI,MAAM,QAAQ,KAAK,OAAO,qCAAqC;;;;;CAM3E,MAAM,QAAQ,OAAsC;AAClD,MAAI,CAAC,KAAK,cAAc,MAAM,CAC5B,OAAM,IAAI,kBAAkB,MAAM;EAGpC,MAAM,OAAO,KAAK,YAAY,MAAM;AAGpC,MAAI,CAFWA,WAAmB,KAAK,CAGrC,QAAO;GACL;GACA,QAAQ;GACT;EAGH,MAAM,WAAWC,YAAoB,KAAK;EAC1C,MAAM,SAAS,KAAK,WAAW,KAAK;AAEpC,SAAO;GACL;GACA,QAAQ;GACR,SAAS,KAAK,UAAU,QAAQ,MAAM,EAAE;GACxC,MAAM,UAAU;GAChB,cAAc,UAAU;GACzB;;;;;CAMH,MAAM,KAAK,OAAc,UAAgD;AACvE,QAAM,IAAI,MAAM,QAAQ,KAAK,OAAO,6BAA6B,QAAQ;;;;;CAM3E,AAAU,WAAW,MAAuC;AAC1D,SAAOC,SAAiB,KAAK;;;;;CAM/B,AAAU,YACR,MACA,MACA,SAAS,MACH;AACN,YAAkB,MAAM,MAAM,OAAO"}
@@ -0,0 +1,209 @@
1
+ import { a as InvalidScopeError, s as SettingsVariantNotFoundError } from "./errors-CAZ5k5YT.js";
2
+ import { n as resolveEditorCommand, t as openInEditor } from "./editor-D4qoje1V.js";
3
+ import { t as formatDiff } from "./format-Cqecj3RS.js";
4
+ import { c as writeJSON, i as getFileInfo, n as ensureDir, s as resolveHome } from "./fsStore-i-3731TM.js";
5
+ import { t as BaseAdapter } from "./base-Cm9xh6sW.js";
6
+ import { t as CLAUDE_SETTINGS_TEMPLATE } from "./claudeDefault-Fk1-kHLE.js";
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+
10
+ //#region src/services/settings/adapters/claude.ts
11
+ /**
12
+ * Claude Code 适配器
13
+ */
14
+ /**
15
+ * Claude Code 配置适配器
16
+ *
17
+ * 配置文件路径:
18
+ * - user: ~/.claude/settings.json
19
+ * - project: <cwd>/.claude/settings.json
20
+ * - local: <cwd>/.claude/settings.local.json
21
+ */
22
+ var ClaudeAdapter = class extends BaseAdapter {
23
+ toolId = "claude";
24
+ /**
25
+ * 列出所有 settings.*.json 文件
26
+ */
27
+ async list(scope) {
28
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
29
+ const activePath = resolveHome(this.resolvePath(scope));
30
+ const directory = path.dirname(activePath);
31
+ const activeFilename = path.basename(activePath);
32
+ const files = [this.buildEntry(activePath, scope, true)];
33
+ if (fs.existsSync(directory)) {
34
+ const entries = fs.readdirSync(directory, { withFileTypes: true });
35
+ for (const entry of entries) {
36
+ if (!entry.isFile()) continue;
37
+ if (entry.name === activeFilename) continue;
38
+ if (!this.isSettingsFile(entry.name)) continue;
39
+ const entryPath = path.join(directory, entry.name);
40
+ files.push(this.buildEntry(entryPath, scope, false));
41
+ }
42
+ }
43
+ return {
44
+ type: "files",
45
+ files: this.sortFiles(files)
46
+ };
47
+ }
48
+ /**
49
+ * 解析配置文件路径
50
+ */
51
+ resolvePath(scope) {
52
+ switch (scope) {
53
+ case "user": return "~/.claude/settings.json";
54
+ case "project": return ".claude/settings.json";
55
+ case "local": return ".claude/settings.local.json";
56
+ default: throw new Error(`Unsupported scope for Claude: ${scope}`);
57
+ }
58
+ }
59
+ /**
60
+ * 验证 scope 是否有效
61
+ */
62
+ validateScope(scope) {
63
+ return [
64
+ "user",
65
+ "project",
66
+ "local"
67
+ ].includes(scope);
68
+ }
69
+ /**
70
+ * 切换 settings.<variant>.json 到活动文件
71
+ */
72
+ async switchProfile(scope, profile, options) {
73
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
74
+ const variant = profile.trim();
75
+ if (!variant) throw new Error("Variant name cannot be empty");
76
+ const targetPath = resolveHome(this.resolvePath(scope));
77
+ const directory = path.dirname(targetPath);
78
+ const sourcePath = this.findVariantPath(directory, variant, targetPath);
79
+ if (!sourcePath) throw new SettingsVariantNotFoundError(variant);
80
+ const nextConfig = this.readConfig(sourcePath);
81
+ let currentConfig = {};
82
+ try {
83
+ currentConfig = this.readConfig(targetPath);
84
+ } catch {
85
+ currentConfig = {};
86
+ }
87
+ const diff = formatDiff(currentConfig, nextConfig);
88
+ if (options?.preview) return {
89
+ success: true,
90
+ preview: true,
91
+ filePath: targetPath,
92
+ diff: diff ?? void 0,
93
+ data: {
94
+ from: sourcePath,
95
+ to: targetPath,
96
+ hasChanges: Boolean(diff)
97
+ },
98
+ message: diff ? "Preview generated. Review diff before applying." : "Current settings already match the selected variant."
99
+ };
100
+ if (!diff) return {
101
+ success: true,
102
+ message: "Current settings already match the selected variant.",
103
+ filePath: targetPath
104
+ };
105
+ const shouldBackup = options?.backup ?? false;
106
+ this.writeConfig(targetPath, nextConfig, shouldBackup);
107
+ return {
108
+ success: true,
109
+ message: `Switched to ${path.basename(sourcePath)}`,
110
+ filePath: targetPath,
111
+ data: {
112
+ from: sourcePath,
113
+ to: targetPath
114
+ }
115
+ };
116
+ }
117
+ async edit(scope, options) {
118
+ if (!this.validateScope(scope)) throw new InvalidScopeError(scope);
119
+ const basePath = resolveHome(this.resolvePath(scope));
120
+ const directory = path.dirname(basePath);
121
+ const variantName = options.name?.trim();
122
+ const resolvedEditor = resolveEditorCommand(options.ide);
123
+ ensureDir(directory);
124
+ let targetPath = basePath;
125
+ let label = "default";
126
+ if (variantName && variantName !== "" && variantName !== "default") {
127
+ const existingPath = this.findVariantPath(directory, variantName, basePath);
128
+ if (existingPath) targetPath = existingPath;
129
+ else {
130
+ targetPath = path.join(directory, `settings.${variantName}.json`);
131
+ if (!fs.existsSync(targetPath)) {
132
+ const seed = this.buildSeedConfig(basePath);
133
+ writeJSON(targetPath, seed, false);
134
+ }
135
+ }
136
+ label = variantName;
137
+ } else if (!fs.existsSync(targetPath)) {
138
+ const seed = this.buildSeedConfig(basePath);
139
+ writeJSON(targetPath, seed, false);
140
+ }
141
+ await openInEditor(resolvedEditor, targetPath);
142
+ return {
143
+ success: true,
144
+ message: `Opened ${label} settings in ${resolvedEditor}`,
145
+ filePath: targetPath,
146
+ data: {
147
+ variant: label,
148
+ ide: resolvedEditor
149
+ }
150
+ };
151
+ }
152
+ buildEntry(filePath, scope, active) {
153
+ const info = getFileInfo(filePath);
154
+ return {
155
+ filename: path.basename(filePath),
156
+ variant: this.extractVariant(filePath),
157
+ path: filePath,
158
+ scope,
159
+ active,
160
+ exists: Boolean(info),
161
+ size: info?.size,
162
+ lastModified: info?.lastModified
163
+ };
164
+ }
165
+ extractVariant(filePath) {
166
+ const filename = path.basename(filePath);
167
+ const match = filename.match(/^settings(?:[._-](.+))?\.json$/);
168
+ if (!match) return filename.replace(/\.json$/, "");
169
+ return match[1] ?? "default";
170
+ }
171
+ buildSeedConfig(basePath) {
172
+ try {
173
+ if (fs.existsSync(basePath)) {
174
+ const content = fs.readFileSync(basePath, "utf-8");
175
+ return JSON.parse(content);
176
+ }
177
+ } catch {}
178
+ return { ...CLAUDE_SETTINGS_TEMPLATE };
179
+ }
180
+ isSettingsFile(filename) {
181
+ return /^settings[._-].+\.json$/.test(filename);
182
+ }
183
+ sortFiles(files) {
184
+ return files.sort((a, b) => {
185
+ if (a.active && !b.active) return -1;
186
+ if (!a.active && b.active) return 1;
187
+ return a.variant.localeCompare(b.variant);
188
+ });
189
+ }
190
+ findVariantPath(directory, profile, defaultPath) {
191
+ const candidates = [];
192
+ const pushCandidate = (value) => {
193
+ if (!candidates.includes(value)) candidates.push(value);
194
+ };
195
+ if (profile === "default") pushCandidate(defaultPath);
196
+ if (profile.endsWith(".json")) pushCandidate(path.isAbsolute(profile) ? profile : path.join(directory, profile));
197
+ else {
198
+ pushCandidate(path.join(directory, `settings.${profile}.json`));
199
+ pushCandidate(path.join(directory, `settings-${profile}.json`));
200
+ pushCandidate(path.join(directory, `settings_${profile}.json`));
201
+ }
202
+ for (const candidate of candidates) if (fs.existsSync(candidate)) return candidate;
203
+ return null;
204
+ }
205
+ };
206
+
207
+ //#endregion
208
+ export { ClaudeAdapter as t };
209
+ //# sourceMappingURL=claude-l3zomoHg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-l3zomoHg.js","names":["fsStore.resolveHome","files: SettingsFileEntry[]","currentConfig: Record<string, unknown>","fsStore.getFileInfo","candidates: string[]"],"sources":["../src/services/settings/adapters/claude.ts"],"sourcesContent":["/**\n * Claude Code 适配器\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport type {\n Scope,\n SettingsListData,\n SettingsFileEntry,\n SettingsResult,\n EditOptions,\n SwitchOptions,\n} from \"@/domain/types.ts\";\nimport { BaseAdapter } from \"./base.ts\";\nimport * as fsStore from \"@/services/settings/fsStore.ts\";\nimport {\n InvalidScopeError,\n SettingsVariantNotFoundError,\n} from \"@/utils/errors.ts\";\nimport { CLAUDE_SETTINGS_TEMPLATE } from \"@/services/settings/templates/claudeDefault.ts\";\nimport { openInEditor, resolveEditorCommand } from \"@/utils/editor.ts\";\nimport { formatDiff } from \"@/utils/format.ts\";\n\n/**\n * Claude Code 配置适配器\n *\n * 配置文件路径:\n * - user: ~/.claude/settings.json\n * - project: <cwd>/.claude/settings.json\n * - local: <cwd>/.claude/settings.local.json\n */\nexport class ClaudeAdapter extends BaseAdapter {\n readonly toolId = \"claude\" as const;\n\n /**\n * 列出所有 settings.*.json 文件\n */\n override async list(scope: Scope): Promise<SettingsListData> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const activePath = fsStore.resolveHome(this.resolvePath(scope));\n const directory = path.dirname(activePath);\n const activeFilename = path.basename(activePath);\n\n const files: SettingsFileEntry[] = [\n this.buildEntry(activePath, scope, true),\n ];\n\n if (fs.existsSync(directory)) {\n const entries = fs.readdirSync(directory, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile()) continue;\n if (entry.name === activeFilename) continue;\n if (!this.isSettingsFile(entry.name)) continue;\n\n const entryPath = path.join(directory, entry.name);\n files.push(this.buildEntry(entryPath, scope, false));\n }\n }\n\n return {\n type: \"files\",\n files: this.sortFiles(files),\n };\n }\n\n /**\n * 解析配置文件路径\n */\n resolvePath(scope: Scope): string {\n switch (scope) {\n case \"user\":\n return \"~/.claude/settings.json\";\n case \"project\":\n return \".claude/settings.json\";\n case \"local\":\n return \".claude/settings.local.json\";\n default:\n throw new Error(`Unsupported scope for Claude: ${scope}`);\n }\n }\n\n /**\n * 验证 scope 是否有效\n */\n validateScope(scope: Scope): boolean {\n return [\"user\", \"project\", \"local\"].includes(scope);\n }\n\n /**\n * 切换 settings.<variant>.json 到活动文件\n */\n override async switchProfile(\n scope: Scope,\n profile: string,\n options?: SwitchOptions,\n ): Promise<SettingsResult> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const variant = profile.trim();\n if (!variant) {\n throw new Error(\"Variant name cannot be empty\");\n }\n\n const targetPath = fsStore.resolveHome(this.resolvePath(scope));\n const directory = path.dirname(targetPath);\n const sourcePath = this.findVariantPath(directory, variant, targetPath);\n\n if (!sourcePath) {\n throw new SettingsVariantNotFoundError(variant);\n }\n\n const nextConfig = this.readConfig(sourcePath);\n\n let currentConfig: Record<string, unknown> = {};\n try {\n currentConfig = this.readConfig(targetPath);\n } catch {\n currentConfig = {};\n }\n\n const diff = formatDiff(currentConfig, nextConfig);\n\n if (options?.preview) {\n return {\n success: true,\n preview: true,\n filePath: targetPath,\n diff: diff ?? undefined,\n data: {\n from: sourcePath,\n to: targetPath,\n hasChanges: Boolean(diff),\n },\n message: diff\n ? \"Preview generated. Review diff before applying.\"\n : \"Current settings already match the selected variant.\",\n };\n }\n\n if (!diff) {\n return {\n success: true,\n message: \"Current settings already match the selected variant.\",\n filePath: targetPath,\n };\n }\n\n const shouldBackup = options?.backup ?? false;\n this.writeConfig(targetPath, nextConfig, shouldBackup);\n\n return {\n success: true,\n message: `Switched to ${path.basename(sourcePath)}`,\n filePath: targetPath,\n data: {\n from: sourcePath,\n to: targetPath,\n },\n };\n }\n\n override async edit(\n scope: Scope,\n options: EditOptions,\n ): Promise<SettingsResult> {\n if (!this.validateScope(scope)) {\n throw new InvalidScopeError(scope);\n }\n\n const basePath = fsStore.resolveHome(this.resolvePath(scope));\n const directory = path.dirname(basePath);\n const variantName = options.name?.trim();\n const resolvedEditor = resolveEditorCommand(options.ide);\n\n fsStore.ensureDir(directory);\n\n let targetPath = basePath;\n let label = \"default\";\n\n if (variantName && variantName !== \"\" && variantName !== \"default\") {\n const existingPath = this.findVariantPath(\n directory,\n variantName,\n basePath,\n );\n if (existingPath) {\n targetPath = existingPath;\n } else {\n targetPath = path.join(directory, `settings.${variantName}.json`);\n if (!fs.existsSync(targetPath)) {\n const seed = this.buildSeedConfig(basePath);\n fsStore.writeJSON(targetPath, seed, false);\n }\n }\n label = variantName;\n } else if (!fs.existsSync(targetPath)) {\n const seed = this.buildSeedConfig(basePath);\n fsStore.writeJSON(targetPath, seed, false);\n }\n\n await openInEditor(resolvedEditor, targetPath);\n\n return {\n success: true,\n message: `Opened ${label} settings in ${resolvedEditor}`,\n filePath: targetPath,\n data: {\n variant: label,\n ide: resolvedEditor,\n },\n };\n }\n\n private buildEntry(\n filePath: string,\n scope: Scope,\n active: boolean,\n ): SettingsFileEntry {\n const info = fsStore.getFileInfo(filePath);\n\n return {\n filename: path.basename(filePath),\n variant: this.extractVariant(filePath),\n path: filePath,\n scope,\n active,\n exists: Boolean(info),\n size: info?.size,\n lastModified: info?.lastModified,\n };\n }\n\n private extractVariant(filePath: string): string {\n const filename = path.basename(filePath);\n const match = filename.match(/^settings(?:[._-](.+))?\\.json$/);\n if (!match) {\n return filename.replace(/\\.json$/, \"\");\n }\n return match[1] ?? \"default\";\n }\n\n private buildSeedConfig(basePath: string): Record<string, unknown> {\n try {\n if (fs.existsSync(basePath)) {\n const content = fs.readFileSync(basePath, \"utf-8\");\n return JSON.parse(content);\n }\n } catch {\n // ignore, fallback to template\n }\n return { ...CLAUDE_SETTINGS_TEMPLATE };\n }\n\n private isSettingsFile(filename: string): boolean {\n return /^settings[._-].+\\.json$/.test(filename);\n }\n\n private sortFiles(files: SettingsFileEntry[]): SettingsFileEntry[] {\n return files.sort((a, b) => {\n if (a.active && !b.active) return -1;\n if (!a.active && b.active) return 1;\n return a.variant.localeCompare(b.variant);\n });\n }\n\n private findVariantPath(\n directory: string,\n profile: string,\n defaultPath: string,\n ): string | null {\n const candidates: string[] = [];\n const pushCandidate = (value: string) => {\n if (!candidates.includes(value)) {\n candidates.push(value);\n }\n };\n\n if (profile === \"default\") {\n pushCandidate(defaultPath);\n }\n\n if (profile.endsWith(\".json\")) {\n pushCandidate(\n path.isAbsolute(profile) ? profile : path.join(directory, profile),\n );\n } else {\n pushCandidate(path.join(directory, `settings.${profile}.json`));\n pushCandidate(path.join(directory, `settings-${profile}.json`));\n pushCandidate(path.join(directory, `settings_${profile}.json`));\n }\n\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n return candidate;\n }\n }\n\n return null;\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ //#region src/services/settings/templates/claudeDefault.ts
2
+ const CLAUDE_SETTINGS_TEMPLATE = {
3
+ env: {
4
+ ANTHROPIC_AUTH_TOKEN: "",
5
+ ANTHROPIC_BASE_URL: "https://api.anthropic.com",
6
+ CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1",
7
+ ANTHROPIC_MODEL: "claude-sonnet-4-5-20250929",
8
+ ANTHROPIC_SMALL_FAST_MODEL: "claude-haiku-4-5-20251001"
9
+ },
10
+ permissions: {
11
+ allow: [],
12
+ deny: []
13
+ },
14
+ enabledPlugins: { "example-skills@anthropic-agent-skills": false }
15
+ };
16
+
17
+ //#endregion
18
+ export { CLAUDE_SETTINGS_TEMPLATE as t };
19
+ //# sourceMappingURL=claudeDefault-Fk1-kHLE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeDefault-Fk1-kHLE.js","names":[],"sources":["../src/services/settings/templates/claudeDefault.ts"],"sourcesContent":["export const CLAUDE_SETTINGS_TEMPLATE = {\n env: {\n ANTHROPIC_AUTH_TOKEN: \"\",\n ANTHROPIC_BASE_URL: \"https://api.anthropic.com\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n ANTHROPIC_MODEL: \"claude-sonnet-4-5-20250929\",\n ANTHROPIC_SMALL_FAST_MODEL: \"claude-haiku-4-5-20251001\",\n },\n permissions: {\n allow: [],\n deny: [],\n },\n enabledPlugins: {\n \"example-skills@anthropic-agent-skills\": false,\n },\n} satisfies Record<string, unknown>;\n"],"mappings":";AAAA,MAAa,2BAA2B;CACtC,KAAK;EACH,sBAAsB;EACtB,oBAAoB;EACpB,0CAA0C;EAC1C,iBAAiB;EACjB,4BAA4B;EAC7B;CACD,aAAa;EACX,OAAO,EAAE;EACT,MAAM,EAAE;EACT;CACD,gBAAgB,EACd,yCAAyC,OAC1C;CACF"}