Skip to content

fix(hooks): allow tmux-wrapped dev server commands#321

Merged
affaan-m merged 2 commits intoaffaan-m:mainfrom
zzzhizhia:fix/tmux-dev-hook
Mar 7, 2026
Merged

fix(hooks): allow tmux-wrapped dev server commands#321
affaan-m merged 2 commits intoaffaan-m:mainfrom
zzzhizhia:fix/tmux-dev-hook

Conversation

@zzzhizhia
Copy link
Contributor

@zzzhizhia zzzhizhia commented Mar 3, 2026

Summary

  • The PreToolUse hook that blocks direct dev server execution also incorrectly blocks tmux-wrapped commands like tmux new-session -d -s dev '...'
  • The regex matches the dev server pattern anywhere in the command string, causing false positives when the command is already wrapped in tmux
  • Added a !/^\s*tmux\b/.test(cmd) check to skip blocking when the command starts with tmux

Test plan

  • Direct dev server command → blocked (correct, unchanged behavior)
  • tmux-wrapped dev server command → allowed (fixed)

Summary by cubic

Allow tmux-wrapped dev servers while still blocking direct runs. We split commands with a quote- and escape-aware parser and exempt tmux launcher subcommands.

  • Bug Fixes
    • Fix redirection handling (&>, >&, 2>&1) and escaped quotes inside quoted strings.
    • Handle backslash escapes outside quotes (e.g., &&, ;) so they don’t split commands.
    • Extract the splitter to scripts/lib/shell-split.js, use it in both hooks, and add tests for edge cases.

Written for commit ea3f66d. Summary will update on new commits.

Summary by CodeRabbit

  • Refactor

    • Consolidated duplicated utility code across development hooks into a shared module.
  • Tests

    • Added comprehensive test coverage for command-line parsing functionality, including operator handling, quoting behavior, and edge cases.

Copilot AI review requested due to automatic review settings March 3, 2026 09:21
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change extracts a shared splitShellSegments utility function from two separate hook files into a dedicated module at scripts/lib/shell-split.js, eliminating code duplication while adding comprehensive test coverage for the shell command parsing logic.

Changes

Cohort / File(s) Summary
Hook Files Refactored
.cursor/hooks/before-shell-execution.js, scripts/hooks/pre-bash-dev-server-block.js
Replaced duplicate inline splitShellSegments implementations with imports from the shared scripts/lib/shell-split module. Logic and behavior remain unchanged.
Shell Parsing Utility
scripts/lib/shell-split.js
New module exporting splitShellSegments(command) function that tokenizes shell commands by operators (&&,
Test Suite
tests/lib/shell-split.test.js
Comprehensive test suite covering basic operator splitting, redirection handling, quote behavior, escaped characters, and real-world scenarios including tmux commands and background processes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A shell so split, in one place it does dwell,
No duplication in this coding spell,
Quotes and escapes, all handled with care,
One function to rule them—it's only fair!
Tests wrap it up, complete and so tight,

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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
Title check ✅ Passed The title 'fix(hooks): allow tmux-wrapped dev server commands' accurately summarizes the main objective of the PR: fixing the hooks to permit tmux-wrapped dev server commands while blocking direct invocations.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fa2785567e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

hooks/hooks.json Outdated
{
"type": "command",
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(process.platform!=='win32'&&/(npm run dev\\b|pnpm( run)? dev\\b|yarn dev\\b|bun run dev\\b)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}}catch{}console.log(d)})\""
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(process.platform!=='win32'&&!/^\\s*tmux\\b/.test(cmd)&&/(npm run dev\\b|pnpm( run)? dev\\b|yarn dev\\b|bun run dev\\b)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}}catch{}console.log(d)})\""

Choose a reason for hiding this comment

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

P2 Badge Don't bypass dev-server block on any tmux prefix

The new !/^\s*tmux\b/.test(cmd) guard exempts every command string that merely starts with tmux, so a command like tmux ls && npm run dev now passes even though the dev server still runs outside tmux. This weakens the hook’s stated enforcement (“Dev server must run in tmux for log access”) and introduces an easy false negative compared with the previous behavior.

Useful? React with 👍 / 👎.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@hooks/hooks.json`:
- Line 10: The current prefix check in the "command" string (the long node -e
snippet in hooks.json) treats any command that starts with "tmux" as a safe
bypass and thus allows cases like "tmux ls && npm run dev"; change the check to
only allow tmux when it is used as a launcher that actually contains the dev
payload (e.g., tmux new, new-session, new-window, split-window variants that
include the dev command). Locate the "command" value in hooks.json and replace
the loose /^\\s*tmux\\b/ test with a stricter pattern that verifies both a
launcher verb (new, new-session, new-window, split-window) immediately after
tmux and that the rest of the tmux invocation includes one of the dev commands
(npm run dev | pnpm[ run]? dev | yarn dev | bun run dev), so only true
tmux-launched dev servers bypass the block.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ada4cd7 and fa27855.

📒 Files selected for processing (1)
  • hooks/hooks.json

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the Claude Code PreToolUse Bash hook to stop falsely blocking dev-server commands when they’re already wrapped by tmux, aligning the hook’s behavior with the intended “run dev server via tmux” workflow.

Changes:

  • Add an early check to skip dev-server blocking when the command starts with tmux.
  • Preserve existing dev-server blocking behavior for non-tmux commands.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

hooks/hooks.json Outdated
{
"type": "command",
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(process.platform!=='win32'&&/(npm run dev\\b|pnpm( run)? dev\\b|yarn dev\\b|bun run dev\\b)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}}catch{}console.log(d)})\""
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(process.platform!=='win32'&&!/^\\s*tmux\\b/.test(cmd)&&/(npm run dev\\b|pnpm( run)? dev\\b|yarn dev\\b|bun run dev\\b)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}}catch{}console.log(d)})\""
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

This tmux-prefix exemption is added in the Claude PreToolUse hook, but the Cursor hook implementation still blocks tmux-wrapped dev server commands (see .cursor/hooks/before-shell-execution.js, used by .cursor/hooks.json). If both hook systems are used in this repo, consider applying the same tmux-detection change there as well to keep behavior consistent and avoid the false-positive persisting in Cursor.

Suggested change
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(process.platform!=='win32'&&!/^\\s*tmux\\b/.test(cmd)&&/(npm run dev\\b|pnpm( run)? dev\\b|yarn dev\\b|bun run dev\\b)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}}catch{}console.log(d)})\""
"command": "node -e \"let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const i=JSON.parse(d);const cmd=i.tool_input?.command||'';if(process.platform!=='win32'&&!process.env.TMUX&&!/^\\s*tmux\\b/.test(cmd)&&/(npm run dev\\b|pnpm( run)? dev\\b|yarn dev\\b|bun run dev\\b)/.test(cmd)){console.error('[Hook] BLOCKED: Dev server must run in tmux for log access');console.error('[Hook] Use: tmux new-session -d -s dev \\\"npm run dev\\\"');console.error('[Hook] Then: tmux attach -t dev');process.exit(2)}}catch{}console.log(d)})\""

Copilot uses AI. Check for mistakes.
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="hooks/hooks.json">

<violation number="1" location="hooks/hooks.json:10">
P2: The tmux prefix check is too broad — any command starting with `tmux` bypasses the block, even when the dev server isn't actually wrapped in a tmux session (e.g., `tmux ls; npm run dev`). Consider matching only session-creation subcommands like `tmux new-session` or `tmux new` to ensure the dev server is genuinely running inside tmux.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".cursor/hooks/before-shell-execution.js">

<violation number="1" location=".cursor/hooks/before-shell-execution.js:10">
P2: Regex bypass: `.*` in `tmuxDevRe` matches across shell operators (`;`, `&&`, `||`), so a chained command like `tmux new-session -d 'echo'; npm run dev` is incorrectly allowed even though the dev server runs **outside** tmux.

Consider requiring the dev command to appear within a quoted argument to the tmux subcommand, e.g. by replacing the last `.*` with a pattern that expects a quote before the dev command:</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.cursor/hooks/before-shell-execution.js:
- Around line 10-11: The current check uses devRe and tmuxDevRe against the
whole cmd string so chained commands can bypass detection; update the logic in
before-shell-execution.js to split cmd into individual segments using a
separator regex (e.g. split on /\s*(?:&&|\|\||;)\s*/) and then for each segment
test if devRe.test(segment) and not tmuxDevRe.test(segment) — if any segment
matches that condition, treat it as a non-tmux dev invocation and block/handle
accordingly; refer to the existing tmuxDevRe, devRe, and cmd identifiers when
locating and replacing the single-string test with the per-segment loop.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa27855 and f6bbd8c.

📒 Files selected for processing (2)
  • .cursor/hooks/before-shell-execution.js
  • hooks/hooks.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • hooks/hooks.json

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

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

Automated review: checks are failing. Please fix failures before review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".cursor/hooks/before-shell-execution.js">

<violation number="1" location=".cursor/hooks/before-shell-execution.js:12">
P1: Naive splitting by `&&`/`||`/`;` doesn't respect shell quoting, causing a regression for common tmux patterns like `tmux new-session -d -s dev "cd /app && npm run dev"`. The `&&` inside the quoted tmux argument is treated as a shell operator, producing a bare `npm run dev"` segment that gets incorrectly blocked.

Add a full-command `tmuxDevRe` check as an escape hatch so that quoted compound inner commands are still recognized as tmux-wrapped:</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Owner

@affaan-m affaan-m left a comment

Choose a reason for hiding this comment

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

Automated review: checks are failing. Please fix failures before review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="hooks/hooks.json">

<violation number="1" location="hooks/hooks.json:10">
P2: The new quote-aware splitter mis-parses escaped quotes, which can wrongly block valid tmux-wrapped dev commands (false positive). Handle escaped quotes before toggling quote state.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.cursor/hooks/before-shell-execution.js:
- Around line 18-20: The parser only treats '&&' and '||' as segment separators
and misses single '&', allowing commands like '... & npm run dev' to be one
segment; update the splitting logic around variables s, i, c, sq, dq, segs, cur
so that a lone '&' (when not part of '&&') is treated as a separator too, and
adjust the increment logic so you only skip the next character when you matched
a two-character operator ('&&' or '||') rather than for single '&'; ensure the
segment push remains segs.push(cur.trim()); cur = '' and that you continue
parsing afterward.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f192e60 and 8820098.

📒 Files selected for processing (4)
  • .cursor/hooks/before-shell-execution.js
  • hooks/hooks.json
  • scripts/hooks/doc-file-warning.js
  • scripts/lib/project-detect.js

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
hooks/hooks.json (1)

10-10: Consider centralizing this parser/gating logic in one shared script.

The same splitter/regex behavior now exists here and in .cursor/hooks/before-shell-execution.js; reusing one implementation would reduce drift risk.

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

In `@hooks/hooks.json` at line 10, The inline node -e hook contains duplicated
parsing/gating logic (the sq splitter function and regexes devRe and tmuxDevRe);
extract that logic into a single reusable module that exports the splitter (sq)
and a gating function (e.g., shouldBlockDevCommand(command):boolean) and replace
the inline script in the "command" string (and the duplicate in
.cursor/hooks/before-shell-execution.js) to require/execute the shared module so
both places call the same implementation (use the same exported names like sq,
devRe, tmuxDevRe or a single shouldBlockDevCommand helper to locate and reuse
the exact behavior).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@hooks/hooks.json`:
- Line 10: The inline node -e hook contains duplicated parsing/gating logic (the
sq splitter function and regexes devRe and tmuxDevRe); extract that logic into a
single reusable module that exports the splitter (sq) and a gating function
(e.g., shouldBlockDevCommand(command):boolean) and replace the inline script in
the "command" string (and the duplicate in
.cursor/hooks/before-shell-execution.js) to require/execute the shared module so
both places call the same implementation (use the same exported names like sq,
devRe, tmuxDevRe or a single shouldBlockDevCommand helper to locate and reuse
the exact behavior).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8820098 and 026af41.

📒 Files selected for processing (2)
  • .cursor/hooks/before-shell-execution.js
  • hooks/hooks.json

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="hooks/hooks.json">

<violation number="1" location="hooks/hooks.json:10">
P2: The new single-`&` split rule incorrectly treats redirection operators (`2>&1`, `&>`, `|&`) as command separators, so command segmentation is wrong for valid shell commands.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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
Owner

affaan-m commented Mar 6, 2026

Hey @zzzhizhia! This PR has a merge conflict with main. Could you please rebase when you get a chance? Thanks!

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

Copy link
Owner

@affaan-m affaan-m left a comment

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.

…d module

- Fix single & incorrectly splitting redirection operators (&>, >&, 2>&1)
- Fix escaped quotes (\", \') not being handled inside quoted strings
- Extract splitShellSegments into shared scripts/lib/shell-split.js
  to eliminate duplication between hooks.json, before-shell-execution.js,
  and pre-bash-dev-server-block.js
- Add comprehensive tests for shell splitting edge cases
@zzzhizhia zzzhizhia force-pushed the fix/tmux-dev-hook branch from 437e0b3 to d1238e0 Compare March 6, 2026 08:33
@zzzhizhia
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.cursor/hooks/before-shell-execution.js:
- Around line 35-41: The current catch blocks in before-shell-execution.js (the
inner catch after parsing/stdin and the final .catch(() => process.exit(0)))
silently swallow errors and exit 0; change them to fail fast and emit clear
errors instead: when the parser/stdin handling fails (the inner catch that
currently does noop) log a descriptive error to stderr (including the exception
message) and exit with a non-zero code, and replace the final .catch handler to
print a clear error message and exit non-zero rather than success. Target the
anonymous catch blocks surrounding the parse/stdin logic and the terminal
promise .catch and ensure they return a non-zero process.exit and include the
error details.

In `@scripts/lib/shell-split.js`:
- Around line 16-33: The splitter treats backslash-escaped operator characters
only when inside quotes, so sequences like \&& or \; outside quotes are still
parsed as separators; update shell-split logic to handle backslash escapes
outside quotes by adding the same escape-handling branch used inside the quoted
block (the if (ch === '\\' && i + 1 < command.length) { current += ch +
command[i + 1]; i++; continue; } pattern) before the separator/operator checks
so escaped separators are appended to current instead of splitting; modify the
code around variables command, ch, i, current and quote handling to run that
escape branch when quote is null, and add a unit/integration test that asserts a
command like "tmux new-session -d bash -lc cd /app \\&\\& npm run dev" does not
split on the escaped && outside quotes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f2827942-408c-40c7-b048-c7d300637180

📥 Commits

Reviewing files that changed from the base of the PR and between 026af41 and d1238e0.

📒 Files selected for processing (4)
  • .cursor/hooks/before-shell-execution.js
  • scripts/hooks/pre-bash-dev-server-block.js
  • scripts/lib/shell-split.js
  • tests/lib/shell-split.test.js

Escaped operators like \&& and \; outside quotes were still being
treated as separators. Add escape handling for unquoted context.
@zzzhizhia zzzhizhia requested a review from affaan-m March 6, 2026 09:15
@affaan-m affaan-m merged commit 177dd36 into affaan-m:main Mar 7, 2026
39 checks passed
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.

3 participants