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