docs: update CLAUDE.md with enhanced development commands and web deployment instructions

- Expanded development commands for frontend and backend, including new build and test commands.
- Added detailed instructions for web deployment and server management.
- Improved organization of commands for better clarity and usability.
This commit is contained in:
Kang committed 2026-10-07 14:15:36 +08:00
1 parent 7b6c2cf544
commit 1a41b06470
1 file changed
+440 -90
+440 -90
View File
@@ -5,121 +5,471 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Development commands ## Development commands
### Root app ### Root app
- `pnpm install` — install JS dependencies - `pnpm install` — install JS dependencies
- `pnpm dev` — run the Vite frontend only - `pnpm dev` — run the Vite frontend only
- `pnpm tauri dev` — run the full desktop app in Tauri dev mode - `pnpm tauri dev` — run the full desktop app in Tauri dev mode
- `pnpm build` — run `tsc` and build the frontend with Vite - `pnpm build` — build the desktop frontend
- `pnpm build:web` — type-check and build the frontend for Web deployment
- `pnpm tauri build` — build the production desktop bundle - `pnpm tauri build` — build the production desktop bundle
- `pnpm lint` — run Biome checks for `src/**/*.ts` and `src/**/*.tsx` - `pnpm test` — run frontend Vitest tests
- `pnpm format` — apply Biome formatting to `src/**/*.ts` and `src/**/*.tsx` - `pnpm lint` — run frontend lint checks
- `pnpm format:check` — check Biome formatting without writing changes - `pnpm format` — apply frontend formatting
- `pnpm format:check` — check frontend formatting
- `pnpm i18n:check` — check locale JSON formatting - `pnpm i18n:check` — check locale JSON formatting
- `pnpm i18n:fix` — rewrite locale JSON formatting - `pnpm i18n:fix` — rewrite locale JSON formatting
- `pnpm i18n:keys` — check locale key consistency
- `pnpm version-sync` — sync version numbers across app files - `pnpm version-sync` — sync version numbers across app files
- `pnpm release` — version sync + frontend build + Tauri build - `pnpm release` — version sync + production Tauri build
### Rust / Tauri backend ### Rust / Tauri backend
- `cargo fmt --manifest-path src-tauri/Cargo.toml` — format Rust code - `cargo fmt --manifest-path src-tauri/Cargo.toml` — format Rust code
- `cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets` — lint Rust code - `cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets` — lint Rust code
- `cargo test --manifest-path src-tauri/Cargo.toml` — run backend Rust tests - `cargo test --manifest-path src-tauri/Cargo.toml` — run desktop backend tests
- `cargo test --manifest-path src-tauri/Cargo.toml <test_name>` — run a single backend Rust test - `cargo test --manifest-path src-tauri/Cargo.toml <test_name>` — run a single backend test
- `cargo test --manifest-path src-tauri/crates/otp/Cargo.toml` — run OTP crate tests - `cargo test --manifest-path src-tauri/crates/otp/Cargo.toml` — run OTP crate tests
- `cargo test --manifest-path src-tauri/crates/otp/Cargo.toml <test_name>` — run a single OTP crate test
Example single-test command: ### Web deployment
- `cargo test --manifest-path src-tauri/Cargo.toml normalizes_trailing_slashes_without_breaking_roots`
- `pnpm web:build:server` — build the Web Rust server
- `pnpm web:serve` — run the Web server locally
- `pnpm test:web` — run Web backend tests
- `pnpm test:web:e2e` — run Web deployment E2E tests
Web deployment details are documented in:
- `docs/web-deployment.md`
- `deploy/web/README.md`
### Docs site ### Docs site
- `pnpm --dir docs-site start` — build and serve the docs site locally for all locales (`/` and `/en/`)
- `pnpm --dir docs-site start:zh` — run the zh-CN docs dev server with hot reload - `pnpm --dir docs-site start` — serve all locales
- `pnpm --dir docs-site start:en` — run the English docs dev server with hot reload - `pnpm --dir docs-site start:zh` — run zh-CN docs dev server
- `pnpm --dir docs-site start:ko` — run the Korean docs dev server with hot reload - `pnpm --dir docs-site start:en` — run English docs dev server
- `pnpm --dir docs-site start:ko` — run Korean docs dev server
- `pnpm --dir docs-site build` — build the docs site - `pnpm --dir docs-site build` — build the docs site
## Big-picture architecture ## Big-picture architecture
- This is a Tauri 2 desktop app: React/TypeScript frontend in `src/`, Rust backend in `src-tauri/src/`, and IPC between them via Tauri commands/events. NyaTerm is primarily a Tauri 2 desktop application built with React, TypeScript, and Rust.
- The frontend should call Rust through the typed wrapper in `src/lib/invoke.ts`, not raw scattered `invoke()` calls where a shared wrapper already exists.
- Tauri commands are registered centrally in `src-tauri/src/lib.rs` and grouped by concern under `src-tauri/src/cmd/` (`session`, `sftp`, `connection`, `credential`, `settings`, `watcher`, `translate`, `stats`, `tunnel`, `proxy`, `otp`, `importer`, plus `app`, `backup`, `clipboard`, `cloud_sync`, `log`, and `ai`).
### Window model The repository also supports a Web deployment runtime. The React frontend is shared, while backend access is adapted per runtime.
- `src/main.tsx` decides between two boot paths:
- main window: `AppProvider` + `App.tsx`
- child windows: `ChildAppProvider` + `ChildWindowRouter`
- Child windows are opened from `src/lib/windowManager.ts` using `?window=` query params. Current child-window flows include settings, new-session, quick-command, and per-file auto-upload dialogs.
- Modal child-window focus/enable state is managed in `windowManager.ts` plus `src/ChildWindowRouter.tsx`; changes here affect cross-window UX.
### Frontend state model ```text
- `src/context/AppContext.tsx` is the main state container. It owns: React / TypeScript
- tab/session workspace state |
- persisted UI/app settings src/lib/backend/api.ts
- saved connections/groups loading and refresh |
- startup session restoration from persisted `ui.open_tabs` +----+----------------+
- `src/context/ChildAppProvider.tsx` is a lightweight provider for child windows. It only loads/saves settings and emits cross-window events; it does not manage the full tab/session workspace. | |
- `src/context/TransferContext.tsx` separately tracks file transfer progress from backend `transfer-event` notifications. Desktop Web
| |
Tauri IPC HTTP / SSE / WS
| |
src-tauri/src/ nyaterm-web
| |
+------ shared -------+
nyaterm-core
```
### Workspace / terminal model For ordinary Desktop-specific work, keep the existing Tauri architecture and do not over-generalize solely for Web.
- The terminal workspace has two distinct layers that are easy to confuse:
- `src/lib/workspaceTabs.ts` manages the persistent logical tab model. Each tab owns a recursive pane tree (`leaf` session panes and `split` panes). This is what gets serialized into `ui.open_tabs` for startup restore.
- `src/lib/tabWindows.ts` manages the runtime terminal window layout: which tabs live in each split window leaf, active tab per leaf, and window split ratios for the multi-tab/multi-split UI.
- `src/App.tsx` is the shell that composes activity bars, left/right panels, the terminal workspace, quick command / serial send bottom panels, OTP dialogs, transfer UI, recording, and lock screen.
- `src/components/terminal/XTerminal.tsx` is the xterm.js integration point. It wires Fit/Search/WebLinks addons, shell integration, command suggestions, reconnect hooks, and listens to per-session backend events.
### Backend runtime model When changing shared frontend backend abstractions or shared Rust core logic, consider both runtimes.
- `src-tauri/src/lib.rs` constructs and stores the shared backend managers in Tauri state:
- `SessionManager`
- `TunnelManager`
- `RecordingManager`
- `PendingAuthManager`
- `HostKeyVerifyManager`
- `QuickCommandsStore`
- `CloudSyncManager`
- `AgentApprovalManager` (gates AI agent command execution)
- Tauri commands are registered centrally in `src-tauri/src/lib.rs`; newer backend capability areas now include app, backup, clipboard, cloud sync, logging, and AI in addition to sessions/SFTP/settings/importers.
- `src-tauri/src/core/session.rs` contains `SessionManager`, which is the central registry for active sessions, command routing, command history, fuzzy history search, and session lifecycle events.
- Session implementations live under `src-tauri/src/core/`:
- `ssh/` for SSH transport, auth, OSC/CWD tracking, tunnels, and SFTP
- `pty.rs` for local terminal sessions
- `telnet.rs` for Telnet sessions
- `serial.rs` for serial sessions
- `recording.rs` for terminal recording
- `watcher.rs` for file-watch driven flows
- `importer.rs` for Xshell / MobaXterm / WindTerm import
- `cloud_sync.rs` for sync/backup runtime and conflict events
- `portable_snapshot.rs` for defining what sync/backup payloads include
- `ai/` for provider calls, streaming responses, structured command cards, agent execution/approval, prompt redaction, and audit/history storage
- Backend session I/O is event-driven. The Rust side emits session-specific and app-wide events such as `terminal-output-{id}`, `cwd-changed-{id}`, `session-closed-{id}`, `sessions-changed`, `connections-changed`, `command-history-changed`, `transfer-event`, `otp-request`, `cloud-sync-status-changed`, `cloud-sync-history-changed`, and `cloud-sync-conflict`.
### SSH / auth / transfer details ### Frontend backend abstraction
- SSH logic is split across `src-tauri/src/core/ssh/`:
- `client.rs` handles russh client setup, keepalive config, proxy-aware connection setup, and TOFU-style `known_hosts` verification (host-key prompts are coordinated through `HostKeyVerifyManager`)
- `auth.rs` handles saved auth loading plus keyboard-interactive / OTP flows through `PendingAuthManager` and the `otp-request` event
- `io.rs` streams terminal output and emits CWD updates
- `sftp.rs` implements remote file operations and emits transfer progress events consumed by `TransferContext`
- `tunnel.rs` manages local / remote / dynamic SSH tunnel behavior
- SFTP commands exposed to the frontend are in `src-tauri/src/cmd/sftp.rs`; the file explorer and transfer UI sit on top of these commands and events.
- File watcher / auto-upload flows bridge backend and child windows: remote files are downloaded locally, watched by `src-tauri/src/core/watcher.rs`, then uploaded back through the auto-upload UI flow.
### Persistence model Shared frontend code should normally access backend functionality through `src/lib/backend/`.
- App data lives under `~/.nyaterm/`, but the primary store is now `~/.nyaterm/nyaterm.redb` rather than a set of standalone JSON files.
- Important redb JSON documents include `settings`, `sessions`, `keys`, `passwords`, `otp`, `quick-command`, `tunnels`, `proxies`, `history`, `cloud-sync`, `cloud-sync-state`, `ai-history`, and `ai-audit`. Important files:
- Important text documents stored through the same layer include `known_hosts` and `master.key`.
- Sensitive values are encrypted before being written; cloud-sync credentials and other secret-bearing config need to stay within the existing crypto/storage helpers. - `src/lib/backend/api.ts` — common `invoke`, `listen`, and `emit` entry point
- When changing settings or workspace persistence, update both the frontend defaults (`AppContext` / `ChildAppProvider`) and the Rust persistence/migration code (`src-tauri/src/config/settings/mod.rs`, `src-tauri/src/config/ui.rs`, and related `src-tauri/src/storage.rs` / cloud-sync snapshot code when applicable). - `src/lib/backend/runtime.ts` — runtime detection and capability checks
- The app also contains legacy Dragonfly migration paths; if you change persistence formats, check that import/migration behavior still makes sense for `~/.dragonfly/` data. - `src/lib/backend/tauri.ts` — Desktop/Tauri adapter
- `src/lib/backend/http.ts` — Web HTTP/SSE/WebSocket adapter
- `src/lib/backend/platform/` — runtime-specific platform API wrappers
Avoid adding scattered direct `@tauri-apps/api` calls where an existing shared adapter should be used.
Do not assume a shared React component implies identical Desktop and Web capabilities. Check `runtime.ts` before changing capability gating.
### Desktop backend
The main Desktop backend lives under:
```text
src-tauri/src/
```
Tauri commands are registered centrally in `src-tauri/src/lib.rs` and grouped by concern under `src-tauri/src/cmd/`.
Desktop-specific functionality includes areas such as:
- native windows
- Local Shell
- Serial
- RDP
- tray
- native file integration
- global shortcuts
- updater
- OS-specific integrations
### Shared Rust core
Reusable backend/domain logic shared by Desktop and Web is located under:
```text
src-tauri/crates/nyaterm-core/
```
When backend behavior genuinely applies to both runtimes, prefer sharing it through `nyaterm-core` instead of duplicating implementations.
Do not move Desktop-only behavior into the shared core merely for architectural symmetry.
### Web backend
The Web server lives under:
```text
src-tauri/crates/nyaterm-web/
```
It provides browser-compatible backend access using HTTP, SSE, and WebSocket transports.
Web support is intentionally a subset of the Desktop application. Do not assume every Desktop capability has or needs an equivalent Web implementation.
## Window model
`src/main.tsx` decides between the main application and child-page/window flows.
The main application uses the normal app provider and `App.tsx`.
Child flows use `ChildAppProvider` and `ChildWindowRouter`.
Desktop child windows are coordinated through `src/lib/windowManager.ts`.
Native Tauri window APIs are Desktop-specific. When changing shared window-related code, ensure browser mode does not accidentally call native window APIs.
## Frontend state model
`src/context/AppContext.tsx` and `src/context/AppProvider.tsx` are central to application state.
They cover areas such as:
- tab/session workspace state
- UI and application settings
- saved connections and groups
- startup workspace restoration
`src/context/ChildAppProvider.tsx` is the lighter provider used by child-page/window flows.
`src/context/TransferContext.tsx` tracks file transfer state and backend transfer notifications.
## Workspace / terminal model
The terminal workspace has two distinct layers:
- `src/lib/workspaceTabs.ts` manages the persistent logical tab and pane model
- `src/lib/tabWindows.ts` manages the runtime multi-tab / split-window layout
Do not confuse persistent workspace state with runtime terminal layout.
`src/App.tsx` is the main application shell.
`src/components/terminal/XTerminal.tsx` is the central xterm.js integration point.
Terminal issues may involve:
```text
transport
-> backend session I/O
-> IPC / Web transport
-> frontend event handling
-> buffering / backpressure
-> xterm rendering
-> user interaction
```
Do not attribute terminal performance or correctness problems to the network, Rust, WebView, or xterm without tracing the actual path.
## Backend runtime model
Desktop backend state and managers are constructed in `src-tauri/src/lib.rs`.
Backend functionality is grouped under `src-tauri/src/core/` and related command modules.
Relevant areas include:
- SSH
- SFTP
- Local PTY
- Telnet
- Serial
- RDP
- VNC
- tunnels
- recording
- AI
- monitoring
- sync / backup
- plugins
- storage
When investigating async Rust behavior, check:
- task ownership
- channels
- cancellation
- locks
- reconnect
- shutdown
- session lifecycle
## SSH / auth / transfer details
SSH-related work should consider:
- connection lifecycle
- authentication
- saved credentials
- keyboard-interactive / OTP
- host-key verification
- known hosts
- proxies
- jump hosts
- tunnels
- SFTP
- reconnect
- session ownership
Do not bypass host-key verification or credential encryption.
File-transfer behavior differs between Desktop and Web. Desktop may use native paths, file watchers, native dialogs, and child windows, while Web uses browser-compatible upload/download and internal editing flows.
## AI Assistant
The AI Assistant includes Ask and Agent-style workflows.
Relevant areas include:
- streaming
- provider compatibility
- terminal context
- session mentions
- command cards
- command risk levels
- approvals
- approved execution
- cancellation
- history
- audit
- prompt redaction
High-risk commands must continue to use the existing approval mechanism.
Web currently supports a more limited AI capability set than Desktop. Do not expose Desktop Agent/MCP behavior in Web merely because shared UI is available.
## Persistence model
Desktop data normally lives under:
```text
~/.nyaterm/
```
The primary store is `nyaterm.redb`.
Sensitive values are encrypted before storage.
When changing persistence, consider:
- backward compatibility
- migrations
- backup/import/export
- cloud-sync snapshots
- existing legacy migration paths
Web uses its own data directory configured through `NYATERM_WEB_DATA_DIR`. Do not assume Web data lives under the Desktop user's `~/.nyaterm/`.
Security-sensitive code must not:
- store passwords or secrets in plaintext
- log credentials or private keys
- bypass master-password or server-key protections
- weaken host-key verification
- break compatibility with existing encrypted data
## Plugins
Plugin-related code spans:
```text
plugins/
src/components/plugins/
src/lib/plugins.ts
src/lib/pluginBridge.ts
src/lib/pluginIpc.ts
src-tauri/crates/nyaterm-plugin-runtime/
```
Web currently supports only a subset of plugin functionality.
Do not assume native plugin installation or execution is browser-compatible.
## Project-specific guidance ## Project-specific guidance
- If a task touches UI, prefer shadcn/ui patterns and components. The repo has an explicit Cursor rule for this in `.cursor/rules/ui.mdc`. ### UI
- shadcn is configured in `components.json`, and shared UI components live in `src/components/ui/`.
- When changing user-facing UI text, update both locale files: Prefer existing shadcn/ui patterns and components.
- `src/i18n/locales/en.json`
- `src/i18n/locales/zh-CN.json` Shared UI components live under:
- `src/i18n/locales/zh-TW.json`
- `src/i18n/locales/ko.json` ```text
- The root app currently has no dedicated frontend unit test runner configured in `package.json`; the automated tests in this repo are Rust tests under `src-tauri/` and `src-tauri/crates/otp/`. src/components/ui/
- Frontend linting includes a no-`console` check before Biome (`pnpm lint` runs `scripts/check-no-console.mjs` and `biome check src/`). ```
- Vite uses the `@` alias for `src/`.
- Tauri dev/build behavior is configured in `src-tauri/tauri.conf.json`; the dev server runs on port `1420` with HMR on `1421`. ### Internationalization
- There is a separate Docusaurus docs app in `docs-site/`. The most useful repo docs for implementation context are in `docs-site/docs/development/` (`architecture.md`, `frontend.md`, `backend.md`, `setup.md`, `contributing.md`).
- Repo docs and recent history use Conventional Commits (`feat:`, `fix:`, `perf:`, `chore:`). When changing user-facing text, update all supported locale files:
- `src/i18n/locales/en.json`
- `src/i18n/locales/zh-CN.json`
- `src/i18n/locales/zh-TW.json`
- `src/i18n/locales/ko.json`
### Frontend tests
The root frontend uses Vitest.
Tests are colocated throughout `src/` using `*.test.ts` and `*.test.tsx`.
Add or update focused tests when changing reusable frontend logic.
### Frontend linting
`pnpm lint` includes the repository no-console check.
Prefer the existing logger infrastructure over direct `console.*` calls.
### Vite
Vite uses the `@` alias for `src/`.
### Docs
There is a separate Docusaurus app under `docs-site/`.
Useful implementation documentation is under `docs-site/docs/development/`.
For Web deployment behavior, prefer the current implementation and `docs/web-deployment.md` over assumptions based on older architecture notes.
## Code modification principles
This is a long-lived project.
When modifying code:
- understand the current implementation before changing it
- prefer small, targeted changes
- avoid unrelated refactors
- preserve existing module boundaries
- reuse existing abstractions
- avoid introducing complex architecture merely to remove minor duplication
- consider backward compatibility for config, databases, backups, and persisted state
- consider Windows, macOS, and Linux differences
- preserve Desktop behavior when changing shared Web-facing code
- consider both runtimes when modifying shared backend abstractions or `nyaterm-core`
- consider cancellation, teardown, and ownership in async Rust
- do not remove compatibility logic without understanding why it exists
## Validation principles
Choose the smallest meaningful validation set.
Frontend changes may use:
```sh
pnpm test
pnpm lint
pnpm build:web
```
Desktop Rust changes may use:
```sh
cargo fmt --manifest-path src-tauri/Cargo.toml -- --check
cargo test --manifest-path src-tauri/Cargo.toml <relevant_test>
cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets
```
Web backend changes may use:
```sh
pnpm test:web
pnpm build:web
```
Use `pnpm test:web:e2e` when the change affects actual Web deployment, transport, or browser integration.
Do not run the heaviest full build by default for every small change.
If validation fails because of the environment or an unrelated existing issue, report what was run, what passed, what failed, and whether the failure appears related to the change.
Do not claim tests or builds passed unless they were actually executed successfully.
## Source analysis principles
For implementation questions:
1. identify whether the problem belongs to React UI, frontend state, backend adapter, Tauri IPC, Web transport, Rust backend, transport, or persistence
2. find the actual entry point and call sites
3. read the real implementation before drawing conclusions
4. follow the actual call chain
5. inspect Git history when compatibility logic is involved
6. for async code, inspect task ownership, channels, locks, cancellation, and lifecycle
7. do not invent files, functions, types, commands, or behavior from names alone
Typical Desktop flow:
```text
User action
-> React component / hook
-> backend adapter
-> Tauri command / event
-> Rust backend
-> transport / storage
-> frontend state update
-> UI
```
Typical Web flow:
```text
User action
-> React component / hook
-> backend adapter
-> HTTP / SSE / WebSocket
-> nyaterm-web
-> shared core / service
-> frontend state update
-> UI
```
Always verify the actual implementation in the current source tree.
## Git conventions
Repository history generally follows Conventional Commit-style subjects such as:
```text
feat:
fix:
perf:
refactor:
test:
chore:
docs:
```
Keep commits focused and consistent with recent repository history.