RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Diff/vaillerteeter-hoshiminest-clinerules-project-identity ↔ vaillerteeter-hoshiminest-clinerules-backend-rules

Comparison

A · Cline rules · VaillerTeeter/HoshimiNestB · Cline rules · VaillerTeeter/HoshimiNest
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections01190%
Commands0810%
Section tags13314%

What each file covers

Sections

0 shared · 11 only in A · 9 only in B
  • − Project Identity
  • − Project Name & Purpose
  • − Tech Stack
  • − Frontend
  • − Backend
  • − External Binaries
  • − Development Environment
  • − Directory Structure
  • − Package Rules
  • − Dev Commands
  • − Window Config
  • + Backend Rules
  • + Tauri Commands
  • + State Management
  • + Frontend Communication
  • + Logging
  • + External Processes
  • + Compile-time Config
  • + HTTP Client
  • + Clippy & Code Quality

Commands

0 shared · 8 only in A · 1 only in B
  • − yarn dev
  • − yarn tauri dev
  • − yarn build
  • − yarn tauri build
  • − yarn rustcheck
  • − npm install
  • − pnpm add
  • − yarn
  • + cargo build

Section tags

1 shared · 3 only in A · 3 only in B
  • − setup
  • − architecture
  • − types
  • + build
  • + lint-format
  • + code-style
  •   do-not

Line diff

+96 added−86 removed29 unchanged23.2% identical
VaillerTeeter/HoshimiNest · .clinerules/project-identity.md
@@ −1 @@
1---
2description: "HoshimiNest project overview — tech stack, directory structure, package manager, dev commands, Rust dependencies. Always apply."
3globs: ""
4alwaysApply: true
5---
6 
7# Project Identity
8 
9<!-- HoshimiNest 项目身份与架构,AI 每次对话自动加载 -->
10 
11## Project Name & Purpose
12 
13HoshimiNest is a desktop anime tracking & download manager.
14 
15## Tech Stack
16 
17### Frontend
 
 
 
18 
19- **React 19 + TypeScript** — functional components + hooks, strict mode
20- **Vite 7** — bundler, dev port `1520`
21- **Zustand** — state management (`src/store/`)
22- **Plain CSS** — NO Tailwind, NO CSS-in-JS
23- **Yarn** — the ONLY package manager
24 
25### Backend
26 
27- **Tauri v2** — Rust desktop shell
28- **Key Rust crates:**
29 - `reqwest` (HTTP client, rustls-tls)
30 - `serde` + `serde_json` (serialization)
31 - `tokio` (async runtime: time, sync, macros, rt)
32 - `tauri-plugin-shell` / `tauri-plugin-opener` / `tauri-plugin-dialog`
33 - `log` + `env_logger`
34 
35### External Binaries
36 
37Bundled with the app via `externalBin`:
38 
39- `aria2c` — download engine
40- `mkvmerge` — media remuxing
 
41 
42## Development Environment
 
43 
44- **OS**: Windows only — NEVER assume macOS/Linux/WSL paths or tools
45- **Shell**: PowerShell (`.ps1` scripts) — NEVER write `.sh` or bash scripts
46- **Terminal commands**: always use PowerShell syntax; NEVER use Unix-only flags or pipes
47 
48## Directory Structure
49 
50```text
51src/ # React frontend source
52 ├── App.css # global layout & component styles (colors reference theme.css vars)
53 ├── App.tsx # root component (topbar + sidebar nav + download settings modal)
54 ├── assets/
55 │ └── fonts/ # bundled font files
56 ├── main.tsx # React entry point
57 ├── pages/ # page-level components (one per nav item)
58 │ ├── BacklogPage.tsx # backlog / plan-to-watch
59 │ ├── DownloadPage.tsx # download manager
60 │ ├── FinishedPage.tsx # completed anime (main file, sub-logic in finished/)
61 │ ├── QueryPage.tsx # seasonal query (main page)
62 │ ├── QueryPage/ # seasonal query sub-components
63 │ ├── SearchPage.tsx # resource search (main page)
64 │ ├── SearchPage/ # resource search sub-components
65 │ ├── TracksPage.tsx # track workshop (main file, sub-logic in tracks/)
66 │ ├── WatchingPage.tsx # currently watching
67 │ ├── WatchListPage.tsx # watchlist base (main file, sub-logic in watchlist/)
68 │ ├── finished/ # completed anime sub-components
69 │ ├── tracks/ # track workshop sub-components
70 │ └── watchlist/ # watchlist sub-components
71 ├── store/ # global state
72 │ ├── downloadStore.tsx # download task context (state machine + aria2 events + localStorage)
73 │ └── watchStore.ts # watchlist localStorage helpers
74 ├── styles/
75 │ ├── fonts.css # @font-face declarations
76 │ └── theme.css # theme CSS variables
77 └── vite-env.d.ts # Vite type declarations
78src-tauri/ # Tauri/Rust backend
79 ├── app-config.json # compile-time config (BT trackers, ports, cache)
80 ├── build.rs # Tauri build script
81 ├── capabilities/
82 │ └── default.json # Tauri ACL capability config
83 ├── icons/ # app icons
84 ├── src/
85 │ ├── lib.rs # Tauri commands + aria2 control + mkvmerge track merge
86 │ └── main.rs # Rust entry point
87 └── tauri.conf.json # Tauri app config (window/bundle/permissions)
88scripts/ # dev & setup scripts (.ps1)
89```
90 
91## Package Rules
92 
93NEVER run `npm install` or `pnpm add`. Always use `yarn`.
94 
95NEVER suggest re-installing these — already in `package.json`:
96 
97- `@tauri-apps/api`, `@tauri-apps/plugin-dialog`, `@tauri-apps/plugin-opener`
98- `animal-island-ui`, `bangumi-api-client`
99- `react`, `react-dom`, `zustand`
100 
101## Dev Commands
 
 
 
 
102 
103```bash
104yarn dev # Vite dev server (frontend only, port 1520)
105yarn tauri dev # full Tauri app in dev mode
106yarn build # TypeScript check + Vite build
107yarn tauri build # production Tauri bundle
108yarn rustcheck # cargo check (Rust compilation check only)
 
 
 
 
 
 
 
109```
110 
111## Window Config
112 
113- Window: 1360×820, non-resizable, non-maximizable, frameless (custom titlebar)
114- App identifier: `HoshimiNest`
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115 
VaillerTeeter/HoshimiNest · .clinerules/backend-rules.md
@@ +1 @@
1---
2description: "Use when: writing or modifying Rust code in src-tauri/. Covers Tauri command structure, state management, external process handling, logging, and compile-time config."
3globs: "src-tauri/**"
4alwaysApply: false
5---
6 
7# Backend Rules
8 
9<!-- Tauri v2 / Rust 后端规范,操作 src-tauri/ 目录时自动加载 -->
10 
11## Tauri Commands
12 
13Always declare Tauri commands in `src-tauri/src/lib.rs` and register them in `run()` via `.invoke_handler(tauri::generate_handler![...])`.
14 
15Always use `#[tauri::command]` on async functions. NEVER use sync commands for I/O-bound work.
16 
17```rust
18#[tauri::command]
19async fn my_command(app: tauri::AppHandle, ...) -> Result<T, String> { ... }
20```
21 
22Always receive `app: tauri::AppHandle` as the first parameter. Use `app.state::<MyState>()` to access managed state.
 
 
 
 
23 
24Prefer `Result<T, String>` as the return type for all commands. Use the `?` operator with `.map_err(|e| e.to_string())` or `.map_err(|e| format!("context: {e}"))` for error propagation.
25 
26Use `tauri::async_runtime::spawn()` for long-running background tasks spawned from commands (e.g., polling loops, sidecar process monitors). NEVER use `std::thread::spawn` or `tokio::spawn` directly.
 
 
 
 
 
 
27 
28## State Management
29 
30Always use Tauri managed state (`app.manage(...)` in `run()`) for shared data. Declare state structs with thread-safe wrappers:
31 
32```rust
33/// task_id → aria2 gid
34struct GidMap(Mutex<HashMap<String, String>>);
35 
36/// task_id → oneshot sender to stop the polling loop
37struct PollStops(Mutex<HashMap<String, oneshot::Sender<()>>>);
38 
39/// Flag to break re-entry loops
40struct Closing(AtomicBool);
41```
42 
43Never use global `static mut` or `lazy_static!` for mutable state — always go through `app.state::<T>()`.
44 
45## Frontend Communication
46 
47Always emit events to the frontend via `app.emit("event-name", payload)`. Define payload types with `#[derive(serde::Serialize, Clone)]`.
48 
49```rust
50#[derive(serde::Serialize, Clone)]
51struct MyEventPayload {
52 id: String,
53 value: u8,
54}
55 
56let _ = app.emit("my-event", MyEventPayload { id, value });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57```
58 
59Never call `app.emit()` from a synchronous context that holds a lock — always clone the `AppHandle` and emit from an async context or after releasing the lock.
60 
61## Logging
62 
63Always use the `log` crate macros: `debug!`, `info!`, `warn!`, `error!`.
64 
65Prefix log messages with a tag for filtering:
 
 
66 
67```rust
68info!("[add_magnet] task={task_id}");
69debug!("[{task_id}] gid handoff: {current_gid} → {new_gid}");
70error!("[merge][{}] 合并失败: {}", job.id, msg.trim());
71```
72 
73Use `debug!` for detailed diagnostics, `info!` for lifecycle events, `warn!` for recoverable issues, `error!` for failures.
74 
75Register `env_logger` in `run()` before the Tauri builder. Do NOT add additional logging frameworks.
76 
77## External Processes
78 
79Always use `tauri-plugin-shell` for spawning external binaries (aria2c, mkvmerge, etc.). NEVER use `std::process::Command` directly.
80 
81```rust
82use tauri_plugin_shell::{process::CommandEvent, ShellExt};
83 
84let sidecar_cmd = app.shell().sidecar("mkvmerge").map_err(|e| format!("sidecar error: {e}"))?;
85let (mut rx, _child) = sidecar_cmd.args(&args).spawn().map_err(|e| format!("spawn error: {e}"))?;
86```
87 
88External binaries (`aria2c`, `mkvmerge`) are bundled via `externalBin` in `tauri.conf.json`. Reference them by name via `app.shell().sidecar()`.
89 
90Always handle `CommandEvent::Stdout`, `Stderr`, `Terminated`, and the `None` case in the event loop.
91 
92## Compile-time Config
93 
94Compile-time configuration lives in `src-tauri/app-config.json`. Embed it at compile time with `include_str!`:
95 
96```rust
97fn load_app_config() -> Result<AppConfig, String> {
98 const RAW: &str = include_str!("../app-config.json");
99 serde_json::from_str(RAW).map_err(|e| format!("app-config.json 格式错误: {e}"))
100}
101```
102 
103Define a `#[derive(serde::Deserialize)]` struct matching the JSON shape. Changes to `app-config.json` take effect on the next `cargo build`.
104 
105## HTTP Client
106 
107Always use `reqwest` for outbound HTTP. Include `use reqwest::Client;` and build clients with `reqwest::Client::builder()`.
108 
109Include reasonable `User-Agent` headers for external scraping. Use `.timeout(Duration::from_secs(N))` on requests to aria2c and external services.
110 
111```rust
112let client = reqwest::Client::builder()
113 .user_agent("Mozilla/5.0 ...")
114 .build()
115 .map_err(|e| e.to_string())?;
116```
117 
118## Clippy & Code Quality
119 
120Always respect Clippy's `disallowed_macros` and `too-many-arguments` rules. If a lint is explicitly suppressed, add `#[allow(...)]` with a comment explaining why.
121 
122Keep argument counts low. Use helper structs or `app.state()` to pull dependencies into the function body rather than adding more parameters.
123 
124Avoid `unwrap()` on locks in async contexts — use `unwrap_or_else(|e| e.into_inner())` to handle poisoned mutexes gracefully.
125 
@@ −1 +1 @@
11 ---
2−description: "HoshimiNest project overview — tech stack, directory structure, package manager, dev commands, Rust dependencies. Always apply."
3−globs: ""
4−alwaysApply: true
2+description: "Use when: writing or modifying Rust code in src-tauri/. Covers Tauri command structure, state management, external process handling, logging, and compile-time config."
3+globs: "src-tauri/**"
4+alwaysApply: false
55 ---
66  
7−# Project Identity
7+# Backend Rules
88  
9−<!-- HoshimiNest 项目身份与架构,AI 每次对话自动加载 -->
9+<!-- Tauri v2 / Rust 后端规范,操作 src-tauri/ 目录时自动加载 -->
1010  
11−## Project Name & Purpose
11+## Tauri Commands
1212  
13−HoshimiNest is a desktop anime tracking & download manager.
13+Always declare Tauri commands in `src-tauri/src/lib.rs` and register them in `run()` via `.invoke_handler(tauri::generate_handler![...])`.
1414  
15−## Tech Stack
15+Always use `#[tauri::command]` on async functions. NEVER use sync commands for I/O-bound work.
1616  
17−### Frontend
17+```rust
18+#[tauri::command]
19+async fn my_command(app: tauri::AppHandle, ...) -> Result<T, String> { ... }
20+```
1821  
19−- **React 19 + TypeScript** — functional components + hooks, strict mode
20−- **Vite 7** — bundler, dev port `1520`
21−- **Zustand** — state management (`src/store/`)
22−- **Plain CSS** — NO Tailwind, NO CSS-in-JS
23−- **Yarn** — the ONLY package manager
22+Always receive `app: tauri::AppHandle` as the first parameter. Use `app.state::<MyState>()` to access managed state.
2423  
25−### Backend
24+Prefer `Result<T, String>` as the return type for all commands. Use the `?` operator with `.map_err(|e| e.to_string())` or `.map_err(|e| format!("context: {e}"))` for error propagation.
2625  
27−- **Tauri v2** — Rust desktop shell
28−- **Key Rust crates:**
29− - `reqwest` (HTTP client, rustls-tls)
30− - `serde` + `serde_json` (serialization)
31− - `tokio` (async runtime: time, sync, macros, rt)
32− - `tauri-plugin-shell` / `tauri-plugin-opener` / `tauri-plugin-dialog`
33− - `log` + `env_logger`
26+Use `tauri::async_runtime::spawn()` for long-running background tasks spawned from commands (e.g., polling loops, sidecar process monitors). NEVER use `std::thread::spawn` or `tokio::spawn` directly.
3427  
35−### External Binaries
28+## State Management
3629  
37−Bundled with the app via `externalBin`:
30+Always use Tauri managed state (`app.manage(...)` in `run()`) for shared data. Declare state structs with thread-safe wrappers:
3831  
39−- `aria2c` — download engine
40−- `mkvmerge` — media remuxing
32+```rust
33+/// task_id → aria2 gid
34+struct GidMap(Mutex<HashMap<String, String>>);
4135  
42−## Development Environment
36+/// task_id → oneshot sender to stop the polling loop
37+struct PollStops(Mutex<HashMap<String, oneshot::Sender<()>>>);
4338  
44−- **OS**: Windows only — NEVER assume macOS/Linux/WSL paths or tools
45−- **Shell**: PowerShell (`.ps1` scripts) — NEVER write `.sh` or bash scripts
46−- **Terminal commands**: always use PowerShell syntax; NEVER use Unix-only flags or pipes
39+/// Flag to break re-entry loops
40+struct Closing(AtomicBool);
41+```
4742  
48−## Directory Structure
43+Never use global `static mut` or `lazy_static!` for mutable state — always go through `app.state::<T>()`.
4944  
50−```text
51−src/ # React frontend source
52− ├── App.css # global layout & component styles (colors reference theme.css vars)
53− ├── App.tsx # root component (topbar + sidebar nav + download settings modal)
54− ├── assets/
55− │ └── fonts/ # bundled font files
56− ├── main.tsx # React entry point
57− ├── pages/ # page-level components (one per nav item)
58− │ ├── BacklogPage.tsx # backlog / plan-to-watch
59− │ ├── DownloadPage.tsx # download manager
60− │ ├── FinishedPage.tsx # completed anime (main file, sub-logic in finished/)
61− │ ├── QueryPage.tsx # seasonal query (main page)
62− │ ├── QueryPage/ # seasonal query sub-components
63− │ ├── SearchPage.tsx # resource search (main page)
64− │ ├── SearchPage/ # resource search sub-components
65− │ ├── TracksPage.tsx # track workshop (main file, sub-logic in tracks/)
66− │ ├── WatchingPage.tsx # currently watching
67− │ ├── WatchListPage.tsx # watchlist base (main file, sub-logic in watchlist/)
68− │ ├── finished/ # completed anime sub-components
69− │ ├── tracks/ # track workshop sub-components
70− │ └── watchlist/ # watchlist sub-components
71− ├── store/ # global state
72− │ ├── downloadStore.tsx # download task context (state machine + aria2 events + localStorage)
73− │ └── watchStore.ts # watchlist localStorage helpers
74− ├── styles/
75− │ ├── fonts.css # @font-face declarations
76− │ └── theme.css # theme CSS variables
77− └── vite-env.d.ts # Vite type declarations
78−src-tauri/ # Tauri/Rust backend
79− ├── app-config.json # compile-time config (BT trackers, ports, cache)
80− ├── build.rs # Tauri build script
81− ├── capabilities/
82− │ └── default.json # Tauri ACL capability config
83− ├── icons/ # app icons
84− ├── src/
85− │ ├── lib.rs # Tauri commands + aria2 control + mkvmerge track merge
86− │ └── main.rs # Rust entry point
87− └── tauri.conf.json # Tauri app config (window/bundle/permissions)
88−scripts/ # dev & setup scripts (.ps1)
45+## Frontend Communication
46+ 
47+Always emit events to the frontend via `app.emit("event-name", payload)`. Define payload types with `#[derive(serde::Serialize, Clone)]`.
48+ 
49+```rust
50+#[derive(serde::Serialize, Clone)]
51+struct MyEventPayload {
52+ id: String,
53+ value: u8,
54+}
55+ 
56+let _ = app.emit("my-event", MyEventPayload { id, value });
8957 ```
9058  
91−## Package Rules
59+Never call `app.emit()` from a synchronous context that holds a lock — always clone the `AppHandle` and emit from an async context or after releasing the lock.
9260  
93−NEVER run `npm install` or `pnpm add`. Always use `yarn`.
61+## Logging
9462  
95−NEVER suggest re-installing these — already in `package.json`:
63+Always use the `log` crate macros: `debug!`, `info!`, `warn!`, `error!`.
9664  
97−- `@tauri-apps/api`, `@tauri-apps/plugin-dialog`, `@tauri-apps/plugin-opener`
98−- `animal-island-ui`, `bangumi-api-client`
99−- `react`, `react-dom`, `zustand`
65+Prefix log messages with a tag for filtering:
10066  
101−## Dev Commands
67+```rust
68+info!("[add_magnet] task={task_id}");
69+debug!("[{task_id}] gid handoff: {current_gid} → {new_gid}");
70+error!("[merge][{}] 合并失败: {}", job.id, msg.trim());
71+```
10272  
103−```bash
104−yarn dev # Vite dev server (frontend only, port 1520)
105−yarn tauri dev # full Tauri app in dev mode
106−yarn build # TypeScript check + Vite build
107−yarn tauri build # production Tauri bundle
108−yarn rustcheck # cargo check (Rust compilation check only)
73+Use `debug!` for detailed diagnostics, `info!` for lifecycle events, `warn!` for recoverable issues, `error!` for failures.
74+ 
75+Register `env_logger` in `run()` before the Tauri builder. Do NOT add additional logging frameworks.
76+ 
77+## External Processes
78+ 
79+Always use `tauri-plugin-shell` for spawning external binaries (aria2c, mkvmerge, etc.). NEVER use `std::process::Command` directly.
80+ 
81+```rust
82+use tauri_plugin_shell::{process::CommandEvent, ShellExt};
83+ 
84+let sidecar_cmd = app.shell().sidecar("mkvmerge").map_err(|e| format!("sidecar error: {e}"))?;
85+let (mut rx, _child) = sidecar_cmd.args(&args).spawn().map_err(|e| format!("spawn error: {e}"))?;
10986 ```
11087  
111−## Window Config
88+External binaries (`aria2c`, `mkvmerge`) are bundled via `externalBin` in `tauri.conf.json`. Reference them by name via `app.shell().sidecar()`.
11289  
113−- Window: 1360×820, non-resizable, non-maximizable, frameless (custom titlebar)
114−- App identifier: `HoshimiNest`
90+Always handle `CommandEvent::Stdout`, `Stderr`, `Terminated`, and the `None` case in the event loop.
91+ 
92+## Compile-time Config
93+ 
94+Compile-time configuration lives in `src-tauri/app-config.json`. Embed it at compile time with `include_str!`:
95+ 
96+```rust
97+fn load_app_config() -> Result<AppConfig, String> {
98+ const RAW: &str = include_str!("../app-config.json");
99+ serde_json::from_str(RAW).map_err(|e| format!("app-config.json 格式错误: {e}"))
100+}
101+```
102+ 
103+Define a `#[derive(serde::Deserialize)]` struct matching the JSON shape. Changes to `app-config.json` take effect on the next `cargo build`.
104+ 
105+## HTTP Client
106+ 
107+Always use `reqwest` for outbound HTTP. Include `use reqwest::Client;` and build clients with `reqwest::Client::builder()`.
108+ 
109+Include reasonable `User-Agent` headers for external scraping. Use `.timeout(Duration::from_secs(N))` on requests to aria2c and external services.
110+ 
111+```rust
112+let client = reqwest::Client::builder()
113+ .user_agent("Mozilla/5.0 ...")
114+ .build()
115+ .map_err(|e| e.to_string())?;
116+```
117+ 
118+## Clippy & Code Quality
119+ 
120+Always respect Clippy's `disallowed_macros` and `too-many-arguments` rules. If a lint is explicitly suppressed, add `#[allow(...)]` with a comment explaining why.
121+ 
122+Keep argument counts low. Use helper structs or `app.state()` to pull dependencies into the function body rather than adding more parameters.
123+ 
124+Avoid `unwrap()` on locks in async contexts — use `unwrap_or_else(|e| e.into_inner())` to handle poisoned mutexes gracefully.
115125  
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack