Skip to content

Conversation

dsarno
Copy link
Collaborator

@dsarno dsarno commented Aug 14, 2025

Summary

Reduces accidental MCP client config rewrites and path churn. Always targets the stable, installed server directory by default, validates existing uv commands before preserving them, writes configs atomically, and fixes Linux config locations. Adds resilient detection to avoid flipping user-edited configs on refresh.

What changed

  • Don’t clobber existing working configs
    • Preserve an existing absolute command only if it’s actually uv (<path> --version starts with uv ).
    • Extract and validate existing --directory and keep it if it contains server.py.
    • Normalize args everywhere to: ["run", "--directory", "<serverSrc>", "server.py"].
    • Only write when something actually changed; writes are atomic (temp file + replace/move).
  • Prefer installed server; block PackageCache on Windows unless dev override
    • New resolver picks the installed path first; embedded path only if UnityMCP.UseEmbeddedServer = true.
    • On Windows, any \Library\PackageCache\... path is replaced by the installed path unless dev override is on.
    • Remembers last-known-good via UnityMCP.ServerSrc.
  • Safer uv resolution
    • Preserve validated existing command; otherwise resolve.
    • Windows WinGet shim probing order: LocalAppData Links → ProgramData Links → ProgramFiles Links (low priority).
  • Robust detection and comparisons
    • Cursor detection now extracts --directory and compares with normalized, case-correct path semantics (PathsEqual).
    • VSCode manual/auto configs use the new top-level servers.unityMCP schema with type: "stdio" and canonical args order.
  • Correct Linux config paths (XDG)
    • VSCode: ~/.config/Code/User/mcp.json (was macOS-style path).
    • Claude Desktop: ~/.config/Claude/claude_desktop_config.json.

Why

  • PackageCache is volatile; users were getting resets to hashed folders or paths with spaces.
  • Multiple uv.exe on Windows caused drift; WinGet Links are the most stable entrypoints.
  • Mid-write reads caused occasional malformed JSON; atomic writes prevent this.
  • Linux configs were silently written to the wrong locations; XDG fixes that.

Verification checklist

  • Windows (Cursor / VSCode / Windsurf)
    • If multiple uv.exe exist, the selected command is the WinGet Links shim when present.
    • Config shows canonical args: ["run","--directory","C:\\Users\\YOU\\AppData\\Local\\Programs\\UnityMCP\\UnityMcpServer\\src","server.py"].
    • Manual run of the exact command starts the server and blocks awaiting stdio.
    • Manual absolute command and --directory are preserved across restarts.
  • VSCode
    • Code/User/mcp.json uses the top-level servers schema and includes "type": "stdio".
  • Linux
    • VSCode config lives at ~/.config/Code/User/mcp.json.
    • Claude Desktop config lives at ~/.config/Claude/claude_desktop_config.json.

Notes

  • New/used EditorPrefs keys: UnityMCP.UvPath, UnityMCP.ServerSrc, UnityMCP.UseEmbeddedServer, UnityMCP.LockCursorConfig.
  • No public API changes; behavior is safer defaults with opt-in dev override.

Summary by CodeRabbit

  • New Features
    • None
  • Bug Fixes
    • Corrected Linux config paths for supported apps.
    • More reliable Windows UV discovery and validation.
    • Stable argument order for VSCode configuration.
    • Safer directory copy by skipping cache/symlink folders.
    • Improved server/source discovery and config change detection.
  • Documentation
    • Added Windows guide for UV path issues.
    • Added macOS guide for Claude CLI ICU errors and FAQs.
    • Updated manual instructions to match new argument format.
  • Refactor
    • Canonical path comparison, argument parsing, and incremental config writes.
  • Chores
    • Bumped version to 2.1.1 and added placeholder package.json.

dsarno added 2 commits August 13, 2025 17:46
…add ResolveServerSrc; block PackageCache unless dev override; canonical uv args
…etection; atomic writes; uv validation; WinGet Links ordering
Copy link
Contributor

coderabbitai bot commented Aug 14, 2025

Walkthrough

Adds Windows/macOS/Linux path handling updates for UV and MCP configs, refactors config write/merge logic with canonical args and validation, updates Linux config paths, skips certain directories during server copy, adds docs for Cursor/Claude troubleshooting, and bumps UnityMcpBridge version to 2.1.1 with a new empty package.json.

Changes

Cohort / File(s) Summary of changes
Documentation (Windows/macOS troubleshooting)
CursorHelp.md, claude-chunk.md
New guides for Windows UV path issues (Cursor/Windsurf/VSCode) and macOS Claude CLI ICU issues; includes fixes, commands, and verification steps.
Editor config workflow & path resolution
UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs
Reworks IsCursorConfigured; adds path/arg utilities; canonicalizes args to ["run","--directory",src,"server.py"]; robust WriteToConfig with format detection, change-detection, safe writes, UV validation, server source resolution, and Windows package-cache guard; updated instructions and checks.
Server installer and UV discovery
UnityMcpBridge/Editor/Helpers/ServerInstaller.cs
Uses RootFolder for macOS save location; adds skip list for recursive copies and skips symlinks; revises Windows FindUvPath candidates (favor per-user/shim, add Program Files, remove ProgramData fallback).
Linux config path updates
UnityMcpBridge/Editor/Data/McpClients.cs
Adjusts Linux paths for Claude Desktop and VSCode Copilot from Library/Application Support to ~/.config equivalents.
Package metadata
UnityMcpBridge/package.json, package.json
Bumps version to 2.1.1; adds root package.json with empty object.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UnityEditor as UnityMcpEditorWindow
  participant Resolver as ResolveServerSrc
  participant UV as Find/Validate UV
  participant FS as File System (mcp.json)

  User->>UnityEditor: Trigger Check/Write Config
  UnityEditor->>Resolver: Resolve server source
  Resolver-->>UnityEditor: serverSrc or error
  UnityEditor->>UV: ValidateUvBinarySafe(path) / FindUvPath()
  UV-->>UnityEditor: uvPath or error
  UnityEditor->>FS: Read existing config (VSCode or standard)
  UnityEditor->>UnityEditor: Build canonical args ["run","--directory",serverSrc,"server.py"]
  UnityEditor->>FS: Write temp and replace if command/args changed
  UnityEditor-->>User: Success or error message
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

I twitch my nose at paths that hide,
Hop-hop—UV now by my side.
Configs align in tidy rows,
Through temp writes, the river flows.
On mac and win, my trails are clear—
2.1.1, I thump with cheer! 🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 616d399 and 80d311e.

📒 Files selected for processing (1)
  • UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • UnityMcpBridge/Editor/Helpers/ServerInstaller.cs
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🔭 Outside diff range comments (3)
UnityMcpBridge/UnityMcpServer~/src/unity_connection.py (3)

104-112: send_command short-circuits on params=None, preventing ping and breaking connection verification.

The early return for None params blocks legitimate calls like ping (which require no params) and causes get_unity_connection to think a connection is valid without actually talking to Unity.

Either allow None params as {} or exempt ping from the guard. Minimal change:

-        if params is None:
-            # Return a fast, structured error that clients can display without hanging
-            return {"success": False, "error": "MCP call received with no parameters (client placeholder?)"}
+        if params is None and command_type != "ping":
+            # Return a fast, structured error that clients can display without hanging
+            return {"success": False, "error": "MCP call received with no parameters (client placeholder?)"}

241-247: Connection reuse check doesn’t actually verify connectivity; it ignores the ping result.

Because send_command may return a structured error without raising, the try/except path won’t catch a failed ping. Explicitly assert a pong.

-            result = _unity_connection.send_command("ping")
-            # If we get here, the connection is still valid
-            logger.debug("Reusing existing Unity connection")
-            return _unity_connection
+            result = _unity_connection.send_command("ping", {})
+            if isinstance(result, dict) and result.get("message") == "pong":
+                logger.debug("Reusing existing Unity connection")
+                return _unity_connection
+            else:
+                raise Exception("Ping failed")

262-267: Verify new connection with an explicit pong check.

Same issue as above: make sure the ping actually succeeds.

-        _unity_connection.send_command("ping")
-        logger.info("Successfully established new Unity connection")
-        return _unity_connection
+        resp = _unity_connection.send_command("ping", {})
+        if isinstance(resp, dict) and resp.get("message") == "pong":
+            logger.info("Successfully established new Unity connection")
+            return _unity_connection
+        else:
+            raise Exception("Ping did not return pong")
🧹 Nitpick comments (12)
package.json (1)

1-1: Mark the package as private to avoid accidental publish and add minimal metadata.

An empty package.json can be accidentally published or confuse tooling. Consider marking it private and add a minimal name to improve clarity.

-{}
+{
+  "name": "unity-mcp",
+  "private": true
+}
UnityMcpBridge/Editor/Data/McpClients.cs (1)

72-77: Optionally respect XDG_CONFIG_HOME for Linux users.

Some environments customize the config folder via XDG_CONFIG_HOME. You can fall back to ~/.config when it’s unset.

-                linuxConfigPath = Path.Combine(
-                    Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
-                    ".config",
-                    "Claude",
-                    "claude_desktop_config.json"
-                ),
+                linuxConfigPath = Path.Combine(
+                    Environment.GetEnvironmentVariable("XDG_CONFIG_HOME")
+                        ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config"),
+                    "Claude",
+                    "claude_desktop_config.json"
+                ),
-                linuxConfigPath = Path.Combine(
-                    Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
-                    ".config",
-                    "Code",
-                    "User",
-                    "mcp.json"
-                ),
+                linuxConfigPath = Path.Combine(
+                    Environment.GetEnvironmentVariable("XDG_CONFIG_HOME")
+                        ?? Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config"),
+                    "Code",
+                    "User",
+                    "mcp.json"
+                ),

Also applies to: 91-97

UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (3)

129-153: Avoid goto in directory traversal; simplify skip logic and improve readability.

The goto-based skip is unconventional in C#. You can replace it with early-continue checks and a HashSet for O(1) case-insensitive lookups.

-        private static readonly string[] _skipDirs = { ".venv", "__pycache__", ".pytest_cache", ".mypy_cache", ".git" };
+        private static readonly HashSet<string> _skipDirs = new(StringComparer.OrdinalIgnoreCase)
+        { ".venv", "__pycache__", ".pytest_cache", ".mypy_cache", ".git" };

         private static void CopyDirectoryRecursive(string sourceDir, string destinationDir)
         {
             Directory.CreateDirectory(destinationDir);

             foreach (string filePath in Directory.GetFiles(sourceDir))
             {
                 string fileName = Path.GetFileName(filePath);
                 string destFile = Path.Combine(destinationDir, fileName);
                 File.Copy(filePath, destFile, overwrite: true);
             }

             foreach (string dirPath in Directory.GetDirectories(sourceDir))
             {
                 string dirName = Path.GetFileName(dirPath);
-                foreach (var skip in _skipDirs)
-                {
-                    if (dirName.Equals(skip, StringComparison.OrdinalIgnoreCase))
-                        goto NextDir;
-                }
-                try { if ((File.GetAttributes(dirPath) & FileAttributes.ReparsePoint) != 0) continue; } catch { }
+                if (_skipDirs.Contains(dirName)) continue;
+                try
+                {
+                    if ((File.GetAttributes(dirPath) & FileAttributes.ReparsePoint) != 0) continue;
+                }
+                catch { /* ignore attribute read failures and proceed */ }
                 string destSubDir = Path.Combine(destinationDir, dirName);
                 CopyDirectoryRecursive(dirPath, destSubDir);
-            NextDir: ;
             }
         }

230-235: uv sync timeout may be too aggressive for cold installs.

A 60s timeout can be tight on first-time or cache-cold syncs. Consider extending to 180s or making it configurable via EditorPrefs.

-                if (!proc.WaitForExit(60000))
+                if (!proc.WaitForExit(180000))
                 {
                     try { proc.Kill(); } catch { }
                     Debug.LogError("uv sync timed out.");
                     return false;
                 }

If you’d like, I can wire this timeout to an EditorPrefs key UnityMCP.UvSyncTimeoutMs.


97-109: Unused helper method.

IsDirectoryWritable is not used. Either remove it or use it in GetSaveLocation/EnsureServerInstalled to preflight permissions.

claude-chunk.md (2)

10-17: Tighten language and address LanguageTool hint.

Minor text polish: tighten “Fix options” header and add a caution note for curl | bash.

-- Fix options (pick one)
+- Fix options (pick one)
+  - Note: Review scripts before executing, especially when piping curl to bash.

26-31: Add explicit NVM prerequisite hint.

Some users may not have NVM installed; a short note reduces friction.

   - Use NVM Node (avoids Homebrew ICU churn):
     ```bash
+    # If you don't have NVM installed:
+    # curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
+    # then restart your shell
     nvm install --lts
     nvm use --lts
     npm install -g @anthropic-ai/claude-code
     # Unity MCP → Claude Code → Choose Claude Location → ~/.nvm/versions/node/<ver>/bin/claude
     ```
UnityMcpBridge/UnityMcpServer~/src/unity_connection.py (2)

112-114: Harden access to config.max_retries.

If config lacks max_retries, this line will raise. Use getattr with a default.

-        attempts = max(config.max_retries, 5)
+        attempts = max(getattr(config, "max_retries", 5), 5)

206-231: Backoff variable computed but unused; unify the retry delay.

You compute backoff but then ignore it, using only jitter. Consider incorporating base_backoff into sleep_s.

-                    backoff = base_backoff * (2 ** attempt)
-                    # Decorrelated jitter multiplier
-                    jitter = random.uniform(0.1, 0.3)
+                    backoff = base_backoff * (2 ** attempt)
+                    # Decorrelated jitter multiplier
+                    jitter = random.uniform(0.1, 0.3)
...
-                    sleep_s = min(cap, jitter * (2 ** attempt))
+                    sleep_s = min(cap, backoff * jitter)
UnityMcpBridge/Editor/UnityMcpBridge.cs (1)

536-566: Verify big-endian byte order implementation.

The big-endian conversion methods are correctly implemented. However, consider adding a unit test to verify the round-trip conversion.

Would you like me to generate unit tests for the ReadUInt64BigEndian and WriteUInt64BigEndian methods to ensure they work correctly together?

UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs (1)

1079-1085: Consider adding logging for PackageCache blocking.

When blocking PackageCache paths on Windows, it might be helpful to log this action for debugging purposes, especially since it silently overrides the user's selection.

// Hard-block PackageCache on Windows unless dev override is set
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
    && serverSrc.IndexOf(@"\Library\PackageCache\", StringComparison.OrdinalIgnoreCase) >= 0
    && !UnityEditor.EditorPrefs.GetBool("UnityMCP.UseEmbeddedServer", false))
{
+    if (debugLogsEnabled)
+    {
+        UnityEngine.Debug.Log($"UnityMCP: Redirecting from PackageCache path to installed server path");
+    }
    serverSrc = ServerInstaller.GetServerPath();
}
CursorHelp.md (1)

1-86: Comprehensive Windows UV path troubleshooting guide!

This documentation provides excellent guidance for resolving UV path issues on Windows. The step-by-step instructions, real-world examples, and clear explanation of the WinGet Links shim preference make this very helpful for users.

Minor grammatical suggestions:

  • Line 7: The dash after the closing quote seems unnecessary
  • Consider using consistent bullet point formatting throughout
-  - Cursor shows the UnityMCP server but never connects or reports it "can't start."
+  - Cursor shows the UnityMCP server but never connects or reports it "can't start"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7af0cd and 6e59b8f.

⛔ Files ignored due to path filters (2)
  • UnityMcpBridge/UnityMcpServer~/src/uv.lock is excluded by !**/*.lock
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • CursorHelp.md (1 hunks)
  • UnityMcpBridge/Editor/Data/McpClients.cs (2 hunks)
  • UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (4 hunks)
  • UnityMcpBridge/Editor/UnityMcpBridge.cs (4 hunks)
  • UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs (9 hunks)
  • UnityMcpBridge/UnityMcpServer~/src/unity_connection.py (3 hunks)
  • claude-chunk.md (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-13T21:00:17.211Z
Learnt from: dsarno
PR: CoplayDev/unity-mcp#209
File: UnityMcpBridge/Editor/Helpers/ServerInstaller.cs:279-281
Timestamp: 2025-08-13T21:00:17.211Z
Learning: WinGet per-user Links directory is %LOCALAPPDATA%\Microsoft\WinGet\Links and machine Links directory is %ProgramFiles%\WinGet\Links based on official Microsoft documentation and winget --info command output.

Applied to files:

  • UnityMcpBridge/Editor/Helpers/ServerInstaller.cs
📚 Learning: 2025-08-13T21:00:17.211Z
Learnt from: dsarno
PR: CoplayDev/unity-mcp#209
File: UnityMcpBridge/Editor/Helpers/ServerInstaller.cs:279-281
Timestamp: 2025-08-13T21:00:17.211Z
Learning: WinGet machine-wide Links directory is located at %ProgramFiles%\WinGet\Links, not %ProgramData%\Microsoft\WinGet\Links. This is confirmed by winget --info output and Microsoft's official documentation.

Applied to files:

  • UnityMcpBridge/Editor/Helpers/ServerInstaller.cs
🪛 LanguageTool
claude-chunk.md

[grammar] ~10-~10: There might be a mistake here.
Context: ...nd that dylib. - Fix options (pick one) - Reinstall Homebrew Node (relinks to curr...

(QB_NEW_EN)

CursorHelp.md

[grammar] ~7-~7: There might be a mistake here.
Context: ...er connects or reports it “can’t start.” - Your %USERPROFILE%\\.cursor\\mcp.json ...

(QB_NEW_EN)


[grammar] ~17-~17: There might be a mistake here.
Context: ...ks\uv.exe #### Quick fix (recommended) 1) In Unity:Window > Unity MCP` → select ...

(QB_NEW_EN)


[grammar] ~66-~66: There might be a mistake here.
Context: ... stable launch shims in these locations: - User scope: `%LOCALAPPDATA%\Microsoft\Wi...

(QB_NEW_EN)


[grammar] ~67-~67: There might be a mistake here.
Context: ...ims in these locations: - User scope: %LOCALAPPDATA%\Microsoft\WinGet\Links\uv.exe - Machine scope: `C:\Program Files\WinGet...

(QB_NEW_EN)


[grammar] ~75-~75: There might be a mistake here.
Context: ...ed override and will stop auto-rewrites. - If neither Links path exists, a reasonab...

(QB_NEW_EN)


[style] ~76-~76: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...override and will stop auto-rewrites. - If neither Links path exists, a reasonable...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🔇 Additional comments (9)
UnityMcpBridge/Editor/Data/McpClients.cs (2)

72-77: XDG path update for Claude Desktop on Linux looks correct.

Using ~/.config/Claude/claude_desktop_config.json aligns with XDG. LGTM.


91-97: XDG path update for VSCode Copilot on Linux looks correct.

Using ~/.config/Code/User/mcp.json is the canonical location for VSCode user settings. LGTM.

UnityMcpBridge/Editor/Helpers/ServerInstaller.cs (1)

90-92: macOS save location alignment: LGTM.

Using SpecialFolder.ApplicationData and appending RootFolder should map to ~/Library/Application Support/UnityMCP on macOS, which is appropriate.

UnityMcpBridge/Editor/UnityMcpBridge.cs (2)

398-470: Framing protocol implementation looks good!

The implementation of the 8-byte big-endian length-prefixed framing with legacy fallback is well-designed. The code elegantly handles both the new framed protocol and maintains backward compatibility with unframed messages.


520-534: LGTM! Proper async reading with error handling.

The ReadExactAsync method correctly implements exact byte reading with proper async/await patterns and appropriate error handling for disconnections.

UnityMcpBridge/Editor/Windows/UnityMcpEditorWindow.cs (4)

948-977: Good addition of UV binary validation.

The addition of IsValidUv and ValidateUvBinarySafe methods provides robust validation of UV binaries with proper error handling and timeout protection.


1003-1129: Excellent incremental config writing implementation!

The WriteToConfig method now implements a well-structured incremental update pattern that:

  • Respects the lock preference
  • Preserves existing configuration
  • Only writes when changes are detected
  • Uses atomic file operations (temp file + replace)
  • Properly handles both VSCode and standard MCP config formats

The canonical args order ["run", "--directory", serverSrc, "server.py"] is consistently applied.


1205-1232: Well-structured server source resolution!

The ResolveServerSrc method implements a clear priority chain:

  1. Previously remembered path
  2. Installed server path
  3. Embedded server (if enabled)

The fallback logic ensures a valid server path is always returned.


633-642: Path comparison logic is robust.

The updated IsCursorConfigured method now properly extracts and compares directory arguments using the new helper methods, with appropriate null safety checks.

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