.agents/skills/tauri/SKILL.md
Tauri path handling, cross-platform file operations, and API usage. Use when the user mentions Tauri, desktop app, or when working with file paths in Tauri frontend code, accessing native filesystem APIs, invoking Tauri commands, or handling platform differences.
npx skillsauth add epicenterhq/epicenter tauriInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this pattern when you need to:
@tauri-apps/api/path and Node/Bun path APIs.join(), dirname(), and related helpers.@tauri-apps/plugin-fs operations.Before choosing a path API, determine your execution context:
| Context | Location | Correct API |
| ----------------------- | ---------------------------------------------- | ---------------------- |
| Tauri frontend | apps/*/src/**/*.ts, apps/*/src/**/*.svelte | @tauri-apps/api/path |
| Node.js/Bun backend | packages/**/*.ts, CLI tools | Node.js path module |
Rule: If the code runs in the browser (Tauri webview), use Tauri's path APIs. If it runs in Node.js/Bun, use the Node.js path module.
@tauri-apps/api/path| Function | Purpose | Example |
| ---------------------- | ------------------------------------------ | ------------------------------------------------- |
| join(...paths) | Join path segments with platform separator | await join(baseDir, 'workspaces', id) |
| dirname(path) | Get parent directory | await dirname('/foo/bar/file.txt') → /foo/bar |
| basename(path, ext?) | Get filename, optionally strip extension | await basename('/foo/bar.txt', '.txt') → bar |
| extname(path) | Get file extension | await extname('file.txt') → .txt |
| normalize(path) | Resolve .. and . segments | await normalize('/foo/bar/../baz') → /foo/baz |
| resolve(...paths) | Resolve to absolute path | await resolve('relative', 'path') |
| isAbsolute(path) | Check if path is absolute | await isAbsolute('/foo') → true |
| Function | Purpose | Returns |
| ------------- | ----------------------- | ---------------------------- |
| sep() | Platform path separator | \ on Windows, / on POSIX |
| delimiter() | Platform path delimiter | ; on Windows, : on POSIX |
| Function | Purpose |
| ----------------------- | ---------------------------------- |
| appLocalDataDir() | App's local data directory |
| appDataDir() | App's roaming data directory |
| appConfigDir() | App's config directory |
| appCacheDir() | App's cache directory |
| appLogDir() | App's log directory |
| tempDir() | System temp directory |
| resourceDir() | App's resource directory |
| resolveResource(path) | Resolve path relative to resources |
import { appLocalDataDir, dirname, join } from '@tauri-apps/api/path';
// Join path segments - handles platform separators automatically
const baseDir = await appLocalDataDir();
const filePath = await join(baseDir, 'workspaces', workspaceId, 'data.json');
// Get parent directory - cleaner than manual slicing
const parentDir = await dirname(filePath);
await mkdir(parentDir, { recursive: true });
For human-readable log output, hardcoded / is acceptable since it's not used for filesystem operations:
// OK for logging - consistent cross-platform log output
const logPath = pathSegments.join('/');
console.log(`[Persistence] Loading from ${logPath}`);
// BAD: Hardcoded separator breaks on Windows
const filePath = baseDir + '/' + 'workspaces' + '/' + id;
// BAD: Template literal with hardcoded separator
const filePath = `${baseDir}/workspaces/${id}`;
// GOOD: Use join()
const filePath = await join(baseDir, 'workspaces', id);
// BAD: Manual slicing is error-prone
const parentSegments = pathSegments.slice(0, -1);
const parentDir = await join(baseDir, ...parentSegments);
// GOOD: Use dirname()
const parentDir = await dirname(filePath);
// BAD: Windows uses backslashes
const configPath = appDir + '/config.json';
// GOOD: Platform-agnostic
const configPath = await join(appDir, 'config.json');
// BAD: Splitting on '/' fails on Windows paths
const parts = filePath.split('/');
// GOOD: Use dirname/basename for extraction
const dir = await dirname(filePath);
const file = await basename(filePath);
Always import from @tauri-apps/api/path:
import {
appLocalDataDir,
dirname,
join,
basename,
extname,
normalize,
resolve,
sep,
} from '@tauri-apps/api/path';
All Tauri path functions are async because they communicate with the Rust backend via IPC. Always await them:
// All path operations return Promises
const baseDir = await appLocalDataDir();
const filePath = await join(baseDir, 'file.txt');
const parent = await dirname(filePath);
const separator = await sep();
Use @tauri-apps/plugin-fs for file operations, combined with Tauri path APIs:
import { appLocalDataDir, dirname, join } from '@tauri-apps/api/path';
import { mkdir, readFile, writeFile } from '@tauri-apps/plugin-fs';
async function saveData(segments: string[], data: Uint8Array) {
const baseDir = await appLocalDataDir();
const filePath = await join(baseDir, ...segments);
// Ensure parent directory exists
const parentDir = await dirname(filePath);
await mkdir(parentDir, { recursive: true });
await writeFile(filePath, data);
}
documentation
Yjs CRDT patterns, shared types (Y.Map, Y.Array, Y.Text), conflict resolution, and document storage. Use when the user mentions Yjs, Y.Doc, CRDTs, collaborative editing, or when handling shared types, implementing real-time sync, or optimizing document storage.
tools
Voice and tone rules for all written content—prose, UI text, tooltips, error messages. Use when the user says "fix the tone", "rewrite this", "sounds like AI", "sounds corporate", or when writing any user-facing text, landing pages, product copy, or open-source documentation.
tools
Workspace API patterns for defineTable, defineKv, versioning, migrations, data access (CRUD + observation), withActions, and extension ordering. Use when the user mentions workspace, defineTable, defineKv, createWorkspace, withActions, withExtension, defineQuery, defineMutation, connectWorkspace, or when defining schemas, reading/writing table data, observing changes, writing migrations, chaining extensions, or attaching actions to a workspace client.
documentation
Standard workflow for implementing features with specs and planning documents. Use when the user says "start a new feature", "how should I plan this", "what's the process", or when starting implementation, planning work, or working on any non-trivial task.