MCPInstall

dart-use-path-package

Cross-platform file and directory path manipulation, segment splitting, extension extraction, and context conversion using package:path and package:file. Use when writing, inspecting, joining, splitting, or refactoring file paths, directory names, or extensions, or replacing raw string path operations (.split('/'), '$dir/$file', .endsWith('.ext'), .replaceAll('\\', '/')). Don't use for HTTP network URI routing, database query strings, or non-path string processing.

Installs
6.1K
Last 24h
+183
Trending rank
#1308
Security
Pass

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/flutter/agent-plugins --skill dart-use-path-package
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads dart-use-path-package automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

Security audits

Independent scans of the skill's instructions and bundled files.

Gen Agent Trust Hub PassSAFE ·This skill provides best practices and architectural guidance for cross-platform file path manipulation in Dart. It promotes the use of standard libraries to prevent common OS-specific errors and contains no malicious code or behaviors.
Socket PassNo alerts
Snyk PassLOW ·Risk: LOW · No issues

SKILL.md

The instructions your agent reads when the skill is triggered.

Safe Cross-Platform Path Manipulation in Dart

Contents


1. Core Principles & Cross-Platform Rules

Avoid Treating File Paths as Raw Strings

  • Native file paths on Windows use backslashes (\), whereas macOS and Linux use forward slashes (/).
  • String operations like .contains('foo/'), .startsWith('foo/'), or .split('/') silently fail on Windows native paths.
  • String interpolation like '$dir/$file' injects forward slashes on Windows and produces duplicate slashes (//) when $dir ends with a trailing slash.

Rule: Always decompose paths into segments using p.split(path) before inspecting directory hierarchy or segment names, and always join path components using p.join(...).

Pragmatic Boundary Joining vs. Multi-Segment Decomposition (p.join)

  • Cross-Platform Libraries (Windows + POSIX): Pass individual path segments to p.join(dir, 'sub', 'file.json') so package:path inserts OS-native separators (\ on Windows, / on POSIX) between every component.
  • POSIX-Only Tools & Static Subpath Greppability: In codebases exclusively targeting Linux/macOS (or when joining a dynamic base path to a known static subpath), decomposing 5–6 static segments into separate arguments (p.join(home, '.local', 'share', 'app', 'bin', 'config.json')) causes dart format to wrap across 6–8 vertical lines and destroys substring greppability (grep / code_search for .local/share/app/bin).
  • Rule for POSIX Targets: Prefer 2-argument boundary joining (p.join(home, '.local/share/app/bin/config.json')). This prevents duplicate-slash bugs (//) at variable boundaries while preserving single-line readability and exact string searchability.

Normalization vs. Canonicalization (p.normalize vs. p.canonicalize)

  • p.normalize(path) resolves . and .. segments purely lexically without consulting the filesystem or standardizing case.
  • When deduplicating directory paths or comparing physical file identity across symlinks, relative roots, or case-insensitive filesystems, use p.canonicalize(path).

Strip Location Specifiers & Convert URIs Safely

  • Strings formatted as <path>:<line>-<col> or <path>:<line> are not pure file paths. Passing them directly to p.normalize or Uri.parse causes bugs (on Windows, Uri.parse mistakes C: for a URI scheme and :line for a port).
  • Extract the trailing :line-col suffix via regular expression (RegExp(r'^(.*?):(\d+(?:-\d+)?)$')) before passing the file path to package:path.
  • URI Boundary Conversions: When converting between file paths and Uri objects, always use p.toUri(path) and p.fromUri(uri) rather than Uri.parse(path) or manual string concatenation.

2. Recommended package:path Idioms vs. String Anti-Patterns

Path Joining

  • Prefer: p.join(dir, file)
  • Avoid: '$dir/$file' or 'a/$b'
  • Why: String interpolation injects / on Windows and creates duplicate slashes (//) when $dir ends with a trailing separator.

Segment Matching

  • Prefer: p.split(path).contains('foo')
  • Avoid: path.contains('foo/')
  • Why: String matching fails on Windows backslashes (foo\bar) and produces false positives on partial substring names (e.g. barfoo/).

Root and Directory Prefixes

  • Prefer: if (p.split(path) case ['foo', ...]) (or case ['foo', ...final rest] when extracting tail segments), or p.isWithin('foo', path)
  • Avoid: path.startsWith('foo/') or p.split(path).first == 'foo'
  • Why: String prefix matching fails on Windows separators (foo\bar). Calling p.split(path).first throws a StateError on empty lists and requires separate .skip(1) slicing, whereas list patterns safely check non-emptiness, match multi-segment prefixes, and optionally bind ...final rest in a single step. When unnormalized relative prefixes like ./foo/bar may appear, use p.isWithin('foo', path) (or p.split(p.normalize(path))).

File Extensions

  • Prefer: p.extension(path) == '.wasm'
  • Avoid: path.endsWith('.wasm')
  • Why: Substring suffix matching falsely matches directories (foo.wasm/) or non-extension suffixes.

Extension Slicing and Compound Extensions

  • Prefer: p.withoutExtension(path) and p.extension(path, 2)
  • Avoid: path.lastIndexOf('.') and manual substring slicing
  • Why: Manual arithmetic breaks on hidden dotfiles (.gitignore) and compound extensions (.js.map, .tar.gz).

POSIX and URL Path Conversion

  • Prefer: p.posix.joinAll(p.split(path)) or p.url.joinAll(p.split(path))
  • Avoid: path.replaceAll(r'\', '/')
  • Why: Ad-hoc separator replacement fails on root drives and mixes OS context with POSIX or URL targets.

URI Conversion

  • Prefer: p.toUri(path) and p.fromUri(uri)
  • Avoid: Uri.parse(path) and uri.path
  • Why: Direct URI parsing fails on Windows drive letters (C:) and leaks percent-encoding (e.g. %20 for spaces).

Directory Basename Helper

  • Prefer: String canonicalDirName(Directory d) => p.basename(p.normalize(d.absolute.path));
  • Avoid: Repeating p.basename(p.normalize(dir.absolute.path)) inline across files.
  • Why: Centralizes canonical directory naming logic and reduces boilerplate.

3. Bridging Native Paths to POSIX, Git, & URL Contexts

Avoid calling .replaceAll('\\', '/') or .replaceAll(r'\', '/') to convert OS-native paths into POSIX paths (for Git, YAML, archive manifests) or URL segments.

Rule: Split the relative native path using p.split(...), inspect segments with Dart 3 list pattern matching, and join using p.posix.joinAll(...) or p.url.joinAll(...). Always call p.relative(filePath, from: root) first so leading root segments ('/' on POSIX or r'C:\' on Windows) do not interfere with relative prefix patterns:

import 'package:path/path.dart' as p;

String computeWebAssetKey(String filePath, String projectRoot) {
  final relative = p.relative(filePath, from: projectRoot);
  final segments = p.split(relative);
  return switch (segments) {
    ['assets', ...] => p.posix.joinAll(segments),
    _ => p.posix.joinAll(['assets', ...segments]),
  };
}

Git Paths and Repository Metadata

  • Git repository tree objects, .gitignore pattern rules, .gitattributes, and git-tracked symlinks strictly use POSIX forward slashes (/), even on Windows.
  • Inserting native Windows backslashes (\) into .gitignore or git commands causes Git to treat \ as an escape character rather than a directory separator, silently breaking pattern matching.
  • When generating .gitignore entries, repository manifests, or symlink targets programmatically from native file paths, convert the relative native path using p.posix.joinAll(p.split(relativePath)) or p.posix.join(...).

4. Mockable File Systems (package:file vs. Global p.*)

In codebases that use package:file (e.g., CLI applications or services tested with MemoryFileSystem), avoid calling top-level p.* functions on File or Directory paths.

  • Top-level p.* functions bind to the host operating system running the test.
  • If a unit test creates a MemoryFileSystem(style: FileSystemStyle.windows) on a Linux or macOS runner, global p.split(file.path) will split on / instead of \, breaking the test.

Rule: Always use the Context attached to the FileSystem (file.fileSystem.path):

import 'package:file/file.dart';

List<String> listSubdirectoryNames(Directory dir) {
  final pathContext = dir.fileSystem.path;
  return dir
      .listSync()
      .whereType<Directory>()
      .map((d) => pathContext.basename(d.path))
      .toList();
}

5. Extensions, Compound Extensions & Stem Extraction

Avoid manual .lastIndexOf('.') and .substring() arithmetic when extracting file extensions or inserting content hashes. p.extension natively supports multi-level extensions via its optional level parameter.

  • Multi-Dot Stem Nuance: Calling p.extension('main.dart.wasm', 2) returns '.dart.wasm' because it blindly captures the last two dot-separated segments. When hashing or stripping extensions on files that may have multi-dot stems (e.g., main.dart.wasm vs. main.dart.js.map), check whether p.extension(filename, 2) matches a known compound extension (or .endsWith('.map')) before falling back to single-level p.extension(filename):
import 'package:path/path.dart' as p;

String insertContentHash(String filename, String hash) {
  final compoundExt = p.extension(filename, 2);
  // Only use the 2-level extension for true compound suffixes (e.g., '.js.map')
  final ext = compoundExt.endsWith('.map')
      ? compoundExt
      : p.extension(filename);
  final stem = filename.substring(0, filename.length - ext.length);
  return '$stem.$hash$ext';
}

6. Workflows & Audit Checklist

Path Refactoring Checklist

  • Replace string interpolation ('$dir/$file') with p.join(dir, file).
  • Replace .contains('dir/') and .startsWith('dir/') with p.split(path) list pattern checks (case ['dir', ...final rest]) or p.isWithin(parent, child).
  • Replace .replaceAll(r'\', '/') with p.posix.joinAll(p.split(path)) (or p.url.joinAll).
  • Replace .endsWith('.ext') on file paths with p.extension(path) == '.ext'.
  • Replace manual dot-index slicing with p.withoutExtension(path) and p.extension(path, [level]).
  • Verify that code using package:file accesses fileSystem.path instead of global p.*.
  • Ensure Git paths, .gitignore entries, and symlink targets use p.posix forward slashes.

References & Examples

  • Cross-Platform Path & POSIX Conversion Examples: examples/cross_platform_paths.dart
  • Mockable FileSystem Path Context Example: examples/file_system_context.dart

FAQ

What does the dart-use-path-package skill do?

Cross-platform file and directory path manipulation, segment splitting, extension extraction, and context conversion using package:path and package:file. Use when writing, inspecting, joining, splitting, or refactoring file paths, directory names, or extensions, or replacing raw string path operations (.split('/'), '$dir/$file', .endsWith('.ext'), .replaceAll('\\', '/')). Don't use for HTTP network URI routing, database query strings, or non-path string processing.

How do I install dart-use-path-package?

Run npx skills add https://github.com/flutter/agent-plugins --skill dart-use-path-package in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/dart-use-path-package/ (personal) or .claude/skills/dart-use-path-package/ (project).

Which AI agents can use dart-use-path-package?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is dart-use-path-package safe to install?

Security partners have reviewed it: Gen Agent Trust Hub passed; Socket passed; Snyk passed. As with any skill, read the SKILL.md and bundled scripts before installing.

Who maintains dart-use-path-package?

It is published by flutter in flutter/agent-plugins. It has 6,149 recorded installs.

More from flutter/agent-plugins

View all →

Architects a Flutter application using the recommended layered approach (UI, Logic, Data). Use when structuring a new project or refactoring for scalability.

flutter-build-responsive-layout

flutter/agent-plugins

Use LayoutBuilder, MediaQuery, or Expanded/Flexible to create a layout that adapts to different screen sizes. Use when you need the UI to look good on both mobile and tablet/desktop form factors.

Frontend & Design42.8K installs

flutter-fix-layout-issues

flutter/agent-plugins

Fixes Flutter layout errors (overflows, unbounded constraints) using Dart and Flutter MCP tools. Use when addressing "RenderFlex overflowed", "Vertical viewport was given unbounded height", or similar layout issues.

Mobile40.2K installs

flutter-add-widget-test

flutter/agent-plugins

Implement a component-level test using WidgetTester to verify UI rendering and user interactions (tapping, scrolling, entering text). Use when validating that a specific widget displays correct data and responds to events as expected.

Testing & QA39.4K installs

flutter-add-integration-test

flutter/agent-plugins

Configures Flutter Driver for app interaction and converts MCP actions into permanent integration tests. Use when adding integration testing to a project, exploring UI components via MCP, or automating user flows with the integrationtest package.

Testing & QA38.4K installs

Configure MaterialApp.router using a package like gorouter for advanced URL-based navigation. Use when developing web applications or mobile apps that require specific deep linking and browser history support.

Mobile37.9K installs

Popular data & databases skills

View category →

Postgres best practices maintained by Supabase, for Postgres running anywhere. Load this skill BEFORE writing or changing anything that lives in a Postgres database: creating or altering tables and columns (including choosing column types), schema design, migrations and declarative schema files, RLS policies and the tests that verify them, indexes, triggers, database functions, queues and scheduled jobs (pgcron, pgmq), vector/semantic search (pgvector), and restoring dumps (pgrestore) or importing data. Also load it when diagnosing slow queries, high CPU, timeouts, EXPLAIN plans, connection exhaustion, locking, bloat, or rows visible to the wrong user or tenant. This is not just a performance guide — schema, migration, security, and SQL authoring tasks need these rules too, even for a one-column change or a single query.

OfficialData & Databases462.2K installs

prisma-client-api

prisma/skills

Prisma Client API reference covering model queries, filters, operators, and client methods. Use when writing database queries, using CRUD operations, filtering data, or configuring Prisma Client. Triggers on "prisma query", "findMany", "create", "update", "delete", "$transaction".

OfficialData & Databases393.5K installs

Deprecated compatibility name for prisma-orm-setup. Use only when a user or existing integration explicitly invokes prisma-database-setup; otherwise select prisma-orm-setup.

OfficialData & Databases392.3K installs

prisma-cli

prisma/skills

Prisma ORM 7 CLI reference for existing Prisma 7 applications or explicitly selected Prisma 7 workflows. Covers prisma init, generate, migrate, db, dev, studio, and mcp. For setup, connection repair, or Prisma 8, use prisma-orm-setup; not the Prisma Platform CLI.

OfficialData & Databases390.8K installs

prisma-postgres

prisma/skills

Deprecated compatibility name for prisma-postgres-setup. Use only when a user or existing integration explicitly invokes prisma-postgres; otherwise select prisma-postgres-setup.

OfficialData & Databases384.4K installs

Required reference for Prisma ORM 7 SQL driver adapter work. Use when implementing or modifying adapters, adding database drivers, or touching SqlDriverAdapter, Transaction, savepoint, result mapping, or DriverAdapterError behavior. Covers current transaction lifecycle, optional savepoint hooks, original database-error preservation, and verification.

OfficialData & Databases378.9K installs