Skip to content

Fix local HTML file routing in open wrapper - #684

Merged
lawrencecchen merged 5 commits into
mainfrom
task-html-files-arent-viewable-in-cmux-browser
Mar 1, 2026
Merged

lawrencecchen merged 5 commits into
mainfrom
task-html-files-arent-viewable-in-cmux-browser

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Feb 28, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • route local .html/.htm targets from the terminal open wrapper to cmux browser open (plain paths and file:// URLs)
  • preserve pass-through behavior for non-file schemes (for example ftp: and mailto:)
  • add regression tests for local HTML routing, non-file scheme pass-through, and no-python3 URL encoding fallback

Testing

  • bash -n Resources/bin/open
  • python3 tests/test_open_wrapper.py (pass)
  • ./scripts/reload.sh --tag html-files-browser (build + launch succeeded)

Issues

  • Related task: "html files aren't viewable in cmux browser. fix it and write tests for it"

Summary by CodeRabbit

  • New Features

    • Embedded browser now supports loading local file:// HTML pages in-app and treats file URLs as navigable content.
    • Routing updated to classify inputs into in-app targets vs passthrough, converting valid local HTML paths to file:// targets.
    • Whitelist checks now apply only to HTTP URLs; failed in-app targets and passthroughs fall back to system open.
  • Tests

    • Added tests and a regression verifying local HTML routing, file-URL handling, passthrough cases, and Python fallback behavior.

@vercel

vercel Bot commented Feb 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Mar 1, 2026 3:06am

@coderabbitai

coderabbitai Bot commented Feb 28, 2026 •

Copy link
Copy Markdown

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

📥 Commits

Reviewing files that changed from the base of the PR and between bd29249 and 8284925.

📒 Files selected for processing (4)
  • Resources/bin/open
  • Sources/Panels/BrowserPanel.swift
  • cmuxTests/CmuxWebViewKeyEquivalentTests.swift
  • tests/test_open_wrapper.py
 _____________________________________________________________
< Please stop using global state like it's a communal fridge. >
 -------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).

✏️ Tip: You can disable in-progress messages and the fortune message in your review settings.

📝 Walkthrough

Walkthrough

Adds local file and file URL support across the open wrapper and embedded browser: new URL/path helper functions, path-to-file-URL conversion (with Python fallback and manual encoding), revised routing to classify cmux targets vs passthrough args, and tests plus browser changes to allow file:// navigations.

Changes

Cohort / File(s) Summary
Open wrapper helpers & routing
Resources/bin/open
Added is_file_url(), has_uri_scheme(), is_html_extension(), file_url_points_to_html(), path_to_file_url_without_python(), path_to_file_url(). Implemented path→file URL conversion (Python fallback), manual encoding, host normalization, replaced urls with cmux_targets and passthrough_args, updated routing, whitelist checks for HTTP only, and failed URL accumulation.
Tests — open wrapper
tests/test_open_wrapper.py
Extended run_wrapper() with local_files and python_bin; create local HTML fixtures, set/clear CMUX_OPEN_WRAPPER_PYTHON3, run wrapper with cwd set. Added tests: local HTML routing, file URL handling, no-Python fallback, non-file-scheme passthrough, mailto passthrough, local non-HTML passthrough.
Embedded browser — navigation
Sources/Panels/BrowserPanel.swift
Added file to embedded navigation schemes, implemented browserReadAccessURL and browserLoadRequest to load local file URLs via loadFileURL, and updated resolve logic to accept file:// URLs with non-empty paths. Replaced direct webView.load calls with browserLoadRequest where applicable.
Unit tests — browser navigation
cmuxTests/CmuxWebViewKeyEquivalentTests.swift
Added tests for resolving file scheme as navigable, rejecting non-web/non-file schemes, and read-access URL behavior (parent directory vs directory). Updated embedded-schemes test to include file variants asserting in-webview handling.
Integration test — browser file load
tests_v2/test_browser_file_url_load.py
New regression test that opens a cmux browser surface, navigates to a local file:// HTML file, asserts title/body content and that the browser URL remains a file:// URL.
Manifest / metadata
Manifest (lines changed)
Large diff footprint (+155/-12) reflecting added helpers, tests, routing changes and new test file.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/Caller
    participant Wrapper as Open Wrapper
    participant Router as Routing Logic
    participant Cmux as cmux Browser
    participant SysOpen as system_open

    User->>Wrapper: invoke with arguments
    Wrapper->>Router: parse args, normalize hosts, convert local paths to file://
    Router->>Router: classify into cmux_targets, passthrough_args, failed_urls
    alt cmux_targets present AND passthrough_args empty AND failed_urls empty
        Router->>Cmux: open cmux_targets
        Cmux->>Cmux: embed/open targets (http(s) or file://)
    else
        Router->>SysOpen: fallback with passthrough_args + failed_urls + remaining args
        SysOpen->>SysOpen: system open handling
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hop through paths and stitch a clue,
file:// pages come into view,
I nudge wrappers, cmux hears the call,
Some go in-app, some to the wall,
A rabbit routes them one and all. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.57% 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 summarizes the main change: enabling local HTML files to be routed through the cmux browser via the open wrapper, which aligns with the primary objective and all file modifications.

✏️ 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
  • Commit unit tests in branch task-html-files-arent-viewable-in-cmux-browser

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

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

Copy link
Copy Markdown

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: d7059c45dd

ℹ️ 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".

Comment thread Resources/bin/open Outdated
Comment on lines +371 to +373
elif is_html_extension "$arg"; then
if local_file_url="$(path_to_file_url "$arg")"; then
cmux_targets+=("$local_file_url")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Restrict .html interception to actual local file paths

The new is_html_extension branch converts any argument ending in .html/.htm into a file:// target, even when the input is not a local path (for example example.com/report.html). That means these no-scheme web links are now routed to cmux browser open file:///... instead of being passed through to /usr/bin/open as before, so users/scripts that call open with host/path-style URLs will open a non-existent local file. Please gate this conversion on local-path conditions (e.g., existing path or explicit path prefix) before rewriting.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Feb 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR enhances the open wrapper to route local HTML files to cmux's browser, completing support for HTML file viewing within cmux.

Major changes:

  • Local .html/.htm files (plain paths and file:// URLs) now route to cmux browser open
  • Non-file URI schemes (ftp:, mailto:, etc.) correctly pass through to system open
  • Path-to-URL conversion includes manual bash implementation for environments without python3
  • URL encoding properly handles spaces and special characters in filenames
  • Comprehensive test coverage for all new routing scenarios and edge cases

Implementation highlights:

  • Argument classification logic distinguishes between cmux targets (HTTP/HTTPS URLs, local HTML files) and passthrough args (non-HTML files, non-file schemes)
  • Dual implementation strategy: uses Python's pathlib when available, falls back to bash-only URL encoding
  • Whitelist checks only apply to HTTP/HTTPS URLs, not local file:// URLs

Confidence Score: 5/5

  • This PR is safe to merge with no identified risks
  • Score reflects clean implementation with defensive programming, comprehensive test coverage (6 new test cases), fallback handling for missing dependencies, and successful execution of existing test suite
  • No files require special attention

Important Files Changed

Filename Overview
Resources/bin/open Added local HTML file routing logic with file:// URL conversion, fallback bash implementation for path encoding when python3 is unavailable, and proper scheme detection for pass-through behavior
tests/test_open_wrapper.py Added comprehensive regression tests for local HTML routing, file:// URL handling, non-file scheme pass-through, and no-python fallback scenarios

Last reviewed commit: d7059c4

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
tests/test_open_wrapper.py (1)

322-332: Add a no-Python file:// regression to cover the fallback parser path.

Current no-Python coverage validates local path conversion, but not file://... HTML detection without Python. Adding that case would lock behavior for the shell fallback path.

Also applies to: 334-361

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

In `@tests/test_open_wrapper.py` around lines 322 - 332, Add a regression test
that exercises the shell fallback parser path for file:// HTML detection by
expanding or duplicating the existing test_file_url_html_routes_to_cmux to run
with the "no-Python" scenario; specifically, invoke run_wrapper with a
file://... .html URL, the same intercept_setting and whitelist args used here,
and assert that exit code is 0, system open (open_log) is empty, and cmux_log
contains the expected "browser open {url}" entry, so the fallback parser path
(used when Python is unavailable) is validated; locate and modify the test
function test_file_url_html_routes_to_cmux and/or the adjacent tests that call
run_wrapper to add this case.
Resources/bin/open (1)

213-236: Consider falling back to shell conversion if Python conversion fails.

At Line 232, any Python conversion failure exits without trying path_to_file_url_without_python, even though a fallback exists. Using fallback on Python failure would make conversion more robust.

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

In `@Resources/bin/open` around lines 213 - 236, The Python conversion in
path_to_file_url currently returns immediately after invoking the here-doc,
preventing fallback; change the control flow so that after running the
"$PYTHON3_BIN" block you check its exit status and if it failed (non-zero) call
path_to_file_url_without_python "$raw" instead of returning; ensure you still
propagate success (return 0) when Python succeeds and propagate the non-zero
exit code from the shell fallback when Python fails, referencing the
path_to_file_url and path_to_file_url_without_python functions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Resources/bin/open`:
- Around line 155-157: The non-Python branch currently calls is_html_extension
on the full URL (variable without_query), which misclassifies file:// URLs that
have a host but no path (e.g., file://example.html). Update the logic so that
when the URL has the file:// scheme you strip the scheme and any authority/host
portion before calling is_html_extension: remove the leading "file://" from
without_query, then if the remainder starts with "//" drop the authority up to
the next "/" (or treat as empty path if no "/" exists), and finally call
is_html_extension on that resulting path string instead of the original
without_query.

---

Nitpick comments:
In `@Resources/bin/open`:
- Around line 213-236: The Python conversion in path_to_file_url currently
returns immediately after invoking the here-doc, preventing fallback; change the
control flow so that after running the "$PYTHON3_BIN" block you check its exit
status and if it failed (non-zero) call path_to_file_url_without_python "$raw"
instead of returning; ensure you still propagate success (return 0) when Python
succeeds and propagate the non-zero exit code from the shell fallback when
Python fails, referencing the path_to_file_url and
path_to_file_url_without_python functions.

In `@tests/test_open_wrapper.py`:
- Around line 322-332: Add a regression test that exercises the shell fallback
parser path for file:// HTML detection by expanding or duplicating the existing
test_file_url_html_routes_to_cmux to run with the "no-Python" scenario;
specifically, invoke run_wrapper with a file://... .html URL, the same
intercept_setting and whitelist args used here, and assert that exit code is 0,
system open (open_log) is empty, and cmux_log contains the expected "browser
open {url}" entry, so the fallback parser path (used when Python is unavailable)
is validated; locate and modify the test function
test_file_url_html_routes_to_cmux and/or the adjacent tests that call
run_wrapper to add this case.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7916b2d and d7059c4.

📒 Files selected for processing (2)
  • Resources/bin/open
  • tests/test_open_wrapper.py

Comment thread Resources/bin/open Outdated

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

Copy link
Copy Markdown

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: 0e77dfc80e

ℹ️ 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".

Comment thread Resources/bin/open Outdated
Comment on lines +371 to +373
elif is_html_extension "$arg"; then
if local_file_url="$(path_to_file_url "$arg")"; then
cmux_targets+=("$local_file_url")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Gate .html rewrites to real local paths

The .html fallback currently rewrites any non-schemed token ending in .html to a file:// URL, so host/path-style inputs like example.com/report.html are treated as local files and sent to cmux browser open file:///... instead of being passed through to system open. This is a behavior regression for scripts/users that rely on no-scheme web targets, and I verified the current wrapper produces file:///tmp/.../example.com/report.html for that input.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@Sources/Panels/BrowserPanel.swift`:
- Around line 406-408: The current fallback that returns URL(fileURLWithPath:
"/") when parent.path.isEmpty broadens file read scope; update the validation
around allowingReadAccessTo so you first confirm the URL is a file URL and has
an absolute path (use url.isFileURL && url.path.hasPrefix("/")), and if
parent.path.isEmpty do NOT return root—return nil or propagate an error/invalid
result to the caller so access is denied; apply the same fix where parent/path
fallback is used (including the code near allowingReadAccessTo and the block
around parent.path.isEmpty).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 127b383 and bd29249.

📒 Files selected for processing (3)
  • Sources/Panels/BrowserPanel.swift
  • cmuxTests/CmuxWebViewKeyEquivalentTests.swift
  • tests_v2/test_browser_file_url_load.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmuxTests/CmuxWebViewKeyEquivalentTests.swift

Comment thread Sources/Panels/BrowserPanel.swift Outdated
@lawrencecchen
lawrencecchen merged commit 838d1b0 into main Mar 1, 2026
7 of 9 checks passed
@lawrencecchen
lawrencecchen deleted the task-html-files-arent-viewable-in-cmux-browser branch March 1, 2026 03:08

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

Copy link
Copy Markdown

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: 8284925687

ℹ️ 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".

Comment thread Resources/bin/open
Comment on lines +155 to +158
parts = urlsplit(value)
path = unquote(parts.path or "")
lower = path.lower()
if lower.endswith(".html") or lower.endswith(".htm"):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject non-local file:// hosts in HTML routing

file_url_points_to_html only checks the parsed path suffix and never validates the file URL host, so inputs like file://example.com/report.html are now classified as local HTML and routed to cmux browser open instead of /usr/bin/open. In this commit, resolveBrowserNavigableURL also accepts file URLs based on path alone, so hosted file URLs can be misinterpreted as local paths (for example /report.html), breaking UNC/hosted file links that previously opened through the system handler. Please require an empty/localhost file host before treating a file:// target as a local HTML file.

Useful? React with 👍 / 👎.

0xble added a commit to 0xble/cmux that referenced this pull request Mar 7, 2026
bn-l pushed a commit to bn-l/cmux that referenced this pull request Apr 3, 2026
* Route local HTML open targets to cmux browser

* Keep file:// omnibar navigation inside cmux browser

* Load local file URLs via WKWebView file API

* Add browser regression test for local file URL loads

* Address PR feedback on local HTML and file URL handling

This branch was successfully deployed

1 active deployment
Preview — 82849256 Deployed Mar 1, 2026 by vercel[bot]
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.

1 participant