Files
tauri-shell/AGENTS.md
imbytecat f722e50f0b docs: 添加 AI 编码代理开发指南
- 创建 AGENTS.md 文件以提供 AI 编码代理在该项目中的开发指南,涵盖项目概览、构建命令、代码风格规范、Tauri 通信模式、依赖管理及常见陷阱。
2026-01-16 19:38:21 +08:00

7.6 KiB

AGENTS.md - Coding Agent Guide

This file provides essential information for AI coding agents working in this repository.

📋 Project Overview

Tech Stack: Tauri 2.x Desktop Application

  • Frontend: Vanilla TypeScript + Vite 6.0.3
  • Backend: Rust (edition 2021)
  • Package Manager: Bun (preferred) or npm
  • Build Tool: Vite + Tauri CLI
  • Runtime: mise (for Rust toolchain management)

Project Structure:

tauri-demo/
├── src/                    # Frontend TypeScript/HTML/CSS
│   ├── main.ts            # Application entry point
│   ├── styles.css         # Global styles
│   └── assets/            # Static resources
├── src-tauri/             # Rust backend
│   ├── src/               # Rust source code
│   │   ├── main.rs       # Rust entry
│   │   └── lib.rs        # Tauri commands
│   ├── Cargo.toml        # Rust dependencies
│   ├── tauri.conf.json   # Tauri configuration
│   ├── capabilities/     # Permission configs
│   └── icons/            # Multi-platform icons
├── index.html            # HTML entry
├── package.json          # Node.js config
├── tsconfig.json         # TypeScript config
└── vite.config.ts        # Vite config

🔧 Build/Lint/Test Commands

Development

# Start frontend dev server (port 1420)
bun run dev

# Start Tauri in dev mode (recommended for full app testing)
bun run tauri dev

# Preview production build
bun run preview

Building

# Build frontend only (TypeScript compile + Vite bundle)
bun run build

# Build complete Tauri application (all platforms)
bun run tauri build

# Build for specific platform
bun run tauri build --target x86_64-pc-windows-msvc  # Windows
bun run tauri build --target x86_64-apple-darwin      # macOS
bun run tauri build --target x86_64-unknown-linux-gnu # Linux

Type Checking

# TypeScript type check (run before build)
tsc --noEmit

# Watch mode for continuous type checking
tsc --noEmit --watch

Rust Commands

# Check Rust code (fast compile check)
cd src-tauri && cargo check

# Format Rust code
cd src-tauri && cargo fmt

# Lint Rust code
cd src-tauri && cargo clippy

# Run Rust tests
cd src-tauri && cargo test

# Run a specific Rust test
cd src-tauri && cargo test test_name

# Run tests with output
cd src-tauri && cargo test -- --nocapture

Testing

Note: No test framework is currently configured. To add testing:

Frontend Testing (recommended: Vitest):

bun add -D vitest @vitest/ui
# Run all tests: bun run vitest
# Run single test: bun run vitest path/to/test.test.ts

Rust Testing: Use built-in cargo test (see above)

📐 Code Style Guidelines

TypeScript/JavaScript

Imports

  • Use ES6 imports: import { foo } from "bar"
  • Tauri API imports: import { invoke } from "@tauri-apps/api/core"
  • Group imports: external packages first, then local modules
  • No unused imports (enforced by noUnusedLocals)

Example:

import { invoke } from "@tauri-apps/api/core";
import { open } from "@tauri-apps/plugin-opener";

import { helperFunction } from "./utils";

Types

  • Always use explicit types for function parameters and return values
  • Use type inference for simple variable assignments
  • Prefer interface for object shapes, type for unions/intersections
  • Enable all strict mode checks (already configured in tsconfig.json)

Example:

// Good ✅
async function greet(name: string): Promise<string> {
  return await invoke("greet", { name });
}

// Bad ❌
async function greet(name) {
  return await invoke("greet", { name });
}

Naming Conventions

  • Variables/Functions: camelCase (greetUser, userName)
  • Constants: UPPER_SNAKE_CASE (MAX_RETRIES, API_URL)
  • Types/Interfaces: PascalCase (UserData, AppConfig)
  • Private members: prefix with underscore (_internalState)

Error Handling

  • Always handle promises with async/await or .catch()
  • Use try-catch for critical operations
  • Provide meaningful error messages

Example:

async function callRustCommand(): Promise<void> {
  try {
    const result = await invoke<string>("greet", { name: "World" });
    console.log(result);
  } catch (error) {
    console.error("Failed to call Rust command:", error);
  }
}

Rust

Formatting

  • Use cargo fmt (rustfmt) for automatic formatting
  • 4 spaces for indentation (standard Rust)
  • Line length: 100 characters (rustfmt default)

Naming Conventions

  • Functions/Variables: snake_case (greet_user, user_name)
  • Types/Structs/Enums: PascalCase (UserData, AppState)
  • Constants: SCREAMING_SNAKE_CASE (MAX_CONNECTIONS)
  • Lifetimes: lowercase single letter ('a, 'static)

Tauri Commands

  • Mark with #[tauri::command] attribute
  • Use &str for string parameters (efficient)
  • Return owned types (String, not &str)
  • Register in invoke_handler! macro

Example:

#[tauri::command]
fn process_data(input: &str, count: i32) -> Result<String, String> {
    if count < 0 {
        return Err("Count must be non-negative".to_string());
    }
    Ok(format!("Processed {} with count {}", input, count))
}

// Register in lib.rs:
.invoke_handler(tauri::generate_handler![process_data])

Error Handling

  • Use Result<T, E> for fallible operations
  • Prefer ? operator for error propagation
  • Use expect() only when panic is acceptable
  • Return descriptive error messages

Example:

#[tauri::command]
fn read_config() -> Result<Config, String> {
    let data = std::fs::read_to_string("config.json")
        .map_err(|e| format!("Failed to read config: {}", e))?;
    
    serde_json::from_str(&data)
        .map_err(|e| format!("Invalid JSON: {}", e))
}

🔌 Tauri-Specific Patterns

Frontend → Rust Communication

import { invoke } from "@tauri-apps/api/core";

// Simple command
const result = await invoke<string>("command_name", { param: value });

// With error handling
try {
  const data = await invoke<ReturnType>("command", args);
} catch (error) {
  console.error("Command failed:", error);
}

Adding New Commands

  1. Define in src-tauri/src/lib.rs:

    #[tauri::command]
    fn new_command(param: &str) -> String {
        // implementation
    }
    
  2. Register in invoke_handler:

    .invoke_handler(tauri::generate_handler![greet, new_command])
    
  3. Call from frontend:

    await invoke("new_command", { param: "value" });
    

📦 Dependencies

Adding Dependencies

Frontend:

bun add package-name           # Production dependency
bun add -D package-name        # Dev dependency

Rust:

cd src-tauri
cargo add package-name         # Production dependency
cargo add --dev package-name   # Dev dependency

⚠️ Common Pitfalls

  1. Port conflicts: Dev server uses port 1420, HMR uses 1421
  2. Type mismatches: Ensure Rust return types match TypeScript expectations
  3. Missing command registration: New Tauri commands must be added to generate_handler!
  4. Permission issues: Update src-tauri/capabilities/default.json for new capabilities
  5. Build errors: Run tsc before vite build (automated in build script)

🚀 Workflow Tips

  • Always run tsc --noEmit before committing to catch type errors
  • Test Tauri commands with bun run tauri dev, not just bun run dev
  • Use cargo clippy to catch common Rust mistakes
  • Check both frontend and Rust console for errors during development
  • Clear Vite cache if seeing stale builds: rm -rf node_modules/.vite