mdcontext 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +28 -0
- package/.changeset/config.json +11 -0
- package/.claude/settings.local.json +25 -0
- package/.github/workflows/ci.yml +83 -0
- package/.github/workflows/claude-code-review.yml +44 -0
- package/.github/workflows/claude.yml +85 -0
- package/.github/workflows/release.yml +113 -0
- package/.tldrignore +112 -0
- package/BACKLOG.md +338 -0
- package/CONTRIBUTING.md +186 -0
- package/NOTES/NOTES +44 -0
- package/README.md +434 -11
- package/biome.json +36 -0
- package/cspell.config.yaml +14 -0
- package/dist/chunk-23UPXDNL.js +3044 -0
- package/dist/chunk-2W7MO2DL.js +1366 -0
- package/dist/chunk-3NUAZGMA.js +1689 -0
- package/dist/chunk-7TOWB2XB.js +366 -0
- package/dist/chunk-7XOTOADQ.js +3065 -0
- package/dist/chunk-AH2PDM2K.js +3042 -0
- package/dist/chunk-BNXWSZ63.js +3742 -0
- package/dist/chunk-BTL5DJVU.js +3222 -0
- package/dist/chunk-HDHYG7E4.js +104 -0
- package/dist/chunk-HLR4KZBP.js +3234 -0
- package/dist/chunk-IP3FRFEB.js +1045 -0
- package/dist/chunk-KHU56VDO.js +3042 -0
- package/dist/chunk-KRYIFLQR.js +88 -0
- package/dist/chunk-LBSDNLEM.js +287 -0
- package/dist/chunk-MNTQ7HCP.js +2643 -0
- package/dist/chunk-MUJELQQ6.js +1387 -0
- package/dist/chunk-MXJGMSLV.js +2199 -0
- package/dist/chunk-N6QJGC3Z.js +2636 -0
- package/dist/chunk-OBELGBPM.js +1713 -0
- package/dist/chunk-OT7R5XTA.js +3192 -0
- package/dist/chunk-P7X4RA2T.js +106 -0
- package/dist/chunk-PIDUQNC2.js +3185 -0
- package/dist/chunk-POGCDIH4.js +3187 -0
- package/dist/chunk-PSIEOQGZ.js +3043 -0
- package/dist/chunk-PVRT3IHA.js +3238 -0
- package/dist/chunk-QNN4TT23.js +1430 -0
- package/dist/chunk-RE3R45RJ.js +3042 -0
- package/dist/chunk-S7E6TFX6.js +803 -0
- package/dist/chunk-SG6GLU4U.js +1378 -0
- package/dist/chunk-SJCDV2ST.js +274 -0
- package/dist/chunk-SYE5XLF3.js +104 -0
- package/dist/chunk-T5VLYBZD.js +103 -0
- package/dist/chunk-TOQB7VWU.js +3238 -0
- package/dist/chunk-VFNMZ4ZQ.js +3228 -0
- package/dist/chunk-VVTGZNBT.js +1629 -0
- package/dist/chunk-W7Q4RFEV.js +104 -0
- package/dist/chunk-XTYYVRLO.js +3190 -0
- package/dist/chunk-Y6MDYVJD.js +3063 -0
- package/dist/cli/main.d.ts +1 -0
- package/dist/cli/main.js +5458 -0
- package/dist/index.d.ts +653 -0
- package/dist/index.js +79 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +472 -0
- package/dist/schema-BAWSG7KY.js +22 -0
- package/dist/schema-E3QUPL26.js +20 -0
- package/dist/schema-EHL7WUT6.js +20 -0
- package/docs/019-USAGE.md +625 -0
- package/docs/020-current-implementation.md +364 -0
- package/docs/021-DOGFOODING-FINDINGS.md +175 -0
- package/docs/BACKLOG.md +80 -0
- package/docs/CONFIG.md +1123 -0
- package/docs/DESIGN.md +439 -0
- package/docs/ERRORS.md +383 -0
- package/docs/PROJECT.md +88 -0
- package/docs/ROADMAP.md +407 -0
- package/docs/summarization.md +320 -0
- package/docs/test-links.md +9 -0
- package/justfile +40 -0
- package/package.json +74 -9
- package/pnpm-workspace.yaml +5 -0
- package/research/INDEX.md +315 -0
- package/research/code-review/README.md +90 -0
- package/research/code-review/cli-error-handling-review.md +979 -0
- package/research/code-review/code-review-validation-report.md +464 -0
- package/research/code-review/main-ts-review.md +1128 -0
- package/research/config-analysis/01-current-implementation.md +470 -0
- package/research/config-analysis/02-strategy-recommendation.md +428 -0
- package/research/config-analysis/03-task-candidates.md +715 -0
- package/research/config-analysis/033-research-configuration-management.md +828 -0
- package/research/config-analysis/034-research-effect-cli-config.md +1504 -0
- package/research/config-analysis/04-consolidated-task-candidates.md +277 -0
- package/research/config-docs/SUMMARY.md +357 -0
- package/research/config-docs/TEST-RESULTS.md +776 -0
- package/research/config-docs/TODO.md +542 -0
- package/research/config-docs/analysis.md +744 -0
- package/research/config-docs/fix-validation.md +502 -0
- package/research/config-docs/help-audit.md +264 -0
- package/research/config-docs/help-system-analysis.md +890 -0
- package/research/dogfood/consolidated-tool-evaluation.md +373 -0
- package/research/dogfood/strategy-a/a-synthesis.md +184 -0
- package/research/dogfood/strategy-a/a1-docs.md +226 -0
- package/research/dogfood/strategy-a/a2-amorphic.md +156 -0
- package/research/dogfood/strategy-a/a3-llm.md +164 -0
- package/research/dogfood/strategy-b/b-synthesis.md +228 -0
- package/research/dogfood/strategy-b/b1-architecture.md +207 -0
- package/research/dogfood/strategy-b/b2-gaps.md +258 -0
- package/research/dogfood/strategy-b/b3-workflows.md +250 -0
- package/research/dogfood/strategy-c/c-synthesis.md +451 -0
- package/research/dogfood/strategy-c/c1-explorer.md +192 -0
- package/research/dogfood/strategy-c/c2-diver-memory.md +145 -0
- package/research/dogfood/strategy-c/c3-diver-control.md +148 -0
- package/research/dogfood/strategy-c/c4-diver-failure.md +151 -0
- package/research/dogfood/strategy-c/c5-diver-execution.md +221 -0
- package/research/dogfood/strategy-c/c6-diver-org.md +221 -0
- package/research/effect-cli-error-handling.md +845 -0
- package/research/effect-errors-as-values.md +943 -0
- package/research/errors-task-analysis/00-consolidated-tasks.md +207 -0
- package/research/errors-task-analysis/cli-commands-analysis.md +909 -0
- package/research/errors-task-analysis/embeddings-analysis.md +709 -0
- package/research/errors-task-analysis/index-search-analysis.md +812 -0
- package/research/frontmatter/COMMENTS-ARE-SKIPPED.md +149 -0
- package/research/frontmatter/LLM-CODE-NAVIGATION.md +276 -0
- package/research/issue-review.md +603 -0
- package/research/llm-summarization/agent-cli-tools-2026.md +1082 -0
- package/research/llm-summarization/alternative-providers-2026.md +1428 -0
- package/research/llm-summarization/anthropic-2026.md +367 -0
- package/research/llm-summarization/claude-cli-integration.md +1706 -0
- package/research/llm-summarization/cli-integration-patterns.md +3155 -0
- package/research/llm-summarization/openai-2026.md +473 -0
- package/research/llm-summarization/openai-compatible-providers-2026.md +1022 -0
- package/research/llm-summarization/opencode-cli-integration.md +1552 -0
- package/research/llm-summarization/prompt-engineering-2026.md +1426 -0
- package/research/llm-summarization/prototype-results.md +56 -0
- package/research/llm-summarization/provider-switching-patterns-2026.md +2153 -0
- package/research/llm-summarization/typescript-llm-libraries-2026.md +2436 -0
- package/research/mdcontext-error-analysis.md +521 -0
- package/research/mdcontext-pudding/00-EXECUTIVE-SUMMARY.md +282 -0
- package/research/mdcontext-pudding/01-index-embed.md +956 -0
- package/research/mdcontext-pudding/02-search-COMMANDS.md +142 -0
- package/research/mdcontext-pudding/02-search-SUMMARY.md +146 -0
- package/research/mdcontext-pudding/02-search.md +970 -0
- package/research/mdcontext-pudding/03-context.md +779 -0
- package/research/mdcontext-pudding/04-navigation-and-analytics.md +803 -0
- package/research/mdcontext-pudding/04-tree.md +704 -0
- package/research/mdcontext-pudding/05-config.md +1038 -0
- package/research/mdcontext-pudding/06-links-summary.txt +87 -0
- package/research/mdcontext-pudding/06-links.md +679 -0
- package/research/mdcontext-pudding/07-stats.md +693 -0
- package/research/mdcontext-pudding/BUG-FIX-PLAN.md +388 -0
- package/research/mdcontext-pudding/P0-BUG-VALIDATION.md +167 -0
- package/research/mdcontext-pudding/README.md +168 -0
- package/research/mdcontext-pudding/TESTING-SUMMARY.md +128 -0
- package/research/npm_publish/011-npm-workflow-research-agent2.md +792 -0
- package/research/npm_publish/012-npm-workflow-research-agent1.md +530 -0
- package/research/npm_publish/013-npm-workflow-research-agent3.md +722 -0
- package/research/npm_publish/014-npm-workflow-synthesis.md +556 -0
- package/research/npm_publish/031-npm-workflow-task-analysis.md +134 -0
- package/research/research-quality-review.md +834 -0
- package/research/semantic-search/002-research-embedding-models.md +490 -0
- package/research/semantic-search/003-research-rag-alternatives.md +523 -0
- package/research/semantic-search/004-research-vector-search.md +841 -0
- package/research/semantic-search/032-research-semantic-search.md +427 -0
- package/research/semantic-search/embedding-text-analysis.md +156 -0
- package/research/semantic-search/multi-word-failure-reproduction.md +171 -0
- package/research/semantic-search/query-processing-analysis.md +207 -0
- package/research/semantic-search/root-cause-and-solution.md +114 -0
- package/research/semantic-search/threshold-validation-report.md +69 -0
- package/research/semantic-search/vector-search-analysis.md +63 -0
- package/research/task-management-2026/00-synthesis-recommendations.md +295 -0
- package/research/task-management-2026/01-ai-workflow-tools.md +416 -0
- package/research/task-management-2026/02-agent-framework-patterns.md +476 -0
- package/research/task-management-2026/03-lightweight-file-based.md +567 -0
- package/research/task-management-2026/04-established-tools-ai-features.md +541 -0
- package/research/task-management-2026/linear/01-core-features-workflow.md +771 -0
- package/research/task-management-2026/linear/02-api-integrations.md +930 -0
- package/research/task-management-2026/linear/03-ai-features.md +368 -0
- package/research/task-management-2026/linear/04-pricing-setup.md +205 -0
- package/research/task-management-2026/linear/05-usage-patterns-best-practices.md +605 -0
- package/research/test-path-issues.md +276 -0
- package/review/ALP-76/1-error-type-design.md +962 -0
- package/review/ALP-76/2-error-handling-patterns.md +906 -0
- package/review/ALP-76/3-error-presentation.md +624 -0
- package/review/ALP-76/4-test-coverage.md +625 -0
- package/review/ALP-76/5-migration-completeness.md +440 -0
- package/review/ALP-76/6-effect-best-practices.md +755 -0
- package/scripts/apply-branch-protection.sh +47 -0
- package/scripts/branch-protection-templates.json +79 -0
- package/scripts/prototype-summarization.ts +346 -0
- package/scripts/rebuild-hnswlib.js +58 -0
- package/scripts/setup-branch-protection.sh +64 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/active-provider.json +7 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.json +541 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/bm25.meta.json +5 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/config.json +8 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/documents.json +60 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/links.json +13 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/.mdcontext/indexes/sections.json +1197 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/configuration-management.md +99 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/distributed-systems.md +92 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/error-handling.md +78 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/failure-automation.md +55 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/job-context.md +69 -0
- package/src/__tests__/fixtures/semantic-search/multi-word-corpus/process-orchestration.md +99 -0
- package/src/cli/argv-preprocessor.test.ts +210 -0
- package/src/cli/argv-preprocessor.ts +202 -0
- package/src/cli/cli.test.ts +627 -0
- package/src/cli/commands/backlinks.ts +54 -0
- package/src/cli/commands/config-cmd.ts +642 -0
- package/src/cli/commands/context.ts +285 -0
- package/src/cli/commands/duplicates.ts +122 -0
- package/src/cli/commands/embeddings.ts +529 -0
- package/src/cli/commands/index-cmd.ts +480 -0
- package/src/cli/commands/index.ts +16 -0
- package/src/cli/commands/links.ts +52 -0
- package/src/cli/commands/search.ts +1281 -0
- package/src/cli/commands/stats.ts +149 -0
- package/src/cli/commands/tree.ts +128 -0
- package/src/cli/config-layer.ts +176 -0
- package/src/cli/error-handler.test.ts +235 -0
- package/src/cli/error-handler.ts +655 -0
- package/src/cli/flag-schemas.ts +341 -0
- package/src/cli/help.ts +588 -0
- package/src/cli/index.ts +9 -0
- package/src/cli/main.ts +435 -0
- package/src/cli/options.ts +41 -0
- package/src/cli/shared-error-handling.ts +199 -0
- package/src/cli/typo-suggester.test.ts +105 -0
- package/src/cli/typo-suggester.ts +130 -0
- package/src/cli/utils.ts +259 -0
- package/src/config/file-provider.test.ts +320 -0
- package/src/config/file-provider.ts +273 -0
- package/src/config/index.ts +72 -0
- package/src/config/integration.test.ts +667 -0
- package/src/config/precedence.test.ts +277 -0
- package/src/config/precedence.ts +451 -0
- package/src/config/schema.test.ts +414 -0
- package/src/config/schema.ts +603 -0
- package/src/config/service.test.ts +320 -0
- package/src/config/service.ts +243 -0
- package/src/config/testing.test.ts +264 -0
- package/src/config/testing.ts +110 -0
- package/src/core/index.ts +1 -0
- package/src/core/types.ts +113 -0
- package/src/duplicates/detector.test.ts +183 -0
- package/src/duplicates/detector.ts +414 -0
- package/src/duplicates/index.ts +18 -0
- package/src/embeddings/embedding-namespace.test.ts +300 -0
- package/src/embeddings/embedding-namespace.ts +947 -0
- package/src/embeddings/heading-boost.test.ts +222 -0
- package/src/embeddings/hnsw-build-options.test.ts +198 -0
- package/src/embeddings/hyde.test.ts +272 -0
- package/src/embeddings/hyde.ts +264 -0
- package/src/embeddings/index.ts +10 -0
- package/src/embeddings/openai-provider.ts +414 -0
- package/src/embeddings/pricing.json +22 -0
- package/src/embeddings/provider-constants.ts +204 -0
- package/src/embeddings/provider-errors.test.ts +967 -0
- package/src/embeddings/provider-errors.ts +565 -0
- package/src/embeddings/provider-factory.test.ts +240 -0
- package/src/embeddings/provider-factory.ts +225 -0
- package/src/embeddings/provider-integration.test.ts +788 -0
- package/src/embeddings/query-preprocessing.test.ts +187 -0
- package/src/embeddings/semantic-search-threshold.test.ts +508 -0
- package/src/embeddings/semantic-search.ts +1270 -0
- package/src/embeddings/types.ts +359 -0
- package/src/embeddings/vector-store.ts +708 -0
- package/src/embeddings/voyage-provider.ts +313 -0
- package/src/errors/errors.test.ts +845 -0
- package/src/errors/index.ts +533 -0
- package/src/index/ignore-patterns.test.ts +354 -0
- package/src/index/ignore-patterns.ts +305 -0
- package/src/index/index.ts +4 -0
- package/src/index/indexer.ts +684 -0
- package/src/index/storage.ts +260 -0
- package/src/index/types.ts +147 -0
- package/src/index/watcher.ts +189 -0
- package/src/index.ts +30 -0
- package/src/integration/search-keyword.test.ts +678 -0
- package/src/mcp/server.ts +612 -0
- package/src/parser/index.ts +1 -0
- package/src/parser/parser.test.ts +291 -0
- package/src/parser/parser.ts +394 -0
- package/src/parser/section-filter.test.ts +277 -0
- package/src/parser/section-filter.ts +392 -0
- package/src/search/__tests__/hybrid-search.test.ts +650 -0
- package/src/search/bm25-store.ts +366 -0
- package/src/search/cross-encoder.test.ts +253 -0
- package/src/search/cross-encoder.ts +406 -0
- package/src/search/fuzzy-search.test.ts +419 -0
- package/src/search/fuzzy-search.ts +273 -0
- package/src/search/hybrid-search.ts +448 -0
- package/src/search/path-matcher.test.ts +276 -0
- package/src/search/path-matcher.ts +33 -0
- package/src/search/query-parser.test.ts +260 -0
- package/src/search/query-parser.ts +319 -0
- package/src/search/searcher.test.ts +280 -0
- package/src/search/searcher.ts +724 -0
- package/src/search/wink-bm25.d.ts +30 -0
- package/src/summarization/cli-providers/claude.ts +202 -0
- package/src/summarization/cli-providers/detection.test.ts +273 -0
- package/src/summarization/cli-providers/detection.ts +118 -0
- package/src/summarization/cli-providers/index.ts +8 -0
- package/src/summarization/cost.test.ts +139 -0
- package/src/summarization/cost.ts +102 -0
- package/src/summarization/error-handler.test.ts +127 -0
- package/src/summarization/error-handler.ts +111 -0
- package/src/summarization/index.ts +102 -0
- package/src/summarization/pipeline.test.ts +498 -0
- package/src/summarization/pipeline.ts +231 -0
- package/src/summarization/prompts.test.ts +269 -0
- package/src/summarization/prompts.ts +133 -0
- package/src/summarization/provider-factory.test.ts +396 -0
- package/src/summarization/provider-factory.ts +178 -0
- package/src/summarization/types.ts +184 -0
- package/src/summarize/budget-bugs.test.ts +620 -0
- package/src/summarize/formatters.ts +419 -0
- package/src/summarize/index.ts +20 -0
- package/src/summarize/summarizer.test.ts +275 -0
- package/src/summarize/summarizer.ts +597 -0
- package/src/summarize/verify-bugs.test.ts +238 -0
- package/src/types/huggingface-transformers.d.ts +66 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/tokens.test.ts +142 -0
- package/src/utils/tokens.ts +186 -0
- package/tests/fixtures/cli/.mdcontext/active-provider.json +7 -0
- package/tests/fixtures/cli/.mdcontext/config.json +8 -0
- package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/embeddings/openai_text-embedding-3-small_512/vectors.meta.bin +0 -0
- package/tests/fixtures/cli/.mdcontext/indexes/documents.json +33 -0
- package/tests/fixtures/cli/.mdcontext/indexes/links.json +12 -0
- package/tests/fixtures/cli/.mdcontext/indexes/sections.json +247 -0
- package/tests/fixtures/cli/README.md +9 -0
- package/tests/fixtures/cli/api-reference.md +11 -0
- package/tests/fixtures/cli/getting-started.md +11 -0
- package/tests/integration/embed-index.test.ts +712 -0
- package/tests/integration/search-context.test.ts +469 -0
- package/tests/integration/search-semantic.test.ts +522 -0
- package/tsconfig.json +26 -0
- package/vitest.config.ts +16 -0
- package/vitest.setup.ts +12 -0
|
@@ -0,0 +1,828 @@
|
|
|
1
|
+
# Configuration Management Research for TypeScript CLI Tools (2026)
|
|
2
|
+
|
|
3
|
+
## Executive Summary
|
|
4
|
+
|
|
5
|
+
This research explores configuration management best practices for modern TypeScript CLI tools in 2026. The goal is to determine the optimal configuration approach for the `mdcontext` project, considering developer experience, type safety, flexibility, and ecosystem alignment.
|
|
6
|
+
|
|
7
|
+
**Key Finding**: The modern TypeScript ecosystem has largely converged on **TypeScript/JavaScript config files** with `defineConfig` helpers for type inference, combined with **environment variable overrides** and **Zod for runtime validation**. TOML remains excellent for simpler, human-edited configs but lacks the ecosystem momentum of TS config files.
|
|
8
|
+
|
|
9
|
+
**Recommendation for mdcontext**: Use **c12 (UnJS)** as the config loader with a **TypeScript config file** (`mdcontext.config.ts`) as the primary format, **Zod** for validation, and a clear precedence hierarchy: CLI flags > env vars > config file > defaults.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Current Landscape Overview
|
|
14
|
+
|
|
15
|
+
### What Are Modern TS Projects Using in 2026?
|
|
16
|
+
|
|
17
|
+
| Tool | Config Format | Config Library | Notes |
|
|
18
|
+
| ------------ | ---------------------------- | ----------------------- | ------------------------------------------- |
|
|
19
|
+
| **Vite** | `vite.config.ts` | Native + `defineConfig` | TypeScript-first, uses esbuild for loading |
|
|
20
|
+
| **Vitest** | `vitest.config.ts` | Same as Vite | Inherits Vite's config system |
|
|
21
|
+
| **Next.js** | `next.config.ts` | Native (Node 22+) | Added TS support in Next.js 15 |
|
|
22
|
+
| **Nuxt** | `nuxt.config.ts` | c12 (UnJS) | `defineNuxtConfig` helper |
|
|
23
|
+
| **ESLint** | `eslint.config.ts` | Native + jiti | Flat config, `defineConfig` since v9.22 |
|
|
24
|
+
| **Biome** | `biome.json` / `biome.jsonc` | Native | JSON-only, schema-validated |
|
|
25
|
+
| **Prettier** | `prettier.config.ts` | Native (Node 22+) | TS support added in Prettier 3.5 (Feb 2025) |
|
|
26
|
+
| **tsup** | `tsup.config.ts` | Native | `defineConfig` helper |
|
|
27
|
+
| **Vercel** | `vercel.json` + `vercel.ts` | Native | Programmatic TS config available |
|
|
28
|
+
|
|
29
|
+
**Trend**: TypeScript config files with `defineConfig` helpers have become the dominant pattern. The "cool kids" (Vite ecosystem, UnJS, Vercel) all support or prefer TS config.
|
|
30
|
+
|
|
31
|
+
### Sources
|
|
32
|
+
|
|
33
|
+
- [Configuring Vite](https://vite.dev/config/)
|
|
34
|
+
- [Next.js Configuration](https://nextjs.org/docs/app/api-reference/config/next-config-js)
|
|
35
|
+
- [Nuxt Configuration](https://nuxt.com/docs/4.x/directory-structure/nuxt-config)
|
|
36
|
+
- [ESLint Configuration Files](https://eslint.org/docs/latest/use/configure/configuration-files)
|
|
37
|
+
- [Prettier Configuration](https://prettier.io/docs/configuration)
|
|
38
|
+
- [Biome Configuration](https://biomejs.dev/guides/configure-biome/)
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 2. Format Comparison: TOML vs YAML vs JSON vs TS
|
|
43
|
+
|
|
44
|
+
### Comparison Matrix
|
|
45
|
+
|
|
46
|
+
| Feature | JSON | JSONC | YAML | TOML | TypeScript |
|
|
47
|
+
| -------------------------- | ---------- | ---------- | ---------- | ---------- | ---------- |
|
|
48
|
+
| **Comments** | No | Yes | Yes | Yes | Yes |
|
|
49
|
+
| **Type inference** | Via schema | Via schema | Via schema | Via schema | Native |
|
|
50
|
+
| **IDE support** | Excellent | Good | Good | Good | Excellent |
|
|
51
|
+
| **Programmatic logic** | No | No | No | No | Yes |
|
|
52
|
+
| **Env var interpolation** | No | No | No | No | Yes |
|
|
53
|
+
| **Human readability** | Medium | Medium | High | High | Medium |
|
|
54
|
+
| **Nested data** | Good | Good | Good | Verbose | Good |
|
|
55
|
+
| **Native Node.js support** | Yes | No | No | No | Node 22+ |
|
|
56
|
+
| **Parse errors** | Clear | Clear | Confusing | Clear | Excellent |
|
|
57
|
+
|
|
58
|
+
### Format Details
|
|
59
|
+
|
|
60
|
+
#### JSON / JSONC
|
|
61
|
+
|
|
62
|
+
**Pros**:
|
|
63
|
+
|
|
64
|
+
- Universal support, native to Node.js
|
|
65
|
+
- Every editor highlights it, every language parses it
|
|
66
|
+
- `$schema` enables autocomplete (used by Biome, Vercel)
|
|
67
|
+
|
|
68
|
+
**Cons**:
|
|
69
|
+
|
|
70
|
+
- No comments in standard JSON (JSONC adds them)
|
|
71
|
+
- No programmatic logic or environment interpolation
|
|
72
|
+
- Verbose for deeply nested structures
|
|
73
|
+
|
|
74
|
+
**Best for**: Simple, static configs; package.json-style metadata; schema-validated configs
|
|
75
|
+
|
|
76
|
+
#### YAML
|
|
77
|
+
|
|
78
|
+
**Pros**:
|
|
79
|
+
|
|
80
|
+
- High readability, minimal syntax noise
|
|
81
|
+
- Supports comments, anchors for reuse
|
|
82
|
+
- Standard in DevOps (Kubernetes, GitHub Actions, Docker Compose)
|
|
83
|
+
|
|
84
|
+
**Cons**:
|
|
85
|
+
|
|
86
|
+
- Indentation-sensitive (easy to break)
|
|
87
|
+
- Implicit type coercion causes bugs (`yes` becomes `true`, `3.10` becomes `3.1`)
|
|
88
|
+
- More complex to parse than JSON
|
|
89
|
+
|
|
90
|
+
**Best for**: DevOps configs, CI/CD, when already in YAML-heavy ecosystem
|
|
91
|
+
|
|
92
|
+
#### TOML
|
|
93
|
+
|
|
94
|
+
**Pros**:
|
|
95
|
+
|
|
96
|
+
- Designed explicitly for configuration files
|
|
97
|
+
- Excellent readability with explicit typing
|
|
98
|
+
- Supports comments, dates natively
|
|
99
|
+
- No indentation ambiguity
|
|
100
|
+
- Popular in Rust (Cargo), Python (pyproject.toml), Go ecosystems
|
|
101
|
+
|
|
102
|
+
**Cons**:
|
|
103
|
+
|
|
104
|
+
- Verbose for deeply nested data (`[section.subsection]`)
|
|
105
|
+
- Smaller ecosystem in JavaScript/Node.js
|
|
106
|
+
- No native browser/Node.js support (needs parser)
|
|
107
|
+
- Limited toolchain support compared to JSON
|
|
108
|
+
|
|
109
|
+
**Best for**: Application configuration, when human editing is primary, cross-language projects
|
|
110
|
+
|
|
111
|
+
#### TypeScript Config Files
|
|
112
|
+
|
|
113
|
+
**Pros**:
|
|
114
|
+
|
|
115
|
+
- Native type inference with `defineConfig`
|
|
116
|
+
- Full programmatic power (conditionals, env vars, imports)
|
|
117
|
+
- IDE autocomplete and error checking without schemas
|
|
118
|
+
- Can import other modules, share config
|
|
119
|
+
- Supports environment-specific logic
|
|
120
|
+
|
|
121
|
+
**Cons**:
|
|
122
|
+
|
|
123
|
+
- Requires transpilation (jiti, esbuild, or Node 22+)
|
|
124
|
+
- Not suitable for non-developer editing
|
|
125
|
+
- Harder to parse/validate from external tools
|
|
126
|
+
|
|
127
|
+
**Best for**: Developer tools, build systems, complex configs with logic
|
|
128
|
+
|
|
129
|
+
### Sources
|
|
130
|
+
|
|
131
|
+
- [JSON vs YAML vs TOML: Which Configuration Format Should You Use in 2026?](https://dev.to/jsontoall_tools/json-vs-yaml-vs-toml-which-configuration-format-should-you-use-in-2026-1hlb)
|
|
132
|
+
- [TOML vs YAML vs JSON: Complete Comparison](https://jsontoyamlconverter.com/yaml-vs-json/toml/)
|
|
133
|
+
- [JSON vs YAML vs TOML vs XML: Best Data Format in 2025](https://leapcell.io/blog/json-yaml-toml-xml-best-choice-2025)
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 3. Popular Config Libraries for Node.js/TypeScript
|
|
138
|
+
|
|
139
|
+
### c12 (UnJS) - **Recommended**
|
|
140
|
+
|
|
141
|
+
The "smart configuration loader" from the UnJS ecosystem (Nuxt, Nitro, etc.).
|
|
142
|
+
|
|
143
|
+
**Features**:
|
|
144
|
+
|
|
145
|
+
- Loads `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, `.cts`, `.json` via jiti
|
|
146
|
+
- Loads `.jsonc`, `.json5`, `.yaml`, `.yml`, `.toml` via confbox
|
|
147
|
+
- `.config/` directory support
|
|
148
|
+
- `.rc` file support (`.foorc`)
|
|
149
|
+
- `.env` support with dotenv
|
|
150
|
+
- Extends configurations from multiple sources (local, git, npm)
|
|
151
|
+
- Config watcher with HMR
|
|
152
|
+
- Deep merging with defu
|
|
153
|
+
- Environment-specific overrides (`$development`, `$production`)
|
|
154
|
+
|
|
155
|
+
**Usage**:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { loadConfig } from "c12";
|
|
159
|
+
|
|
160
|
+
const { config, configFile, layers } = await loadConfig({
|
|
161
|
+
name: "mdcontext", // Loads mdcontext.config.ts, .mdcontextrc
|
|
162
|
+
defaults: { port: 3000 }, // Lowest priority
|
|
163
|
+
overrides: { debug: true }, // Highest priority
|
|
164
|
+
dotenv: true, // Load .env
|
|
165
|
+
packageJson: true, // Read from package.json
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Config file example** (`mdcontext.config.ts`):
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
export default {
|
|
173
|
+
// Default configuration
|
|
174
|
+
logLevel: "info",
|
|
175
|
+
|
|
176
|
+
// Environment overrides (automatic)
|
|
177
|
+
$development: { logLevel: "debug" },
|
|
178
|
+
$production: { logLevel: "error" },
|
|
179
|
+
|
|
180
|
+
// Extend from other configs
|
|
181
|
+
extends: ["./base.config"],
|
|
182
|
+
};
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
**Used by**: Nuxt, Nitro, Prisma, WXT, Hey API, Trigger.dev
|
|
186
|
+
|
|
187
|
+
### cosmiconfig
|
|
188
|
+
|
|
189
|
+
The original "find and load configuration" library.
|
|
190
|
+
|
|
191
|
+
**Features**:
|
|
192
|
+
|
|
193
|
+
- Searches multiple locations (`.rc`, `.config/`, `package.json`)
|
|
194
|
+
- Supports JSON, YAML, JS, TS (via loader)
|
|
195
|
+
- Customizable search paths
|
|
196
|
+
- Caching for performance
|
|
197
|
+
- Async and sync APIs
|
|
198
|
+
|
|
199
|
+
**Usage**:
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { cosmiconfig } from "cosmiconfig";
|
|
203
|
+
|
|
204
|
+
const explorer = cosmiconfig("mdcontext");
|
|
205
|
+
const result = await explorer.search();
|
|
206
|
+
// Finds: .mdcontextrc, .mdcontextrc.json, mdcontext.config.js, etc.
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
**Pros**: Battle-tested, widely used, flexible search
|
|
210
|
+
**Cons**: TypeScript support requires additional loader (cosmiconfig-typescript-loader), more configuration needed
|
|
211
|
+
|
|
212
|
+
### rc9 (UnJS)
|
|
213
|
+
|
|
214
|
+
Simple RC file read/write, often used with c12.
|
|
215
|
+
|
|
216
|
+
**Features**:
|
|
217
|
+
|
|
218
|
+
- Read/write `.rc` files
|
|
219
|
+
- User-level configs (`~/.foorc`)
|
|
220
|
+
- System-level configs
|
|
221
|
+
- Flat configuration format
|
|
222
|
+
|
|
223
|
+
**Usage**:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
import { read, write, update } from "rc9";
|
|
227
|
+
|
|
228
|
+
// Read from .mdcontextrc
|
|
229
|
+
const config = read(".mdcontextrc");
|
|
230
|
+
|
|
231
|
+
// Read from user home directory
|
|
232
|
+
const userConfig = readUser(".mdcontextrc"); // ~/.mdcontextrc
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### node-config
|
|
236
|
+
|
|
237
|
+
Enterprise-focused, environment-based configuration.
|
|
238
|
+
|
|
239
|
+
**Features**:
|
|
240
|
+
|
|
241
|
+
- Environment-specific files (`default.json`, `production.json`)
|
|
242
|
+
- Deep merging of config files
|
|
243
|
+
- Custom environment variables
|
|
244
|
+
- Deferred values
|
|
245
|
+
|
|
246
|
+
**Pros**: Great for multi-environment deployments
|
|
247
|
+
**Cons**: Heavier, more enterprise-focused, less TS-native
|
|
248
|
+
|
|
249
|
+
### Sources
|
|
250
|
+
|
|
251
|
+
- [c12 GitHub](https://github.com/unjs/c12)
|
|
252
|
+
- [c12 UnJS](https://unjs.io/packages/c12/)
|
|
253
|
+
- [cosmiconfig GitHub](https://github.com/cosmiconfig/cosmiconfig)
|
|
254
|
+
- [rc9 GitHub](https://github.com/unjs/rc9)
|
|
255
|
+
- [node-config Wiki](https://github.com/node-config/node-config/wiki)
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 4. Environment Variable Override Patterns
|
|
260
|
+
|
|
261
|
+
### Standard Precedence Order (Highest to Lowest)
|
|
262
|
+
|
|
263
|
+
1. **CLI flags** (e.g., `--port 8080`)
|
|
264
|
+
2. **Environment variables** (e.g., `PORT=8080`)
|
|
265
|
+
3. **Environment files** (`.env`, `.env.local`)
|
|
266
|
+
4. **Config files** (e.g., `mdcontext.config.ts`)
|
|
267
|
+
5. **Default values** (in code)
|
|
268
|
+
|
|
269
|
+
This is the order used by Yargs, node-config, and most modern tools.
|
|
270
|
+
|
|
271
|
+
### Pattern 1: Prefix-Based Env Vars
|
|
272
|
+
|
|
273
|
+
Map env vars with a prefix to config keys:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
MDCONTEXT_LOG_LEVEL=debug → config.logLevel
|
|
277
|
+
MDCONTEXT_PORT=8080 → config.port
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**Implementation with c12**:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// c12 doesn't auto-map env vars, but you can use overrides
|
|
284
|
+
import { loadConfig } from "c12";
|
|
285
|
+
|
|
286
|
+
const envOverrides = {
|
|
287
|
+
logLevel: process.env.MDCONTEXT_LOG_LEVEL,
|
|
288
|
+
port: process.env.MDCONTEXT_PORT
|
|
289
|
+
? parseInt(process.env.MDCONTEXT_PORT)
|
|
290
|
+
: undefined,
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
const { config } = await loadConfig({
|
|
294
|
+
name: "mdcontext",
|
|
295
|
+
overrides: Object.fromEntries(
|
|
296
|
+
Object.entries(envOverrides).filter(([_, v]) => v !== undefined),
|
|
297
|
+
),
|
|
298
|
+
});
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Pattern 2: dotenv Integration
|
|
302
|
+
|
|
303
|
+
Load `.env` files and merge with config:
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
import { loadConfig } from "c12";
|
|
307
|
+
|
|
308
|
+
const { config } = await loadConfig({
|
|
309
|
+
name: "mdcontext",
|
|
310
|
+
dotenv: true, // Loads .env automatically
|
|
311
|
+
});
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### Pattern 3: Zod Transform
|
|
315
|
+
|
|
316
|
+
Use Zod to coerce and validate env vars:
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
import { z } from "zod";
|
|
320
|
+
|
|
321
|
+
const envSchema = z.object({
|
|
322
|
+
MDCONTEXT_LOG_LEVEL: z
|
|
323
|
+
.enum(["debug", "info", "warn", "error"])
|
|
324
|
+
.default("info"),
|
|
325
|
+
MDCONTEXT_PORT: z.coerce.number().default(3000),
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
const env = envSchema.parse(process.env);
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Sources
|
|
332
|
+
|
|
333
|
+
- [node-config Environment Variables](https://github.com/node-config/node-config/wiki/Environment-Variables)
|
|
334
|
+
- [Node.js CLI Documentation](https://nodejs.org/api/cli.html)
|
|
335
|
+
- [Yargs Precedence Discussion](https://github.com/yargs/yargs/issues/627)
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## 5. Type Safety: Getting TypeScript Types from Config
|
|
340
|
+
|
|
341
|
+
### Pattern 1: `defineConfig` Helper (Recommended)
|
|
342
|
+
|
|
343
|
+
The modern pattern used by Vite, ESLint, Nuxt, and tsup.
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
// mdcontext.config.ts
|
|
347
|
+
import { defineConfig } from "mdcontext";
|
|
348
|
+
|
|
349
|
+
export default defineConfig({
|
|
350
|
+
logLevel: "info",
|
|
351
|
+
watch: {
|
|
352
|
+
enabled: true,
|
|
353
|
+
debounce: 100,
|
|
354
|
+
},
|
|
355
|
+
});
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
**Implementation**:
|
|
359
|
+
|
|
360
|
+
```typescript
|
|
361
|
+
// src/config/define.ts
|
|
362
|
+
import type { Config } from "./schema";
|
|
363
|
+
|
|
364
|
+
export function defineConfig(config: Config): Config {
|
|
365
|
+
return config;
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
This is a pass-through function that provides type inference in the config file.
|
|
370
|
+
|
|
371
|
+
### Pattern 2: Zod Schema with Type Inference
|
|
372
|
+
|
|
373
|
+
Define schema once, get both validation and types:
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
// src/config/schema.ts
|
|
377
|
+
import { z } from "zod";
|
|
378
|
+
|
|
379
|
+
export const ConfigSchema = z.object({
|
|
380
|
+
logLevel: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
381
|
+
watch: z
|
|
382
|
+
.object({
|
|
383
|
+
enabled: z.boolean().default(true),
|
|
384
|
+
debounce: z.number().min(0).default(100),
|
|
385
|
+
})
|
|
386
|
+
.default({}),
|
|
387
|
+
embeddings: z
|
|
388
|
+
.object({
|
|
389
|
+
provider: z.enum(["openai", "local"]).default("openai"),
|
|
390
|
+
model: z.string().optional(),
|
|
391
|
+
})
|
|
392
|
+
.default({}),
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// Infer type from schema
|
|
396
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
**Usage**:
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import { loadConfig } from "c12";
|
|
403
|
+
import { ConfigSchema, type Config } from "./schema";
|
|
404
|
+
|
|
405
|
+
export async function loadMdcontextConfig(): Promise<Config> {
|
|
406
|
+
const { config } = await loadConfig({ name: "mdcontext" });
|
|
407
|
+
return ConfigSchema.parse(config);
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### Pattern 3: JSON Schema (for JSON/JSONC configs)
|
|
412
|
+
|
|
413
|
+
For tools like Biome and Vercel that use JSON:
|
|
414
|
+
|
|
415
|
+
```json
|
|
416
|
+
{
|
|
417
|
+
"$schema": "https://mdcontext.dev/schema.json",
|
|
418
|
+
"logLevel": "info"
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Provides autocomplete in editors via JSON Schema.
|
|
423
|
+
|
|
424
|
+
### Sources
|
|
425
|
+
|
|
426
|
+
- [Type your Config - Anthony Fu](https://antfu.me/posts/type-your-config)
|
|
427
|
+
- [Zod Documentation](https://zod.dev/)
|
|
428
|
+
- [ESLint defineConfig](https://eslint.org/blog/2025/03/flat-config-extends-define-config-global-ignores/)
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
## 6. Hierarchical/Cascading Configuration
|
|
433
|
+
|
|
434
|
+
### Level Hierarchy
|
|
435
|
+
|
|
436
|
+
Modern tools typically support three levels:
|
|
437
|
+
|
|
438
|
+
1. **Project-level** (`./<name>.config.ts`, `./.<name>rc`)
|
|
439
|
+
2. **User-level** (`~/.config/<name>/config.ts`, `~/.<name>rc`)
|
|
440
|
+
3. **System-level** (`/etc/<name>/config.ts`) - less common
|
|
441
|
+
|
|
442
|
+
### c12 Implementation
|
|
443
|
+
|
|
444
|
+
c12 supports this via `globalRc`:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import { loadConfig } from "c12";
|
|
448
|
+
|
|
449
|
+
const { config, layers } = await loadConfig({
|
|
450
|
+
name: "mdcontext",
|
|
451
|
+
globalRc: true, // Loads from ~/.mdcontextrc
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// layers shows the merge order:
|
|
455
|
+
// [
|
|
456
|
+
// { config: {...}, configFile: "/home/user/.mdcontextrc" },
|
|
457
|
+
// { config: {...}, configFile: "/project/mdcontext.config.ts" },
|
|
458
|
+
// ]
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### XDG Base Directory Compliance
|
|
462
|
+
|
|
463
|
+
For cross-platform user configs, follow XDG conventions:
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
import envPaths from "env-paths";
|
|
467
|
+
|
|
468
|
+
const paths = envPaths("mdcontext");
|
|
469
|
+
// paths.config → ~/.config/mdcontext (Linux)
|
|
470
|
+
// paths.config → ~/Library/Preferences/mdcontext (macOS)
|
|
471
|
+
// paths.config → %APPDATA%\mdcontext\Config (Windows)
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
Use `env-paths` for macOS/Windows, `xdg-basedir` for Linux-only.
|
|
475
|
+
|
|
476
|
+
### Sources
|
|
477
|
+
|
|
478
|
+
- [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir/latest/)
|
|
479
|
+
- [env-paths GitHub](https://github.com/sindresorhus/env-paths)
|
|
480
|
+
- [xdg-basedir GitHub](https://github.com/sindresorhus/xdg-basedir)
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## 7. What the "Cool Kids" Actually Use
|
|
485
|
+
|
|
486
|
+
### Vercel Ecosystem
|
|
487
|
+
|
|
488
|
+
- **Next.js**: `next.config.ts` with `NextConfig` type, supports TS natively in Node 22+
|
|
489
|
+
- **Vercel CLI**: `vercel.json` (static) + `vercel.ts` (programmatic)
|
|
490
|
+
- Pattern: JSON for simple, TS for complex
|
|
491
|
+
|
|
492
|
+
### UnJS / Nuxt Ecosystem
|
|
493
|
+
|
|
494
|
+
- **Nuxt**: `nuxt.config.ts` with `defineNuxtConfig`, powered by c12
|
|
495
|
+
- **Nitro**: Uses c12 for configuration
|
|
496
|
+
- **Vite**: `vite.config.ts` with `defineConfig`
|
|
497
|
+
- Pattern: Always TypeScript, always `defineConfig` helper
|
|
498
|
+
|
|
499
|
+
### Biome
|
|
500
|
+
|
|
501
|
+
- **Format**: `biome.json` or `biome.jsonc` only
|
|
502
|
+
- **Philosophy**: JSON for simplicity, schema for validation
|
|
503
|
+
- Pattern: JSON with `$schema` for autocomplete
|
|
504
|
+
|
|
505
|
+
### ESLint
|
|
506
|
+
|
|
507
|
+
- **Format**: `eslint.config.ts` (flat config, since ESLint 9)
|
|
508
|
+
- **Helper**: `defineConfig` (since v9.22)
|
|
509
|
+
- **TypeScript**: Requires jiti or Node 22+
|
|
510
|
+
- Pattern: TypeScript config with extends for composition
|
|
511
|
+
|
|
512
|
+
### Summary
|
|
513
|
+
|
|
514
|
+
The "cool kids" (Vite, Nuxt, Vercel) prefer:
|
|
515
|
+
|
|
516
|
+
1. **TypeScript config files** as primary format
|
|
517
|
+
2. **`defineConfig` helper** for type inference
|
|
518
|
+
3. **Programmatic configs** over static JSON/YAML
|
|
519
|
+
4. **Environment-specific overrides** built into the config system
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## 8. Recommendation for mdcontext
|
|
524
|
+
|
|
525
|
+
### Primary Approach: TypeScript Config with c12
|
|
526
|
+
|
|
527
|
+
**Rationale**:
|
|
528
|
+
|
|
529
|
+
- Aligns with the TypeScript ecosystem mdcontext is built on
|
|
530
|
+
- c12 is production-proven (Nuxt, Nitro, Prisma)
|
|
531
|
+
- Supports all formats if users prefer TOML/YAML
|
|
532
|
+
- Built-in environment overrides, extends, and watch support
|
|
533
|
+
- Works with the UnJS ecosystem mdcontext might integrate with
|
|
534
|
+
|
|
535
|
+
### Implementation Plan
|
|
536
|
+
|
|
537
|
+
#### 1. Config Schema with Zod
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
// src/config/schema.ts
|
|
541
|
+
import { z } from "zod";
|
|
542
|
+
|
|
543
|
+
export const ConfigSchema = z.object({
|
|
544
|
+
// Core settings
|
|
545
|
+
logLevel: z.enum(["debug", "info", "warn", "error"]).default("info"),
|
|
546
|
+
|
|
547
|
+
// Watch settings
|
|
548
|
+
watch: z
|
|
549
|
+
.object({
|
|
550
|
+
enabled: z.boolean().default(true),
|
|
551
|
+
debounce: z.number().min(0).default(100),
|
|
552
|
+
ignore: z.array(z.string()).default(["**/node_modules/**", "**/.git/**"]),
|
|
553
|
+
})
|
|
554
|
+
.default({}),
|
|
555
|
+
|
|
556
|
+
// Embeddings
|
|
557
|
+
embeddings: z
|
|
558
|
+
.object({
|
|
559
|
+
provider: z.enum(["openai", "local", "none"]).default("none"),
|
|
560
|
+
model: z.string().optional(),
|
|
561
|
+
apiKey: z.string().optional(),
|
|
562
|
+
})
|
|
563
|
+
.default({}),
|
|
564
|
+
|
|
565
|
+
// Output
|
|
566
|
+
output: z
|
|
567
|
+
.object({
|
|
568
|
+
format: z.enum(["json", "markdown", "compact"]).default("json"),
|
|
569
|
+
tokenBudget: z.number().positive().optional(),
|
|
570
|
+
})
|
|
571
|
+
.default({}),
|
|
572
|
+
|
|
573
|
+
// Extends other configs
|
|
574
|
+
extends: z.union([z.string(), z.array(z.string())]).optional(),
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
export type Config = z.infer<typeof ConfigSchema>;
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
#### 2. defineConfig Helper
|
|
581
|
+
|
|
582
|
+
````typescript
|
|
583
|
+
// src/config/define.ts
|
|
584
|
+
import type { Config } from "./schema";
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Define mdcontext configuration with full type inference.
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```ts
|
|
591
|
+
* // mdcontext.config.ts
|
|
592
|
+
* import { defineConfig } from "mdcontext";
|
|
593
|
+
*
|
|
594
|
+
* export default defineConfig({
|
|
595
|
+
* logLevel: "debug",
|
|
596
|
+
* embeddings: {
|
|
597
|
+
* provider: "openai",
|
|
598
|
+
* },
|
|
599
|
+
* });
|
|
600
|
+
* ```
|
|
601
|
+
*/
|
|
602
|
+
export function defineConfig(config: Partial<Config>): Partial<Config> {
|
|
603
|
+
return config;
|
|
604
|
+
}
|
|
605
|
+
````
|
|
606
|
+
|
|
607
|
+
#### 3. Config Loader
|
|
608
|
+
|
|
609
|
+
```typescript
|
|
610
|
+
// src/config/loader.ts
|
|
611
|
+
import { loadConfig } from "c12";
|
|
612
|
+
import { ConfigSchema, type Config } from "./schema";
|
|
613
|
+
|
|
614
|
+
export interface LoadConfigOptions {
|
|
615
|
+
cwd?: string;
|
|
616
|
+
overrides?: Partial<Config>;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export async function loadMdcontextConfig(
|
|
620
|
+
options: LoadConfigOptions = {},
|
|
621
|
+
): Promise<{ config: Config; configFile?: string }> {
|
|
622
|
+
const { config: rawConfig, configFile } = await loadConfig({
|
|
623
|
+
name: "mdcontext",
|
|
624
|
+
cwd: options.cwd,
|
|
625
|
+
defaults: ConfigSchema.parse({}), // Apply defaults
|
|
626
|
+
overrides: options.overrides,
|
|
627
|
+
dotenv: true,
|
|
628
|
+
globalRc: true,
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
// Validate with Zod
|
|
632
|
+
const config = ConfigSchema.parse(rawConfig);
|
|
633
|
+
|
|
634
|
+
return { config, configFile };
|
|
635
|
+
}
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### 4. CLI Integration
|
|
639
|
+
|
|
640
|
+
```typescript
|
|
641
|
+
// src/cli/index.ts
|
|
642
|
+
import { defineCommand, runMain } from "citty";
|
|
643
|
+
import { loadMdcontextConfig } from "../config/loader";
|
|
644
|
+
|
|
645
|
+
const main = defineCommand({
|
|
646
|
+
meta: {
|
|
647
|
+
name: "mdcontext",
|
|
648
|
+
version: "1.0.0",
|
|
649
|
+
},
|
|
650
|
+
args: {
|
|
651
|
+
logLevel: {
|
|
652
|
+
type: "string",
|
|
653
|
+
description: "Log level (debug, info, warn, error)",
|
|
654
|
+
},
|
|
655
|
+
config: {
|
|
656
|
+
type: "string",
|
|
657
|
+
alias: "c",
|
|
658
|
+
description: "Path to config file",
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
async run({ args }) {
|
|
662
|
+
// CLI flags override config
|
|
663
|
+
const overrides: Partial<Config> = {};
|
|
664
|
+
if (args.logLevel) overrides.logLevel = args.logLevel;
|
|
665
|
+
|
|
666
|
+
const { config } = await loadMdcontextConfig({ overrides });
|
|
667
|
+
// Use config...
|
|
668
|
+
},
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
runMain(main);
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
#### 5. Example Config File
|
|
675
|
+
|
|
676
|
+
```typescript
|
|
677
|
+
// mdcontext.config.ts
|
|
678
|
+
import { defineConfig } from "mdcontext";
|
|
679
|
+
|
|
680
|
+
export default defineConfig({
|
|
681
|
+
logLevel: "info",
|
|
682
|
+
|
|
683
|
+
watch: {
|
|
684
|
+
enabled: true,
|
|
685
|
+
debounce: 200,
|
|
686
|
+
ignore: ["**/node_modules/**", "**/dist/**"],
|
|
687
|
+
},
|
|
688
|
+
|
|
689
|
+
embeddings: {
|
|
690
|
+
provider: "openai",
|
|
691
|
+
model: "text-embedding-3-small",
|
|
692
|
+
},
|
|
693
|
+
|
|
694
|
+
// Environment-specific overrides
|
|
695
|
+
$development: {
|
|
696
|
+
logLevel: "debug",
|
|
697
|
+
},
|
|
698
|
+
|
|
699
|
+
$production: {
|
|
700
|
+
logLevel: "warn",
|
|
701
|
+
},
|
|
702
|
+
});
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### Precedence Order
|
|
706
|
+
|
|
707
|
+
1. **CLI flags** (`--log-level debug`)
|
|
708
|
+
2. **Environment variables** (`MDCONTEXT_LOG_LEVEL=debug`)
|
|
709
|
+
3. **Environment files** (`.env`, `.env.local`)
|
|
710
|
+
4. **Project config** (`./mdcontext.config.ts`, `./.mdcontextrc`)
|
|
711
|
+
5. **User config** (`~/.config/mdcontext/config.ts`)
|
|
712
|
+
6. **Default values** (from Zod schema)
|
|
713
|
+
|
|
714
|
+
### Migration Path
|
|
715
|
+
|
|
716
|
+
1. **No config**: Tool works with sensible defaults from Zod schema
|
|
717
|
+
2. **Simple config**: Users can create `.mdcontextrc` (JSON) or `mdcontext.config.ts`
|
|
718
|
+
3. **Advanced config**: Full TypeScript with extends, env overrides, etc.
|
|
719
|
+
|
|
720
|
+
### Dependencies
|
|
721
|
+
|
|
722
|
+
```json
|
|
723
|
+
{
|
|
724
|
+
"dependencies": {
|
|
725
|
+
"c12": "^2.0.0",
|
|
726
|
+
"zod": "^3.23.0"
|
|
727
|
+
},
|
|
728
|
+
"devDependencies": {
|
|
729
|
+
"citty": "^0.1.6"
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
---
|
|
735
|
+
|
|
736
|
+
## 9. Alternative: TOML-First Approach
|
|
737
|
+
|
|
738
|
+
If mdcontext prioritizes human-edited configs over programmatic configs:
|
|
739
|
+
|
|
740
|
+
### When to Use TOML
|
|
741
|
+
|
|
742
|
+
- Non-developer users edit config (rare for CLI tools)
|
|
743
|
+
- Cross-language ecosystem (Rust, Python, Go)
|
|
744
|
+
- Simple, flat configuration structure
|
|
745
|
+
- Comments are critical for documentation
|
|
746
|
+
|
|
747
|
+
### TOML Implementation with c12
|
|
748
|
+
|
|
749
|
+
c12 supports TOML natively via confbox:
|
|
750
|
+
|
|
751
|
+
```toml
|
|
752
|
+
# mdcontext.toml
|
|
753
|
+
log_level = "info"
|
|
754
|
+
|
|
755
|
+
[watch]
|
|
756
|
+
enabled = true
|
|
757
|
+
debounce = 100
|
|
758
|
+
|
|
759
|
+
[embeddings]
|
|
760
|
+
provider = "openai"
|
|
761
|
+
model = "text-embedding-3-small"
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
```typescript
|
|
765
|
+
import { loadConfig } from "c12";
|
|
766
|
+
|
|
767
|
+
const { config } = await loadConfig({
|
|
768
|
+
name: "mdcontext",
|
|
769
|
+
configFile: "mdcontext.toml", // Explicit TOML
|
|
770
|
+
});
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
### Recommendation
|
|
774
|
+
|
|
775
|
+
For mdcontext, **TypeScript config is recommended** over TOML because:
|
|
776
|
+
|
|
777
|
+
1. Target audience is developers who know TypeScript
|
|
778
|
+
2. Programmatic power (conditionals, env interpolation) is valuable
|
|
779
|
+
3. Better IDE support without additional schema setup
|
|
780
|
+
4. Aligns with the TypeScript/Effect ecosystem
|
|
781
|
+
|
|
782
|
+
---
|
|
783
|
+
|
|
784
|
+
## 10. Summary: Key Decisions
|
|
785
|
+
|
|
786
|
+
| Decision | Choice | Rationale |
|
|
787
|
+
| ----------------------- | ---------------------------------- | ---------------------------------------------------- |
|
|
788
|
+
| **Config library** | c12 (UnJS) | Production-proven, multi-format, ecosystem alignment |
|
|
789
|
+
| **Primary format** | TypeScript (`mdcontext.config.ts`) | Type inference, programmatic power |
|
|
790
|
+
| **Type safety** | Zod + `defineConfig` | Runtime validation + DX |
|
|
791
|
+
| **Fallback formats** | `.mdcontextrc` (JSON), TOML, YAML | c12 supports all via confbox |
|
|
792
|
+
| **Env vars** | Prefix-based + dotenv | `MDCONTEXT_*` pattern |
|
|
793
|
+
| **Hierarchical config** | Project > User via c12 globalRc | Standard hierarchy |
|
|
794
|
+
| **CLI integration** | citty (UnJS) | Modern, typed, lightweight |
|
|
795
|
+
|
|
796
|
+
---
|
|
797
|
+
|
|
798
|
+
## References
|
|
799
|
+
|
|
800
|
+
### Libraries
|
|
801
|
+
|
|
802
|
+
- [c12 - Smart Configuration Loader](https://github.com/unjs/c12)
|
|
803
|
+
- [cosmiconfig](https://github.com/cosmiconfig/cosmiconfig)
|
|
804
|
+
- [rc9 - RC File Handler](https://github.com/unjs/rc9)
|
|
805
|
+
- [jiti - Runtime TypeScript](https://github.com/unjs/jiti)
|
|
806
|
+
- [confbox - Config Parsers](https://github.com/unjs/confbox)
|
|
807
|
+
- [citty - CLI Builder](https://github.com/unjs/citty)
|
|
808
|
+
- [Zod - Schema Validation](https://zod.dev/)
|
|
809
|
+
- [env-paths - Cross-Platform Paths](https://github.com/sindresorhus/env-paths)
|
|
810
|
+
|
|
811
|
+
### Documentation
|
|
812
|
+
|
|
813
|
+
- [Vite Configuration](https://vite.dev/config/)
|
|
814
|
+
- [Next.js Configuration](https://nextjs.org/docs/app/api-reference/config/next-config-js)
|
|
815
|
+
- [Nuxt Configuration](https://nuxt.com/docs/4.x/directory-structure/nuxt-config)
|
|
816
|
+
- [ESLint Flat Config](https://eslint.org/docs/latest/use/configure/configuration-files)
|
|
817
|
+
- [Biome Configuration](https://biomejs.dev/guides/configure-biome/)
|
|
818
|
+
- [Prettier Configuration](https://prettier.io/docs/configuration)
|
|
819
|
+
|
|
820
|
+
### Articles
|
|
821
|
+
|
|
822
|
+
- [Type your Config - Anthony Fu](https://antfu.me/posts/type-your-config)
|
|
823
|
+
- [JSON vs YAML vs TOML - 2025 Comparison](https://leapcell.io/blog/json-yaml-toml-xml-best-choice-2025)
|
|
824
|
+
- [ESLint defineConfig Introduction](https://eslint.org/blog/2025/03/flat-config-extends-define-config-global-ignores/)
|
|
825
|
+
|
|
826
|
+
---
|
|
827
|
+
|
|
828
|
+
_Research completed: 2026-01-21_
|