intent(parity-coverage): the numeric-constraint enforcement block already rejects non-integer `maxFileSize` and `splitOutput`, but the three `v.pipe(v.number(), v.integer(), v.minValue(1))` siblings (`topFilesLength`, `git.sortByChangesMaxCommits`, `git.includeLogsCount`) only had min-bound rejection. Add non-integer cases for each so every pipe-guarded numeric field has matching fencepost coverage
intent(readability): an issue with no `path` (e.g., root-level schema mismatch) previously rendered as `[] message`; emit just `message` when segments are empty. Small quality-of-life for error output
intent(limitation-pin): add an integration test that documents the known ESM unwrap ambiguity — a CJS module shaped like `{ default: {...}, otherKey: ... }` has `otherKey` silently dropped by our heuristic. Non-issue for RepomixConfig today, but worth freezing so the behavior can't drift without someone noticing
intent(pre-merge-gate): buildCliConfig parses against repomixConfigCliSchema before mergeConfigs, so the intersect must preserve both the base-schema `output.filePath` and the CLI-only `output.stdout` + top-level `skillGenerate` before the merged schema ever sees the value. Add a targeted test so a future change to the intersect shape doesn't silently strip CLI fields at the cli-parse step
intent(regression-guard): `repomixConfigDefaultSchema.output` is strict and omits `stdout`, so any future change that alters `v.intersect` merging semantics would silently drop the CLI `--stdout` flag (and `skillGenerate`) after `mergeConfigs` validates the merged value. Pin the behavior with a targeted test
intent(behavioral-coverage): previous tests verified structural equivalence to the zod schemas but never asserted that the integer / minValue / maxValue pipes actually reject invalid values — add focused rejection cases for maxFileSize, topFilesLength, splitOutput, and the git counts so the constraint migration is proven behaviorally
decision(default-schema-maxvalue): mirror the `v.maxValue(Number.MAX_SAFE_INTEGER)` from the base schema onto `repomixConfigDefaultSchema.splitOutput` so the upper bound is enforced regardless of which schema the caller parses against — the prior edit only touched the base entry
intent(test-coverage): the nuanced `defaultExport typeof object` check in configLoad was only exercised through real jiti imports — add two mocked jitiImport cases so the wrapped-object unwrap branch and the CJS-with-primitive-`default` pass-through branch are both guarded against regressions
intent(error-handle): drop the instanceof Error guard in rethrowValidationErrorIfSchemaError so ValiError / ZodError round-tripped through a worker (plain { name, message, issues }) is still recognized — aligns with isError / isRepomixError elsewhere in the file
intent(schema-parity): restore splitOutput's upper bound (Number.MAX_SAFE_INTEGER) in the generated JSON schema so editor hints match the previous zod output; also strip the empty required:[] arrays that @valibot/to-json-schema emits on every object node
intent(esm-unwrap): only unwrap jiti's .default when it's an object, preserving a CJS config that legitimately exports { default: 'plain', ...rest }; plain Symbol.toStringTag === 'Module' was too narrow — jiti returns non-Module namespace wrappers for .ts / .mts files
intent(test-coverage): add tests/shared/errorHandle.test.ts covering the Zod + Valibot + worker-serialized paths through rethrowValidationErrorIfSchemaError; tighten the default-schema assertion in configSchema.test.ts from /expected|invalid/i to toThrow(v.ValiError) + targeted message pattern
decision(path-segment-fallback): return '' for unknown object-shaped path items instead of falling into String(segment) → "[object Object]"; defensive, non-breaking
intent(cold-start): evaluate valibot as a simpler alternative to PR #1484's async deferral of zod
decision(validation-library): valibot v1 picked for smaller module graph and tree-shaking friendliness
decision(error-handling): rename rethrowValidationErrorIfZodError to rethrowValidationErrorIfSchemaError and duck-type both ZodError and ValiError so the helper stays library-agnostic
constraint(module-unwrap): jiti.import returns an ESM Module namespace even with interopDefault — zod v4 quietly unwrapped it, valibot does not, so configLoad manually picks .default
learned(zod-v4-modules): z.object().parse(moduleNamespace) reaches into .default automatically — not documented prominently and was masking the jiti interop gap
learned(cold-start-impact): ~10ms (~6%) faster startup in hyperfine A/B — below the -15ms bar from the task spec, but worth keeping as a branch for the simplicity win
The --config flag represents an explicit user choice and should not be
blocked in remote mode. Only auto-detected config files in the cloned
repo are skipped.
Also adds a logger.note() message when a config file is found in the
remote repository but skipped, guiding users to --remote-trust-config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When using `repomix --remote <url>` or the MCP `pack_remote_repository` tool,
config files (repomix.config.ts/js) from the cloned repository were executed
via jiti, allowing a malicious repository to achieve arbitrary code execution
on the user's machine.
This commit skips all local config file loading when processing remote
repositories. The `isRemote` flag is propagated from remoteAction through
defaultAction to loadFileConfig, which skips local config auto-detection
and --config flag resolution. Global config and CLI options continue to
work normally.
Users who need to trust remote configs can do so in a future release via
an explicit opt-in flag (e.g., --trust-remote-config).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace process.exit() with OperationCancelledError in skillPrompts.ts
- Centralize Handlebars helper registration in outputStyleUtils.ts
- Add path normalization validation in generateSkillTool.ts
- Set idempotentHint to true for generate_skill MCP tool
- Add skillGenerate config merge tests in configLoad.test.ts
- Add path normalization test in generateSkillTool.test.ts
This PR adds support for .ignore files, which are used by tools like ripgrep and the silver searcher. This allows users to maintain a single .ignore file that works across multiple tools instead of maintaining separate ignore files.
Changes:
- Add ignore.useDotIgnore config option (default: true)
- Add --no-dot-ignore CLI flag to disable .ignore file usage
- Update ignore file priority: .repomixignore > .ignore > .gitignore > default patterns
- Add comprehensive tests for .ignore file handling
- Update documentation to reflect new .ignore file support
The .ignore file is enabled by default but can be disabled via configuration or CLI flag, maintaining backward compatibility.
Resolves#937
This commit resolves test coverage instability that occurred after
implementing JS/TS config support. Coverage was fluctuating between
68-71% on each test run, caused by jiti dynamically transforming src/
files that were already instrumented by Vitest for coverage tracking.
Root Cause:
- Test fixture files imported `defineConfig` from src/index.js
- jiti transformed the entire src/ directory when loading fixtures
- Same files existed in two versions (Vitest-instrumented vs jiti-transformed)
- v8 coverage tracker produced non-deterministic results
Solution:
1. Added DI pattern to loadFileConfig with defaultJitiImport factory
2. Removed defineConfig imports from all test fixtures (use plain objects)
3. Mock jiti in dynamic config tests to prevent src/ transformation
Results:
- Coverage now stable at 89.34% (previously 68-71%)
- Coverage improved by ~19% due to accurate instrumentation
- Integration test runtime improved from 3.8s to 0.1s
- All tests pass with zero lint errors
Related Changes:
- Reverted temporary Vitest config workarounds (sequence.shuffle, isolate)
- Extracted defaultJitiImport as reusable factory function
Added comprehensive error handling tests for configLoad.ts to improve coverage:
- Added test for unsupported config file format (.yaml, .toml)
- Added test for general error handling (permission denied)
- Added test for non-Error object error handling
- Improved branch coverage for error cases in loadAndValidateConfig
This addresses the coverage drop that occurred in commit 156897d8 when
TypeScript/JavaScript config file support was added.
Improvements:
- Test count: 840 → 844 (+4 tests)
- Config branch coverage: 80.88% → 86.11% (+5.23%)
- Overall branch coverage: 78.55% → 78.76% (+0.21%)
Added a test to verify that Zod v4 provides helpful error messages when
required fields are missing from the config schema. The test ensures that
the error message includes "expected object" to help users understand what
went wrong.
This addresses the suggestion from Claude bot to improve test coverage
for error message quality and helps catch regressions in error messaging.
Addresses AI reviewer feedback on PR #923:
**Critical fixes:**
- Use structuredClone(defaultConfig) to prevent mutation of global defaults
- Move filePath assignment to merge-time instead of mutating baseConfig
- This prevents side effects in long-running processes and test suites
**Documentation improvements:**
- Add comment explaining Zod v4 nested object initialization pattern
- Expand @ts-nocheck comments in MCP files explaining type incompatibility
- Clarify that the issue extends beyond .shape to handler function signatures
**Test coverage:**
- Add test for nested git config merging (Zod v4 specific behavior)
- Add test to verify defaultConfig immutability
- Add test for tokenCount config merging
All 803 tests passing, all lint checks passing.
Fixes identified by @gemini-code-assist, @coderabbitai, and @claude.
Add support for TypeScript configuration files (.ts, .mts, .cts) using jiti for better developer experience.
**Changes:**
- Install jiti dependency for TypeScript transpilation
- Update config file priority: TS > JS > JSON
- Add TypeScript config test fixtures
- Add integration tests for all TS config formats
- Update documentation (README and website) with TS examples
- Fix existing tests to account for new priority order
**Priority order:**
1. repomix.config.ts/mts/cts
2. repomix.config.js/mjs/cjs
3. repomix.config.json5
4. repomix.config.jsonc
5. repomix.config.json
**Benefits:**
- Full TypeScript type checking in config files
- Excellent IDE autocomplete and IntelliSense
- Compile-time error detection
- Dynamic configuration with type safety
Relates to #870
Add support for JavaScript configuration files (.js, .mjs, .cjs) with a defineConfig helper function for better DX, similar to Vite and ESLint.
**Changes:**
- Add defineConfig() helper function for type-safe config definitions
- Support dynamic values (timestamps, environment variables, etc.)
- Prioritize JS config files over JSON formats
- Update documentation (README and website) with JS config examples
- Add integration tests for JS config files
**Priority order:**
1. repomix.config.js/mjs/cjs
2. repomix.config.json5
3. repomix.config.jsonc
4. repomix.config.json
**Benefits:**
- Better IDE support with TypeScript types
- Dynamic configuration based on environment
- More flexible than static JSON
Relates to #870
Updated biome from v1.9.4 to v2.2.4 to take advantage of latest linting improvements.
- Upgraded @biomejs/biome from ^1.9.4 to ^2.2.4
- Updated biome.json configuration for v2 compatibility:
- Changed schema to 2.2.4
- Updated file includes/ignores syntax
- Added Vue file overrides to disable noUnusedVariables/noUnusedImports
- Fixed all lint errors:
- Added radix parameter to parseInt calls
- Prefixed unused parameters with underscore
- Removed unused imports
- Fixed biome suppression comments
- Removed !important from CSS
- Added type ignores for Vue component definitions
All 325 files now pass lint with 0 warnings and 0 errors.
This feature allows users to include git log information in the output to help AI understand development patterns and file change relationships.
Key changes:
- Added --include-logs and --include-logs-count CLI options
- Default to 50 commits, configurable via CLI and config file
- Includes commit date, message, and changed file paths (excludes commit hashes)
- Added security checks and metrics calculation for git logs
- Updated output templates to include git logs section
- Comprehensive test coverage and TypeScript fixes
Resolves user request for including git commit history to provide development context for AI analysis.
- Merge displayTokenCountTree functionality directly into reportTokenCountTree
- Remove separate displayTokenCountTree export and test file for better code organization
- Update configSchema to accept string values for tokenCountTree (boolean | number | string)
- Enhance tokenCountTreeReporter to handle string to number conversion
- Fix config tests to properly validate tokenCountTree type union
This consolidates the token count tree display logic into a single function
while maintaining all existing functionality and improving type safety.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major restructuring of CLI options and tokenCountTree functionality:
CLI Options:
- Reorganized options into logical groups: "CLI Input/Output Options", "Repomix Output Options", and "File Selection Options"
- Moved --verbose, --quiet, --stdout, --stdin, --copy, --token-count-tree, --top-files-len to CLI I/O group
- Renamed --summarize-token-counts to --token-count-tree for clarity
- Updated README.md documentation to reflect new option organization
TokenCountTree Refactoring:
- Moved tokenCountTree functionality from saveTokenCounts.ts to cliPrint.ts as printTokenCountTree
- Deleted saveTokenCounts.ts (no longer needed)
- Removed handleTokenCountTree function from defaultAction.ts
- Integrated printTokenCountTree into printResults workflow for consistency
- Updated threshold calculation to be handled within printTokenCountTree
Configuration:
- Added tokenCountTree option to config schema with default value false
- Changed schema from z.union([z.boolean(), z.string()]) to z.union([z.boolean(), z.number()])
- CLI now converts string thresholds to numbers during buildCliConfig
Optimizations:
- Modified calculateMetrics to calculate all file tokens when tokenCountTree is enabled
- Prevents double token calculation for better performance
Display:
- Changed emoji from 📊 to 🔢 for Token Count Tree
- Updated title from "Token Count Summary" to "Token Count Tree"
Tests:
- Renamed and updated test files to match new structure
- Updated tests to work with new printTokenCountTree function signature
- All tests pass with new implementation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add truncateBase64 configuration option (default: true)
- Truncate base64 data strings to 32 characters + "..."
- Add --no-truncate-base64 CLI option
- Add unit tests for truncateBase64Content function
- Update documentation in README and website
This feature helps reduce token count by automatically truncating long
base64-encoded data (like embedded images) in the output, while preserving
the beginning of the data for identification purposes.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add support for .jsonc config files alongside existing .json5 and .json
- Implement priority order: repomix.config.json5 → repomix.config.jsonc → repomix.config.json
- Update config file discovery for both local and global configurations
- Add comprehensive tests for JSONC support and priority ordering
- JSON5 parser already supports JSONC format (JSON with comments)
Fixes#618
Co-authored-by: yamadashy <yamadashy@users.noreply.github.com>
- Replace JSON.parse with JSON5.parse for configuration file loading
- Update tests to cover JSON5 features (comments, trailing commas)
- Update documentation to reflect JSON5 support
- Add json5 package as a dependency