- 创建 AGENTS.md 文件以提供 AI 编码代理在该项目中的开发指南,涵盖项目概览、构建命令、代码风格规范、Tauri 通信模式、依赖管理及常见陷阱。
7.6 KiB
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
interfacefor object shapes,typefor 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/awaitor.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
&strfor 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
-
Define in
src-tauri/src/lib.rs:#[tauri::command] fn new_command(param: &str) -> String { // implementation } -
Register in
invoke_handler:.invoke_handler(tauri::generate_handler![greet, new_command]) -
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
- Port conflicts: Dev server uses port 1420, HMR uses 1421
- Type mismatches: Ensure Rust return types match TypeScript expectations
- Missing command registration: New Tauri commands must be added to
generate_handler! - Permission issues: Update
src-tauri/capabilities/default.jsonfor new capabilities - Build errors: Run
tscbeforevite build(automated in build script)
🚀 Workflow Tips
- Always run
tsc --noEmitbefore committing to catch type errors - Test Tauri commands with
bun run tauri dev, not justbun run dev - Use
cargo clippyto 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