Skip to content

feat(hooks): auto-detect formatter in post-edit hook (Biome/Prettier)#252

Merged
affaan-m merged 1 commit into
affaan-m:mainfrom
pythonstrup:feat/auto-detect-formatter
Feb 24, 2026
Merged

feat(hooks): auto-detect formatter in post-edit hook (Biome/Prettier)#252
affaan-m merged 1 commit into
affaan-m:mainfrom
pythonstrup:feat/auto-detect-formatter

Conversation

@pythonstrup

@pythonstrup pythonstrup commented Feb 20, 2026

Copy link
Copy Markdown
Contributor

Description

The post-edit-format hook was hardcoded to use Prettier. Projects using
Biome had their code silently reformatted with Prettier defaults (e.g.
single quotes → double quotes), causing unexpected diffs.

This change makes the hook auto-detect the project's formatter by walking
up the directory tree from the edited file and checking for config files:

  • biome.json / biome.jsonc → Biome
  • .prettierrc / prettier.config.* → Prettier
  • Neither found → skip formatting silently

Type of Change

  • feat: New feature

Checklist

  • Tests pass locally (node tests/run-all.js)
  • Validation scripts pass
  • Follows conventional commits format
  • Updated relevant documentation

Summary by CodeRabbit

Release Notes

  • New Features
    • Auto-format hooks now support both Biome and Prettier, automatically detecting and applying whichever formatter your project is configured to use when formatting JavaScript and TypeScript files after edits.

The post-edit-format hook was hardcoded to use Prettier. Projects using
Biome had their code reformatted with Prettier defaults (e.g. double
quotes overwriting single quotes).

Now the hook walks up from the edited file to find the project root,
then checks for config files:
- biome.json / biome.jsonc → runs Biome
- .prettierrc / prettier.config.* → runs Prettier
- Neither found → skips formatting silently
@coderabbitai

coderabbitai Bot commented Feb 20, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

The post-edit hook now automatically detects and uses either Biome or Prettier for code formatting, replacing a hardcoded Prettier dependency. The description in hooks.json was updated to reflect this auto-detection capability. Detection logic checks for formatter configuration files in the project root.

Changes

Cohort / File(s) Summary
Documentation
hooks/hooks.json
Updated hook description to indicate auto-detection of Biome or Prettier instead of explicit Prettier usage.
Formatter Detection Logic
scripts/hooks/post-edit-format.js
Added findProjectRoot(), detectFormatter(), and getFormatterCommand() functions to dynamically identify the available formatter and construct appropriate npx commands. Refactored main flow to detect formatter before execution, with fallback behavior for missing formatters.

Sequence Diagram(s)

sequenceDiagram
    participant Hook as Post-Edit Hook
    participant FS as File System
    participant Detect as Formatter Detector
    participant Cmd as Command Builder
    participant Exec as Executor

    Hook->>FS: findProjectRoot(startDir)
    FS-->>Hook: projectRoot path
    Hook->>Detect: detectFormatter(projectRoot)
    Detect->>FS: Check for biome.json/biome.jsonc
    Detect->>FS: Check for Prettier config files
    FS-->>Detect: formatter name or null
    Detect-->>Hook: formatter type
    alt Formatter Found
        Hook->>Cmd: getFormatterCommand(formatter, filePath)
        Cmd-->>Hook: npx command string
        Hook->>Exec: Execute command
        Exec-->>Hook: success/failure
    else No Formatter
        Hook-->>Hook: Non-blocking skip
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A formatter's tale, both Biome and Prettier too,
Auto-detect the magic, let the best tool shine through,
No more hardcoded paths, just wisdom and grace,
Hopping through projects with flexible pace! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding auto-detection of formatters (Biome or Prettier) to the post-edit hook, which is the primary objective of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/hooks/post-edit-format.js (2)

36-60: detectFormatter misses two valid Prettier config locations

  1. package.json "prettier" key — a commonly used inline Prettier config that the detection loop skips entirely.
  2. Workspace-level configs in monorepos — detection only runs against the directory containing the nearest package.json. If biome.json or .prettierrc lives at the workspace root (one level above the package), it won't be found. Extending the check to walk up from projectRoot until a formatter config is found (mirroring how findProjectRoot walks up for package.json) would cover this gap.
♻️ Proposed fix: add `package.json` prettier-key check
 function detectFormatter(projectRoot) {
   const biomeConfigs = ['biome.json', 'biome.jsonc'];
   for (const cfg of biomeConfigs) {
     if (fs.existsSync(path.join(projectRoot, cfg))) return 'biome';
   }

   const prettierConfigs = [
     '.prettierrc',
     '.prettierrc.json',
     '.prettierrc.js',
     '.prettierrc.cjs',
     '.prettierrc.mjs',
     '.prettierrc.yml',
     '.prettierrc.yaml',
     '.prettierrc.toml',
     'prettier.config.js',
     'prettier.config.cjs',
     'prettier.config.mjs',
   ];
   for (const cfg of prettierConfigs) {
     if (fs.existsSync(path.join(projectRoot, cfg))) return 'prettier';
   }
+
+  // Check package.json for an inline "prettier" key
+  const pkgPath = path.join(projectRoot, 'package.json');
+  if (fs.existsSync(pkgPath)) {
+    try {
+      const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
+      if (pkg.prettier) return 'prettier';
+    } catch {}
+  }

   return null;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/hooks/post-edit-format.js` around lines 36 - 60, detectFormatter
currently only checks local biomeConfigs and prettierConfigs files and doesn't
detect a "prettier" key inside package.json nor search parent directories;
update detectFormatter to (1) when scanning for Prettier, also read package.json
at the current directory and return 'prettier' if it contains a "prettier" key,
and (2) instead of only checking projectRoot, walk up parent directories (like
findProjectRoot does) until filesystem root to look for biomeConfigs,
prettierConfigs and package.json "prettier" key so workspace-level configs are
detected; keep the existing return values ('biome' or 'prettier') and null
fallback.

78-90: Relative filePath passed to formatter causes silent failures when projectRoot differs from process CWD

Line 80 resolves the path to locate projectRoot, but the original (potentially relative) filePath is passed to getFormatterCommand on line 82. When execFileSync runs with cwd: projectRoot, a relative path is resolved against projectRoot—not the process CWD—targeting the wrong path.

Example (monorepo, process CWD = /workspace):

  • filePath: packages/app/src/index.ts (relative)
  • projectRoot: /workspace/packages/app
  • Formatter receives: prettier --write packages/app/src/index.ts with cwd=/workspace/packages/app
  • Effective path: /workspace/packages/app/packages/app/src/index.ts

Similar defensive path resolution is already used in post-edit-typecheck.js (line 32), confirming that relative paths need handling.

♻️ Proposed fix: resolve filePath once and use it throughout
     if (filePath && /\.(ts|tsx|js|jsx)$/.test(filePath)) {
       try {
-        const projectRoot = findProjectRoot(path.dirname(path.resolve(filePath)));
+        const absFilePath = path.resolve(filePath);
+        const projectRoot = findProjectRoot(path.dirname(absFilePath));
         const formatter = detectFormatter(projectRoot);
-        const cmd = getFormatterCommand(formatter, filePath);
+        const cmd = getFormatterCommand(formatter, absFilePath);

         if (cmd) {
           execFileSync(cmd.bin, cmd.args, {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/hooks/post-edit-format.js` around lines 78 - 90, The formatter is
being passed the original (possibly relative) filePath which, when execFileSync
runs with cwd set to projectRoot, causes wrong paths; resolve filePath to an
absolute path once (e.g., using path.resolve with the original filePath) after
computing projectRoot (or immediately) and then use that resolvedFilePath for
getFormatterCommand, for any args passed to execFileSync, and anywhere else
filePath is used (references: filePath, projectRoot, findProjectRoot,
detectFormatter, getFormatterCommand, execFileSync) so the formatter always
receives an absolute correct path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/hooks/post-edit-format.js`:
- Around line 36-60: detectFormatter currently only checks local biomeConfigs
and prettierConfigs files and doesn't detect a "prettier" key inside
package.json nor search parent directories; update detectFormatter to (1) when
scanning for Prettier, also read package.json at the current directory and
return 'prettier' if it contains a "prettier" key, and (2) instead of only
checking projectRoot, walk up parent directories (like findProjectRoot does)
until filesystem root to look for biomeConfigs, prettierConfigs and package.json
"prettier" key so workspace-level configs are detected; keep the existing return
values ('biome' or 'prettier') and null fallback.
- Around line 78-90: The formatter is being passed the original (possibly
relative) filePath which, when execFileSync runs with cwd set to projectRoot,
causes wrong paths; resolve filePath to an absolute path once (e.g., using
path.resolve with the original filePath) after computing projectRoot (or
immediately) and then use that resolvedFilePath for getFormatterCommand, for any
args passed to execFileSync, and anywhere else filePath is used (references:
filePath, projectRoot, findProjectRoot, detectFormatter, getFormatterCommand,
execFileSync) so the formatter always receives an absolute correct path.

@affaan-m affaan-m left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

@affaan-m

Copy link
Copy Markdown
Owner

Hey @pythonstrup! 👋 This PR has a merge conflict that needs to be resolved before it can be merged. Could you please rebase on main? Thanks!

@affaan-m affaan-m left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review: this PR has merge conflicts. Please rebase or resolve.

@affaan-m

Copy link
Copy Markdown
Owner

CI check requested - please rebase on latest main to trigger CI.

@affaan-m affaan-m merged commit f730fae into affaan-m:main Feb 24, 2026
2 checks passed
FrancescoRosciano pushed a commit to FRosciano-Mambo/everything-claude-code that referenced this pull request Jun 1, 2026
…matter

LGTM — Auto-detect formatter hook. Safe, well-structured.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants