gencode-ai 0.1.0 → 0.1.1

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 (149) hide show
  1. package/README.md +8 -90
  2. package/dist/agent/agent.d.ts +1 -1
  3. package/dist/agent/agent.d.ts.map +1 -1
  4. package/dist/agent/agent.js +8 -2
  5. package/dist/agent/agent.js.map +1 -1
  6. package/dist/agent/types.d.ts +9 -1
  7. package/dist/agent/types.d.ts.map +1 -1
  8. package/dist/cli/components/AllModelsSelector.d.ts +11 -0
  9. package/dist/cli/components/AllModelsSelector.d.ts.map +1 -0
  10. package/dist/cli/components/AllModelsSelector.js +153 -0
  11. package/dist/cli/components/AllModelsSelector.js.map +1 -0
  12. package/dist/cli/components/App.d.ts.map +1 -1
  13. package/dist/cli/components/App.js +59 -25
  14. package/dist/cli/components/App.js.map +1 -1
  15. package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
  16. package/dist/cli/components/CommandSuggestions.js +1 -0
  17. package/dist/cli/components/CommandSuggestions.js.map +1 -1
  18. package/dist/cli/components/Messages.d.ts +15 -1
  19. package/dist/cli/components/Messages.d.ts.map +1 -1
  20. package/dist/cli/components/Messages.js +41 -15
  21. package/dist/cli/components/Messages.js.map +1 -1
  22. package/dist/cli/components/ModelSelector.d.ts +7 -7
  23. package/dist/cli/components/ModelSelector.d.ts.map +1 -1
  24. package/dist/cli/components/ModelSelector.js +116 -33
  25. package/dist/cli/components/ModelSelector.js.map +1 -1
  26. package/dist/cli/components/ProviderManager.d.ts +8 -0
  27. package/dist/cli/components/ProviderManager.d.ts.map +1 -0
  28. package/dist/cli/components/ProviderManager.js +280 -0
  29. package/dist/cli/components/ProviderManager.js.map +1 -0
  30. package/dist/cli/components/markdown.d.ts +9 -0
  31. package/dist/cli/components/markdown.d.ts.map +1 -0
  32. package/dist/cli/components/markdown.js +129 -0
  33. package/dist/cli/components/markdown.js.map +1 -0
  34. package/dist/cli/components/theme.d.ts +5 -0
  35. package/dist/cli/components/theme.d.ts.map +1 -1
  36. package/dist/cli/components/theme.js +7 -0
  37. package/dist/cli/components/theme.js.map +1 -1
  38. package/dist/cli/index.js +19 -5
  39. package/dist/cli/index.js.map +1 -1
  40. package/dist/config/index.d.ts +3 -2
  41. package/dist/config/index.d.ts.map +1 -1
  42. package/dist/config/index.js +2 -1
  43. package/dist/config/index.js.map +1 -1
  44. package/dist/config/providers-config.d.ts +28 -0
  45. package/dist/config/providers-config.d.ts.map +1 -0
  46. package/dist/config/providers-config.js +79 -0
  47. package/dist/config/providers-config.js.map +1 -0
  48. package/dist/config/types.d.ts +31 -1
  49. package/dist/config/types.d.ts.map +1 -1
  50. package/dist/config/types.js +1 -0
  51. package/dist/config/types.js.map +1 -1
  52. package/dist/providers/gemini.d.ts.map +1 -1
  53. package/dist/providers/gemini.js +14 -3
  54. package/dist/providers/gemini.js.map +1 -1
  55. package/dist/providers/index.d.ts +5 -3
  56. package/dist/providers/index.d.ts.map +1 -1
  57. package/dist/providers/index.js +13 -1
  58. package/dist/providers/index.js.map +1 -1
  59. package/dist/providers/registry.d.ts +66 -0
  60. package/dist/providers/registry.d.ts.map +1 -0
  61. package/dist/providers/registry.js +158 -0
  62. package/dist/providers/registry.js.map +1 -0
  63. package/dist/providers/search/brave.d.ts +14 -0
  64. package/dist/providers/search/brave.d.ts.map +1 -0
  65. package/dist/providers/search/brave.js +87 -0
  66. package/dist/providers/search/brave.js.map +1 -0
  67. package/dist/providers/search/exa.d.ts +12 -0
  68. package/dist/providers/search/exa.d.ts.map +1 -0
  69. package/dist/providers/search/exa.js +158 -0
  70. package/dist/providers/search/exa.js.map +1 -0
  71. package/dist/providers/search/index.d.ts +31 -0
  72. package/dist/providers/search/index.d.ts.map +1 -0
  73. package/dist/providers/search/index.js +75 -0
  74. package/dist/providers/search/index.js.map +1 -0
  75. package/dist/providers/search/serper.d.ts +14 -0
  76. package/dist/providers/search/serper.d.ts.map +1 -0
  77. package/dist/providers/search/serper.js +87 -0
  78. package/dist/providers/search/serper.js.map +1 -0
  79. package/dist/providers/search/types.d.ts +21 -0
  80. package/dist/providers/search/types.d.ts.map +1 -0
  81. package/dist/providers/search/types.js +5 -0
  82. package/dist/providers/search/types.js.map +1 -0
  83. package/dist/providers/store.d.ts +104 -0
  84. package/dist/providers/store.d.ts.map +1 -0
  85. package/dist/providers/store.js +171 -0
  86. package/dist/providers/store.js.map +1 -0
  87. package/dist/providers/types.d.ts +7 -1
  88. package/dist/providers/types.d.ts.map +1 -1
  89. package/dist/providers/vertex-ai.d.ts +33 -0
  90. package/dist/providers/vertex-ai.d.ts.map +1 -0
  91. package/dist/providers/vertex-ai.js +407 -0
  92. package/dist/providers/vertex-ai.js.map +1 -0
  93. package/dist/tools/builtin/webfetch.d.ts +20 -0
  94. package/dist/tools/builtin/webfetch.d.ts.map +1 -0
  95. package/dist/tools/builtin/webfetch.js +231 -0
  96. package/dist/tools/builtin/webfetch.js.map +1 -0
  97. package/dist/tools/builtin/websearch.d.ts +17 -0
  98. package/dist/tools/builtin/websearch.d.ts.map +1 -0
  99. package/dist/tools/builtin/websearch.js +101 -0
  100. package/dist/tools/builtin/websearch.js.map +1 -0
  101. package/dist/tools/index.d.ts +11 -0
  102. package/dist/tools/index.d.ts.map +1 -1
  103. package/dist/tools/index.js +24 -2
  104. package/dist/tools/index.js.map +1 -1
  105. package/dist/tools/types.d.ts +19 -0
  106. package/dist/tools/types.d.ts.map +1 -1
  107. package/dist/tools/types.js +8 -0
  108. package/dist/tools/types.js.map +1 -1
  109. package/dist/tools/utils/ssrf.d.ts +18 -0
  110. package/dist/tools/utils/ssrf.d.ts.map +1 -0
  111. package/dist/tools/utils/ssrf.js +70 -0
  112. package/dist/tools/utils/ssrf.js.map +1 -0
  113. package/docs/README.md +5 -4
  114. package/docs/proposals/0001-web-fetch-tool.md +32 -2
  115. package/docs/proposals/0002-web-search-tool.md +59 -2
  116. package/docs/proposals/0041-configuration-system.md +556 -0
  117. package/docs/proposals/README.md +3 -2
  118. package/docs/providers.md +220 -0
  119. package/package.json +7 -2
  120. package/src/agent/agent.ts +9 -2
  121. package/src/agent/types.ts +9 -1
  122. package/src/cli/components/App.tsx +72 -23
  123. package/src/cli/components/CommandSuggestions.tsx +1 -0
  124. package/src/cli/components/Messages.tsx +117 -29
  125. package/src/cli/components/ModelSelector.tsx +169 -52
  126. package/src/cli/components/ProviderManager.tsx +534 -0
  127. package/src/cli/components/markdown.ts +157 -0
  128. package/src/cli/components/theme.ts +7 -0
  129. package/src/cli/index.tsx +22 -7
  130. package/src/config/index.ts +3 -2
  131. package/src/config/providers-config.ts +85 -0
  132. package/src/config/types.ts +35 -1
  133. package/src/providers/gemini.ts +20 -4
  134. package/src/providers/index.ts +18 -3
  135. package/src/providers/registry.ts +198 -0
  136. package/src/providers/search/brave.ts +132 -0
  137. package/src/providers/search/exa.ts +217 -0
  138. package/src/providers/search/index.ts +79 -0
  139. package/src/providers/search/serper.ts +133 -0
  140. package/src/providers/search/types.ts +24 -0
  141. package/src/providers/store.ts +216 -0
  142. package/src/providers/types.ts +9 -1
  143. package/src/providers/vertex-ai.ts +594 -0
  144. package/src/tools/builtin/webfetch.ts +264 -0
  145. package/src/tools/builtin/websearch.ts +117 -0
  146. package/src/tools/index.ts +24 -2
  147. package/src/tools/types.ts +20 -0
  148. package/src/tools/utils/ssrf.ts +79 -0
  149. package/CLAUDE.md +0 -70
@@ -0,0 +1,556 @@
1
+ # Proposal: Configuration System
2
+
3
+ - **Proposal ID**: 0041
4
+ - **Author**: gencode team
5
+ - **Status**: Draft
6
+ - **Created**: 2026-01-15
7
+ - **Updated**: 2026-01-15
8
+
9
+ ## Summary
10
+
11
+ Implement a comprehensive configuration system for gencode, supporting multi-level configuration loading (user and project level), environment variable handling, permission management, and configuration merging. This design draws from both Claude Code's `~/.claude/` directory structure and OpenCode's configuration patterns.
12
+
13
+ ## Motivation
14
+
15
+ A robust configuration system is essential for:
16
+
17
+ 1. **Personalization**: Users need to customize behavior, model selection, and permissions
18
+ 2. **Project-specific settings**: Different projects may require different configurations
19
+ 3. **Team collaboration**: Shared project settings can be version controlled
20
+ 4. **Security**: Sensitive local settings should be gitignored while shared settings remain portable
21
+ 5. **Provider flexibility**: gencode's multi-provider architecture needs clean configuration for API keys and provider selection
22
+
23
+ ## Claude Code Reference
24
+
25
+ ### Configuration File Hierarchy
26
+
27
+ Claude Code uses a layered configuration system with the following priority (high to low):
28
+
29
+ | Level | Location | Purpose | Git Tracked |
30
+ |-------|----------|---------|-------------|
31
+ | 1 | `~/.claude.json` | Legacy main config | No |
32
+ | 2 | `~/.claude/settings.json` | User global settings | No |
33
+ | 3 | `~/.claude/settings.local.json` | User local settings | No |
34
+ | 4 | `.claude/settings.json` | Project shared settings | Yes |
35
+ | 5 | `.claude/settings.local.json` | Project personal settings | No (gitignored) |
36
+ | 6 | `.mcp.json` | Project MCP servers | Yes |
37
+
38
+ ### Environment Variables
39
+
40
+ Claude Code supports extensive environment variables:
41
+
42
+ **Authentication & API:**
43
+ - `ANTHROPIC_API_KEY` - Primary API key
44
+ - `ANTHROPIC_AUTH_TOKEN` - Alternative token
45
+ - `ANTHROPIC_BASE_URL` - Custom API endpoint
46
+ - `ANTHROPIC_MODEL` - Default model selection
47
+ - `ANTHROPIC_SMALL_FAST_MODEL` - Fast model for quick operations
48
+
49
+ **Cloud Providers:**
50
+ - `CLAUDE_CODE_USE_BEDROCK` - Enable AWS Bedrock
51
+ - `CLAUDE_CODE_USE_VERTEX` - Enable Google Vertex AI
52
+ - `CLAUDE_CODE_SKIP_BEDROCK_AUTH` - Bypass AWS auth
53
+ - `CLAUDE_CODE_SKIP_VERTEX_AUTH` - Bypass Vertex auth
54
+
55
+ **Operational:**
56
+ - `CLAUDE_CODE_MAX_OUTPUT_TOKENS` - Token limit
57
+ - `CLAUDE_CODE_ACTION` - Permission mode (acceptEdits, plan, bypassPermissions)
58
+ - `FORCE_CODE_TERMINAL` - Force CLI mode
59
+
60
+ **Debugging:**
61
+ - `DEBUG` - Verbose logging
62
+ - `DISABLE_ERROR_REPORTING` - No error submission
63
+ - `DISABLE_TELEMETRY` - No usage tracking
64
+
65
+ ### settings.json Structure
66
+
67
+ ```json
68
+ {
69
+ "projects": {
70
+ "/path/to/project": {
71
+ "mcpServers": { },
72
+ "allowedTools": [ ]
73
+ }
74
+ },
75
+ "permissions": {
76
+ "allow": ["Bash(npm:*)", "Read(/path/**)"],
77
+ "deny": ["Read(./.env)"]
78
+ },
79
+ "model": "claude-opus-4-5-20251101",
80
+ "spinnerTipsEnabled": false,
81
+ "attribution": {
82
+ "commits": true,
83
+ "pullRequests": true
84
+ },
85
+ "mcpServers": { },
86
+ "enableAllProjectMcpServers": true
87
+ }
88
+ ```
89
+
90
+ ### Tool Permission Patterns
91
+
92
+ - `Bash(git log:*)` - Git commands
93
+ - `Bash(npm run:*)` - NPM scripts
94
+ - `Read(/path/**)` - File patterns with globs
95
+ - `WebFetch(domain:github.com)` - Domain restrictions
96
+ - Tool names: `Task`, `Glob`, `Grep`, `LS`, `Edit`, `MultiEdit`, `Write`, `WebSearch`
97
+
98
+ ## OpenCode Reference
99
+
100
+ OpenCode provides additional patterns worth adopting:
101
+
102
+ ### Configuration Loading Order (Low → High Priority)
103
+
104
+ 1. Remote config (`.well-known/opencode`)
105
+ 2. Global config (`~/.config/opencode/opencode.json`)
106
+ 3. `OPENCODE_CONFIG` env var file
107
+ 4. Project config (`opencode.json`)
108
+ 5. `OPENCODE_CONFIG_CONTENT` inline JSON
109
+
110
+ ### Key Features
111
+
112
+ - **JSON/JSONC support**: Comments and trailing commas allowed
113
+ - **Environment variable substitution**: `{env:VARIABLE_NAME}` syntax
114
+ - **File content inclusion**: `{file:path/to/file}` syntax
115
+ - **Deep merge**: Arrays concatenate rather than replace
116
+ - **Zod schema validation**: Runtime type checking
117
+
118
+ ## Detailed Design
119
+
120
+ ### Directory Structure
121
+
122
+ ```
123
+ ~/.gencode/ # User-level configuration
124
+ ├── settings.json # Main user config
125
+ ├── settings.local.json # User local overrides (gitignored pattern)
126
+ ├── GENCODE.md # User context (like CLAUDE.md)
127
+ ├── commands/ # Custom slash commands
128
+ ├── skills/ # Custom skills
129
+ ├── agents/ # Custom subagents
130
+ ├── plugins/ # Plugin management
131
+ │ ├── marketplaces.json
132
+ │ └── installed.json
133
+ ├── hooks/ # Event hooks
134
+ └── sessions/ # Session data
135
+
136
+ ./gencode.json # Project config (like opencode.json)
137
+ ./.gencode/ # Project directory
138
+ ├── settings.local.json # Project local overrides (gitignored)
139
+ ├── GENCODE.md # Project context
140
+ ├── rules/ # Path-scoped rules
141
+ └── skills/ # Project-specific skills
142
+ ```
143
+
144
+ ### Configuration Priority (High → Low)
145
+
146
+ 1. **Environment variables** (`GENCODE_*`, provider API keys)
147
+ 2. **CLI arguments** (`--model`, `--provider`)
148
+ 3. **Project local** (`./.gencode/settings.local.json`)
149
+ 4. **Project shared** (`./gencode.json`)
150
+ 5. **User local** (`~/.gencode/settings.local.json`)
151
+ 6. **User global** (`~/.gencode/settings.json`)
152
+ 7. **Defaults**
153
+
154
+ ### API Design
155
+
156
+ ```typescript
157
+ // src/config/types.ts
158
+ interface GencodeConfig {
159
+ // Provider configuration
160
+ provider?: 'anthropic' | 'openai' | 'gemini' | 'bedrock' | 'vertex';
161
+ model?: string;
162
+
163
+ // Permission system
164
+ permissions?: {
165
+ allow?: string[]; // e.g., ["Bash(npm:*)", "Read(**/src/**)"]
166
+ deny?: string[]; // e.g., ["Read(.env)", "Bash(rm -rf:*)"]
167
+ };
168
+
169
+ // Environment variables to inject
170
+ env?: Record<string, string>;
171
+
172
+ // Hook definitions
173
+ hooks?: {
174
+ preToolUse?: HookConfig[];
175
+ postToolUse?: HookConfig[];
176
+ notification?: HookConfig[];
177
+ };
178
+
179
+ // MCP server configuration
180
+ mcpServers?: Record<string, McpServerConfig>;
181
+
182
+ // Plugin enablement
183
+ enabledPlugins?: string[];
184
+
185
+ // UI preferences
186
+ theme?: 'dark' | 'light' | 'auto';
187
+ spinnerTipsEnabled?: boolean;
188
+
189
+ // Attribution settings
190
+ attribution?: {
191
+ commits?: boolean;
192
+ pullRequests?: boolean;
193
+ };
194
+ }
195
+
196
+ interface HookConfig {
197
+ tool?: string;
198
+ command: string;
199
+ timeout?: number;
200
+ }
201
+
202
+ interface McpServerConfig {
203
+ command: string;
204
+ args?: string[];
205
+ env?: Record<string, string>;
206
+ }
207
+
208
+ // src/config/loader.ts
209
+ interface ConfigLoader {
210
+ load(): Promise<GencodeConfig>;
211
+ getUserConfig(): Promise<GencodeConfig>;
212
+ getProjectConfig(): Promise<GencodeConfig>;
213
+ getEffectiveConfig(): Promise<GencodeConfig>;
214
+ watch(callback: (config: GencodeConfig) => void): void;
215
+ }
216
+
217
+ // src/config/env.ts
218
+ interface EnvHandler {
219
+ getProviderFromEnv(): string | undefined;
220
+ getModelFromEnv(): string | undefined;
221
+ getApiKey(provider: string): string | undefined;
222
+ substituteEnvVars(value: string): string;
223
+ }
224
+ ```
225
+
226
+ ### Environment Variables
227
+
228
+ **Provider Selection:**
229
+ - `GENCODE_PROVIDER` - Provider name (anthropic, openai, gemini, bedrock, vertex)
230
+ - `GENCODE_MODEL` - Model ID
231
+ - `GENCODE_CONFIG` - Custom config file path
232
+
233
+ **Provider API Keys (Auto-detect):**
234
+ - `ANTHROPIC_API_KEY`
235
+ - `OPENAI_API_KEY`
236
+ - `GOOGLE_API_KEY`
237
+ - `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` (for Bedrock)
238
+
239
+ **Operational:**
240
+ - `GENCODE_MAX_OUTPUT_TOKENS` - Token limit
241
+ - `GENCODE_DISABLE_TELEMETRY` - Disable tracking
242
+ - `GENCODE_DEBUG` - Debug mode
243
+ - `HTTP_PROXY` / `HTTPS_PROXY` - Network proxy
244
+
245
+ ### settings.json Schema
246
+
247
+ ```json
248
+ {
249
+ "$schema": "https://gencode.dev/settings.schema.json",
250
+ "provider": "anthropic",
251
+ "model": "claude-sonnet-4",
252
+ "permissions": {
253
+ "allow": ["Bash(npm:*)", "Read(**/src/**)"],
254
+ "deny": ["Read(.env)", "Bash(rm -rf:*)"]
255
+ },
256
+ "env": {
257
+ "CUSTOM_VAR": "value",
258
+ "API_URL": "{env:BASE_API_URL}/v1"
259
+ },
260
+ "hooks": {
261
+ "postToolUse": [
262
+ { "tool": "Write", "command": "make fmt" }
263
+ ]
264
+ },
265
+ "mcpServers": {
266
+ "memory": {
267
+ "command": "npx",
268
+ "args": ["@modelcontextprotocol/server-memory"]
269
+ }
270
+ },
271
+ "enabledPlugins": ["git@official", "jira@community"],
272
+ "theme": "dark",
273
+ "spinnerTipsEnabled": true,
274
+ "attribution": {
275
+ "commits": true,
276
+ "pullRequests": true
277
+ }
278
+ }
279
+ ```
280
+
281
+ ### Implementation Approach
282
+
283
+ #### Phase 1: Core Config Loading
284
+
285
+ ```typescript
286
+ // src/config/loader.ts
287
+ import { parse as parseJsonc } from 'jsonc-parser';
288
+ import { findUp } from 'find-up';
289
+ import { z } from 'zod';
290
+
291
+ const ConfigSchema = z.object({
292
+ provider: z.enum(['anthropic', 'openai', 'gemini', 'bedrock', 'vertex']).optional(),
293
+ model: z.string().optional(),
294
+ permissions: z.object({
295
+ allow: z.array(z.string()).optional(),
296
+ deny: z.array(z.string()).optional(),
297
+ }).optional(),
298
+ // ... rest of schema
299
+ });
300
+
301
+ export class ConfigLoader {
302
+ private userConfigDir = path.join(os.homedir(), '.gencode');
303
+
304
+ async load(): Promise<GencodeConfig> {
305
+ const configs = await Promise.all([
306
+ this.loadDefaults(),
307
+ this.loadUserGlobal(),
308
+ this.loadUserLocal(),
309
+ this.loadProjectShared(),
310
+ this.loadProjectLocal(),
311
+ ]);
312
+
313
+ return this.deepMerge(...configs);
314
+ }
315
+
316
+ private async loadFile(filePath: string): Promise<Partial<GencodeConfig>> {
317
+ try {
318
+ const content = await fs.readFile(filePath, 'utf-8');
319
+ const parsed = parseJsonc(content); // Supports comments
320
+ return ConfigSchema.partial().parse(parsed);
321
+ } catch {
322
+ return {};
323
+ }
324
+ }
325
+
326
+ private deepMerge(...configs: Partial<GencodeConfig>[]): GencodeConfig {
327
+ // Arrays concatenate, objects merge recursively
328
+ return configs.reduce((acc, config) => {
329
+ return mergeWith(acc, config, (objValue, srcValue) => {
330
+ if (Array.isArray(objValue) && Array.isArray(srcValue)) {
331
+ return [...objValue, ...srcValue]; // Concatenate arrays
332
+ }
333
+ });
334
+ }, {} as GencodeConfig);
335
+ }
336
+ }
337
+ ```
338
+
339
+ #### Phase 2: Environment Variable Handling
340
+
341
+ ```typescript
342
+ // src/config/env.ts
343
+ export class EnvHandler {
344
+ private readonly providerKeyMap: Record<string, string> = {
345
+ anthropic: 'ANTHROPIC_API_KEY',
346
+ openai: 'OPENAI_API_KEY',
347
+ gemini: 'GOOGLE_API_KEY',
348
+ };
349
+
350
+ getProviderFromEnv(): string | undefined {
351
+ return process.env.GENCODE_PROVIDER;
352
+ }
353
+
354
+ getApiKey(provider: string): string | undefined {
355
+ const envKey = this.providerKeyMap[provider];
356
+ return envKey ? process.env[envKey] : undefined;
357
+ }
358
+
359
+ // Substitute {env:VAR} patterns
360
+ substituteEnvVars(value: string): string {
361
+ return value.replace(/\{env:(\w+)\}/g, (_, varName) => {
362
+ return process.env[varName] || '';
363
+ });
364
+ }
365
+
366
+ autoDetectProvider(): string | undefined {
367
+ for (const [provider, key] of Object.entries(this.providerKeyMap)) {
368
+ if (process.env[key]) {
369
+ return provider;
370
+ }
371
+ }
372
+ return undefined;
373
+ }
374
+ }
375
+ ```
376
+
377
+ #### Phase 3: Permission Matching
378
+
379
+ ```typescript
380
+ // src/config/permissions.ts
381
+ import { minimatch } from 'minimatch';
382
+
383
+ export class PermissionMatcher {
384
+ constructor(private config: GencodeConfig) {}
385
+
386
+ isAllowed(tool: string, args: string): boolean {
387
+ const permission = `${tool}(${args})`;
388
+
389
+ // Check deny list first
390
+ for (const pattern of this.config.permissions?.deny || []) {
391
+ if (this.matchPermission(permission, pattern)) {
392
+ return false;
393
+ }
394
+ }
395
+
396
+ // Check allow list
397
+ for (const pattern of this.config.permissions?.allow || []) {
398
+ if (this.matchPermission(permission, pattern)) {
399
+ return true;
400
+ }
401
+ }
402
+
403
+ return false; // Default deny
404
+ }
405
+
406
+ private matchPermission(permission: string, pattern: string): boolean {
407
+ // Parse pattern: Tool(arg:pattern)
408
+ const match = pattern.match(/^(\w+)\((.+)\)$/);
409
+ if (!match) return false;
410
+
411
+ const [, toolPattern, argPattern] = match;
412
+ const [tool, arg] = permission.match(/^(\w+)\((.+)\)$/)?.slice(1) || [];
413
+
414
+ if (toolPattern !== tool && toolPattern !== '*') return false;
415
+ return minimatch(arg, argPattern);
416
+ }
417
+ }
418
+ ```
419
+
420
+ ### File Changes
421
+
422
+ | File | Action | Description |
423
+ |------|--------|-------------|
424
+ | `src/config/types.ts` | Create | Configuration type definitions |
425
+ | `src/config/loader.ts` | Create | Multi-level config loading |
426
+ | `src/config/env.ts` | Create | Environment variable handling |
427
+ | `src/config/permissions.ts` | Create | Permission pattern matching |
428
+ | `src/config/index.ts` | Create | Public API exports |
429
+ | `src/agent/agent.ts` | Modify | Integrate config system |
430
+ | `src/cli/index.ts` | Modify | Add --config CLI flag |
431
+ | `schemas/settings.schema.json` | Create | JSON Schema for validation |
432
+
433
+ ## User Experience
434
+
435
+ ### First-time Setup
436
+
437
+ ```bash
438
+ # gencode auto-detects provider from API keys
439
+ $ export OPENAI_API_KEY=sk-...
440
+ $ gencode
441
+ # Uses OpenAI automatically
442
+
443
+ # Or specify explicitly
444
+ $ export GENCODE_PROVIDER=anthropic
445
+ $ export ANTHROPIC_API_KEY=sk-ant-...
446
+ $ gencode
447
+ ```
448
+
449
+ ### Project Configuration
450
+
451
+ ```bash
452
+ # Initialize project config
453
+ $ gencode init
454
+ # Creates ./gencode.json with sensible defaults
455
+
456
+ # View effective configuration
457
+ $ gencode config
458
+ # Shows merged configuration from all sources
459
+
460
+ # Set project-specific model
461
+ $ gencode config set model claude-sonnet-4
462
+ # Updates ./gencode.json
463
+ ```
464
+
465
+ ### Permission Management
466
+
467
+ ```bash
468
+ # View current permissions
469
+ $ gencode /permissions
470
+
471
+ # Allow npm commands for this project
472
+ $ gencode config allow "Bash(npm:*)"
473
+
474
+ # Deny reading .env files
475
+ $ gencode config deny "Read(.env)"
476
+ ```
477
+
478
+ ## Alternatives Considered
479
+
480
+ ### Single Config File
481
+
482
+ A single `~/.gencoderc` file would be simpler but lacks:
483
+ - Project-specific overrides
484
+ - Team-shareable settings
485
+ - Local-only sensitive settings
486
+
487
+ ### YAML Configuration
488
+
489
+ YAML is more readable but:
490
+ - JSON has better tooling support
491
+ - JSONC provides comments without complexity
492
+ - Matches Claude Code and OpenCode patterns
493
+
494
+ ### No Environment Variable Substitution
495
+
496
+ Simpler implementation but:
497
+ - Forces duplication of values
498
+ - Makes CI/CD integration harder
499
+ - Loses flexibility for sensitive values
500
+
501
+ ## Security Considerations
502
+
503
+ 1. **API Key Handling**: Never log or expose API keys; load from environment only
504
+ 2. **Local Settings**: `settings.local.json` files should be gitignored
505
+ 3. **Permission Defaults**: Default to deny; require explicit allow
506
+ 4. **File Permissions**: Config files should be user-readable only (0600)
507
+ 5. **Command Injection**: Validate hook commands; sanitize environment variable substitution
508
+
509
+ ## Testing Strategy
510
+
511
+ 1. **Unit Tests**:
512
+ - Config loading from multiple sources
513
+ - Deep merge behavior (especially arrays)
514
+ - Environment variable substitution
515
+ - Permission pattern matching
516
+
517
+ 2. **Integration Tests**:
518
+ - Full config resolution with mock file system
519
+ - CLI flag override behavior
520
+ - Provider auto-detection
521
+
522
+ 3. **E2E Tests**:
523
+ - `gencode config` commands
524
+ - Permission enforcement during tool execution
525
+
526
+ ## Migration Path
527
+
528
+ 1. **From mycode**: Migrate `~/.mycode/` to `~/.gencode/`
529
+ 2. **Version Detection**: Check for legacy config locations and prompt migration
530
+ 3. **Backward Compatibility**: Support reading old config format for one major version
531
+
532
+ ## Dependencies
533
+
534
+ - [find-up](https://www.npmjs.com/package/find-up) - Directory traversal
535
+ - [jsonc-parser](https://www.npmjs.com/package/jsonc-parser) - JSON with comments
536
+ - [minimatch](https://www.npmjs.com/package/minimatch) - Glob pattern matching
537
+ - [zod](https://www.npmjs.com/package/zod) - Schema validation (already used)
538
+ - [lodash.mergewith](https://www.npmjs.com/package/lodash.mergewith) - Deep merge
539
+
540
+ ## Related Proposals
541
+
542
+ | Proposal | Relationship |
543
+ |----------|--------------|
544
+ | [0006 Memory System](./0006-memory-system.md) | GENCODE.md is stored in config directories |
545
+ | [0009 Hooks System](./0009-hooks-system.md) | Hook definitions stored in settings.json |
546
+ | [0022 Plugin System](./0022-plugin-system.md) | Plugin enablement configured in settings |
547
+ | [0023 Permission Enhancements](./0023-permission-enhancements.md) | Permission patterns defined in settings |
548
+
549
+ ## References
550
+
551
+ - [Claude Code Settings - Official Docs](https://code.claude.com/docs/en/settings)
552
+ - [Claude Code Configuration Guide | ClaudeLog](https://claudelog.com/configuration/)
553
+ - [Claude Code CLI Environment Variables](https://gist.github.com/unkn0wncode/f87295d055dd0f0e8082358a0b5cc467)
554
+ - [settings.json in Claude Code Guide](https://www.eesel.ai/blog/settings-json-claude-code)
555
+ - [OpenCode Config Docs](https://opencode.ai/docs/config/)
556
+ - [OpenCode Configuration System | DeepWiki](https://deepwiki.com/sst/opencode/3-configuration-system)
@@ -1,6 +1,6 @@
1
- # mycode Enhancement Proposals
1
+ # gencode Enhancement Proposals
2
2
 
3
- This directory contains enhancement proposals for the mycode project. Each proposal describes a feature inspired by Claude Code that we plan to implement.
3
+ This directory contains enhancement proposals for the gencode project. Each proposal describes a feature inspired by Claude Code that we plan to implement.
4
4
 
5
5
  ## Proposal Process
6
6
 
@@ -28,6 +28,7 @@ This directory contains enhancement proposals for the mycode project. Each propo
28
28
  | [0010](./0010-mcp-integration.md) | MCP Integration | Draft |
29
29
  | [0011](./0011-custom-commands.md) | Custom Commands | Draft |
30
30
  | [0012](./0012-ask-user-question.md) | AskUserQuestion Tool | Draft |
31
+ | [0041](./0041-configuration-system.md) | Configuration System | Draft |
31
32
 
32
33
  ### P2 Priority - Enhanced Features
33
34