К основному содержанию
скилл Claude Code CX Codex Cursor GitHub Copilot

dart-use-path-package — скилл для Claude Code: пути в Dart без багов

Учит агента работать с путями файлов в Dart через package:path, избегая строковых операций, которые ломаются на Windows.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add flutter/agent-plugins --skill dart-use-path-package -a claude-code
Открыть на GitHub

Что делает dart-use-path-package

Скилл заменяет небезопасные строковые операции вроде '$dir/$file', .split('/'), .endsWith('.ext') или .replaceAll('\\', '/') на методы package:path: p.join для склейки, p.split для разбора сегментов, p.extension для расширений, p.normalize и p.canonicalize для приведения путей. Агент получает правила кросс-платформенной работы с путями, конверсии в POSIX и URL форматы для Git и манифестов, обработки составных расширений вроде .tar.gz и .js.map, безопасного преобразования между путями и Uri.

Использует синтаксис Dart для сопоставления сегментов списком (list pattern matching), предотвращает баги с обратными слэшами Windows, дублированием разделителей и ложными совпадениями подстрок. Не применяется к HTTP-маршрутам, строкам запросов баз данных и обработке строк, не связанных с путями. Критично для проектов, которые должны работать на Windows: строковые операции с путями молча ломаются там, где macOS и Linux их пропускают.

Какие задачи решает

  • склеить пути без дублирования слэшей и багов Windows
  • извлечь расширение файла, не перепутав с директорией
  • преобразовать нативные пути в POSIX для Git или архивов
  • сопоставить сегмент пути кросс-платформенно
  • разобрать составное расширение вроде .tar.gz

Примеры запросов агенту

  • Замени все `'$dir/$file'` на `p.join` в lib/
  • Проверь path операции в src/ на совместимость с Windows
  • Преобразуй пути в manifest.yaml в POSIX через `p.posix.joinAll`

Как установить dart-use-path-package

1Через Skills CLI (Vercel)

npx skills add flutter/agent-plugins --skill dart-use-path-package -a claude-code

2Вручную: положить файлы

~/.claude/skills/dart-use-path-package/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/dart-use-path-package/

Из того же набора14

Весь набор →
flutter-apply-architecture-best-practices flutter Скилл раскладывает Flutter-приложение по слоям UI, Logic и Data. Пригодится для нового проекта или рефакторинга кода. Claude Code CX Codex Cursor +1 43 000установок flutter-build-responsive-layout flutter Скилл обучает агента строить адаптивные интерфейсы Flutter под экраны телефонов и десктопов. Он задаёт правила работы с LayoutBuilder и MediaQuery. Claude Code CX Codex Cursor +1 42 300установок flutter-add-widget-test flutter Скилл помогает писать компонентные тесты Flutter с помощью WidgetTester. Проверяет, как виджет отображается и реагирует на касания, скролл и ввод текста. Claude Code CX Codex Cursor +1 39 000установок flutter-add-integration-test flutter Скилл настраивает интеграционные тесты во Flutter через пакет integration_test. Он переносит действия из MCP-сервера в готовые тестовые сценарии. Claude Code CX Codex Cursor +1 38 000установок flutter-setup-declarative-routing flutter Настраивает декларативную маршрутизацию Flutter через go_router: маршруты по URL, вложенную навигацию и глубокие ссылки для веба и мобильных платформ. Claude Code CX Codex Cursor +1 37 600установок flutter-implement-json-serialization flutter Скилл учит агента создавать Dart-модели с методами fromJson и toJson через библиотеку dart:convert. Пригодится при ручном разборе простых структур данных в Flutter. Claude Code CX Codex Cursor +1 37 200установок flutter-add-widget-preview flutter Скилл учит агента создавать интерактивные превью виджетов во Flutter через package:flutter/widget_previews.dart. Пригодится для изолированной вёрстки UI без сборки всего приложения. Claude Code CX Codex Cursor +1 36 600установок flutter-setup-localization flutter Скилл автоматизирует инициализацию поддержки многоязычности в Flutter-проекте. Добавляет зависимости, включает генерацию кода и создаёт конфиг для работы с .arb-файлами. Claude Code CX Codex Cursor +1 36 600установок

Похожие

write-concept leonardomso Пишет и проверяет страницы понятий JavaScript для 33 JavaScript Concepts. Нужен при создании, переработке и редактуре материалов в /docs/concepts/. Claude Code CX Codex Cursor +1 305установок cargo-fuzz trailofbits Разворачивает cargo-fuzz в Rust-крейте и проводит через обвязку, санитайзеры и разбор падений. Claude Code CX Codex Cursor +1 5 400установок lsp-setup официальный github Скилл устанавливает языковой сервер и настраивает LSP для Copilot CLI. Подойдёт, когда нужны переход к определению и просмотр ссылок на символ. GitHub Copilot 1 100установок swiftdata-pro Paul Hudson Скилл для написания, проверки и улучшения кода SwiftData с соблюдением современных API и best practices. Нужен, если вы работаете с SwiftData в проектах на Swift. Claude Code CX Codex Cursor +1 9 200установок typescript-advanced-types sickn33 Помогает агенту писать дженерики, условные и mapped-типы в TypeScript и честно говорит, где проверка типов заканчивается. Claude Code CX Codex Cursor +1 1 300установок atheris trailofbits Настраивает coverage-guided фаззинг Python-кода и C-расширений через Atheris. Нужен для поиска сбоев и повреждений памяти. Claude Code CX Codex Cursor +1 5 200установок migrate-to-shoehorn Matt Pocock Переводит type assertions с as в тестах на функции из @total-typescript/shoehorn. Нужен для частичных объектов и намеренно неверных данных в проверках. Claude Code 475 388установок write-swift emilkowalski Скилл помогает писать, проверять и переносить код на Swift с учётом модели языка. Подойдёт, когда нужно разобраться с конкурентностью, ошибкой или циклом удержания объектов. Claude Code CX Codex Cursor +1 117 500установок

Вопросы о dart-use-path-package

Как установить dart-use-path-package в Claude Code?

Выполни npx skills add flutter/agent-plugins --skill dart-use-path-package -a claude-code. Скилл появится в ~/.claude/skills/dart-use-path-package/.

Что делает dart-use-path-package?

Учит агента заменять строковые операции с путями на методы package:path, которые работают одинаково на Windows, macOS и Linux. Предотвращает баги с обратными слэшами, дублированием разделителей и ложными совпадениями расширений.

Когда использовать p.normalize, а когда p.canonicalize?

p.normalize разрешает . и .. лексически, без обращения к файловой системе. p.canonicalize нужен для сравнения физической идентичности файлов через симлинки, относительные корни или регистронезависимые файловые системы.

Исходный текст

SKILL.md · BSD-3-Clause
---
name: dart-use-path-package
description: >-
  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.
metadata:
  model: models/gemini-3.1-pro-preview
  last_modified: Wed, 23 Sep 2026 22:10:00 GMT
---

# Safe Cross-Platform Path Manipulation in Dart

## Contents
* [1. Core Principles & Cross-Platform Rules](#1-core-principles--cross-platform-rules)
* [2. Recommended package:path Idioms vs. String Anti-Patterns](#2-recommended-packagepath-idioms-vs-string-anti-patterns)
* [3. Bridging Native Paths to POSIX, Git, & URL Contexts](#3-bridging-native-paths-to-posix-git--url-contexts)
* [4. Mockable File Systems (`package:file` vs. Global `p.*`)](#4-mockable-file-systems-packagefile-vs-global-p)
* [5. Extensions, Compound Extensions & Stem Extraction](#5-extensions-compound-extensions--stem-extraction)
* [6. Workflows & Audit Checklist](#6-workflows--audit-checklist)
* [References & Examples](#references--examples)

---

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

```dart
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`):

```dart
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)`:

```dart
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](examples/cross_platform_paths.dart)
* **Mockable FileSystem Path Context Example**: [examples/file_system_context.dart](examples/file_system_context.dart)

© flutter · BSD-3-Clause · flutter/agent-plugins

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой