CLAUDE.md · moltis-org/moltis
CLAUDE.md from moltis-org/moltis: 534 lines covering Cargo Features, Workspace Dependencies, Config Schema and Validation, Rust Style and Idioms and more.
Template by moltis-org
Install
Works with Claude Code. Read the repository before you give any tool access to your data.
curl -fsSL https://raw.githubusercontent.com/moltis-org/moltis/main/CLAUDE.md -o CLAUDE.md
Read it and adapt it to your project before use.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: prompt-engineering
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
What's in it
A CLAUDE.md file: project memory Claude Code loads at the start of every session.
- For
- Claude Code
- Length
- 534 lines
- File
CLAUDE.md
Sections
- Cargo Features
- Workspace Dependencies
- Config Schema and Validation
- Rust Style and Idioms
- Build Commands
- Web UI (TypeScript + Preact + Vite)
- API Namespace Convention
- Channel Message Handling
- Adding Channels
- Authentication Architecture
- Testing
- Code Quality
- Sandbox Architecture
- Logging Levels
- Security
- Data and Config Directories
- Database Migrations
- Provider Implementation
- Changelog
- Git Workflow
First lines (shown under the repo's MIT license)
---
description: "Moltis engineering guide for Claude/Codex agents: Rust architecture, testing, security, and release workflows"
alwaysApply: true
---
# CLAUDE.md
Rust version of openclaw ([docs](https://docs.openclaw.ai), [code](https://github.com/openclaw/openclaw)).
All code must have tests with high coverage. Always check for security.
## Cargo Features
Enable new feature flags **by default** in `crates/cli/Cargo.toml` (opt-out, not opt-in):
```toml
[features]
default = ["foo", ...]
foo = ["moltis-gateway/foo"]
```
## Workspace Dependencies
Add new crates to `[workspace.dependencies]` in root `Cargo.toml`, reference with `{ workspace = true }`.
Never add versions directly in crate `Cargo.toml`. Use latest stable crates.io version.
## Config Schema and Validation
When adding/renaming fields in `MoltisConfig` (`crates/config/src/schema.rs`), also update
`build_schema_map()` in `crates/config/src/validate.rs`. New enum variants for string-typed
fields need updates in `check_semantic_warnings()`.
## Rust Style and Idioms
- **File size limit: 1,500 lines.** CI enforces this via `scripts/check-file-size.sh`. Split large files into modules by domain. Existing oversize files are allowlisted for incremental decomposition.
- Do not add implementation code to `mod.rs` or `lib.rs`. Keep those files for module wiring, exports, and crate setup, move real logic into dedicated sibling modules.
- Use traits for behaviour boundaries. Prefer generics for hot paths, `dyn Trait` for heterogeneous/runtime dispatch.
- Derive `Default` when all fields have sensible defaults.
- Use concrete types (`struct`/`enum`) over `serde_json::Value` wherever shape is known.
- **Match on types, never strings.** Only convert to strings at serialization/display boundaries.
- Prefer `From`/`Into`/`TryFrom`/`TryInto` over manual conversions. Ask before adding manual conversion paths.
- **DRY cross-crate types:** When two crates need the same enum/struct, define it once in the lower-level crate and re-export via `pub type Alias = other_crate::Type` from the higher-level one. Never duplicate enums across crates or round-trip through strings (`parse(&id.to_string())`) to convert between mirror types.
- Prefer streaming over non-streaming API calls.
- Run independent async work concurrently (`tokio::join!`, `futures::join_all`).
- Never use `block_on` inside async context.
- **Forbidden:** `Mutex<()>` / `Arc<Mutex<()>>` — mutex must guard actual state.
- Use `anyhow::Result` for app errors, `thiserror` for library errors. Propagate with `?`.
- **Never `.unwrap()`/`.expect()` in production.** Workspace lints deny these. Use `?`, `ok_or_else`, `unwrap_or_default`, `unwrap_or_else(|e| e.into_inner())` for locks.
- Use `time` crate (workspace dep) for date/time — no manual epoch math or magic constants like `86400`.
- Prefer `chrono` only if already imported in the crate; default to `time` for new code.
- Prefer crates over subprocesses (`std::process::Command`). Use subprocesses only when no mature crate exists.
- Prefer guard clauses (early returns) over nested `if` blocks.
- Prefer iterators/combinators over manual loops. Use `Cow<'_, str>` when allocation is conditional.
- Keep public API surfaces small. Use `#[must_use]` where return values matter.
### Tracing and Metrics
All crates must have `tracing` and `metrics` features, gated with `#[cfg(feature = "...")]`.
Use `tracing::instrument` on async functions. Record metrics at key points (counts, durations, errors).
See `docs/metrics-and-tracing.md`.
## Build Commands
```bash
cargo build # Debug build
cargo build --release # Release build
cargo run / cargo run --release
```
## Web UI (TypeScript + Preact + Vite)
TypeScript/TSX source in `crates/web/ui/src/`, built with Vite to `crates/web/src/assets/dist/`.
CSS and static assets in `crates/web/src/assets/`. Release mode embeds via `include_dir!`.
Generated assets (`dist/`, `css/style.css`, `style.css`, `sw.js`) are gitignored.
Run `just build-web-assets` to generate them (requires Node.js).
A `build.rs` check warns (debug) or fails (release/embedded-assets) if they are missing.
See `docs/src/frontend.md` for the full architecture guide.
### Build Commands
```bash
cd crates/web/ui
npm run build # Vite: TS/TSX → dist/
npm run build:css # Tailwind: input.css → ../src/assets/css/style.css
npm run build:sw # esbuild: src/sw.ts → ../src/assets/sw.js
npm run build:all # All three above
npm run dev # Vite watch mode (rebuilds on save)
npx tsc --noEmit # Type check (strict, must be 0 errors)
```
**After changing TS/TSX files**, always:
1. `biome check --write crates/web/ui/src/`
2. `cd crates/web/ui && npm run build`
3. `cd crates/web/ui && npx tsc --noEmit`
### TypeScript Rules
- **File size limit: 1,500 lines** (same rule as Rust). Split large files into modules by domain.
- Pages: extract sections/modals into `pages/sections/`, `pages/channels/`, `pages/chat/`, etc.
- Utilities: extract sub-modules into sibling directories (`providers/`, `sessions/`, `ws/`).
- Keep shared signals, types, and re-exports in the main file; move logic into sub-modules.
- All UI code is **TypeScript** with **JSX** (Preact). No HTM tagged templates.
- Add typed Props interfaces for all Preact components.
- Use `@preact/signals` with generic type parameters: `signal<string[]>([])`.
- Prefer typed interfaces over `Record<string, unknown>` — define concrete shapes where property access is known.
- Use `targetValue(e)` / `targetChecked(e)` from `typed-events.ts` for form event handlers.
- No `any` types — use `unknown` with type guards or specific interfaces.
- Use shared components from `components/forms/` (TextField, SaveButton, ListItem, Badge, TabBar, etc.).
### CSS Rules
- **Always use Tailwind classes** instead of inline `style="..."`.
- Reuse CSS classes from `components.css`: `provider-btn`, `provider-btn-secondary`, `provider-btn-danger`.
- Match button heights/text sizes when elements sit together.
- **Rebuild Tailwind** after adding new classes: `cd crates/web/ui && npm run build:css`.
### Adding Settings Nav Icons
Settings sidebar icons use `::before` pseudo-elements in `components.css`, **not** the `icon`
JSX property in the `sections` array. When adding a new settings section:
1. Create the SVG mask in `crates/web/src/assets/icons/masks/` with `fill="black"` (not `currentColor`)
2. Add `.icon-<name>` class in `crates/web/ui/input.css` under the mask-image icons section
3. **Also add** `.settings-nav-item[data-section="<id>"]::before` in `crates/web/src/assets/css/components.css`
pointing to the SVG — without this the icon renders as a black square
4. The `icon: <span className="icon icon-<name>" />` in `SettingsPage.tsx` is a fallback only
### E2E Test Shims
E2E tests dynamically import individual JS modules (`js/state.js`, `js/helpers.js`, etc.).
With Vite bundling, these don't exist as standalone files. Shim files in `src/assets/js/`
proxy to `window.__moltis_modules` (populated by `app.tsx`). When adding new modules that
tests import, add a shim file and expose the module in `app.tsx`.
### Selection Cards
Use clickable cards (`.model-card`, `.backend-card` in `input.css`) instead of dropdowns for option selection.
States: `.selected`, `.disabled`, default. Badges: `.recommended-badge`, `.tier-badge`.
### Provider Config Storage
Provider keys in `~/.config/moltis/provider_keys.json` via `KeyStore` in `provider_setup.rs`.
When adding fields, update: `ProviderConfig` struct, `available()` response, `save_key()`.
### Server-Injected Data (gon pattern)
For server data needed at page load: add to `GonData` in `server.rs` / `build_gon_data()`.
TS side: `import * as gon from "./gon"` — use `gon.get()`, `gon.onChange()`, `gon.refresh()`.
Types in `crates/web/ui/src/types/gon.ts` mirror the Rust `GonData` struct.
Never inject inline `<script>` tags or build HTML in Rust.
### Event Bus
Server events via WebSocket: `import { onEvent } from "./events"`. Returns unsubscribe function.
Do **not** use `window.addEventListener`/`CustomEvent` for server events.
## API Namespace Convention
Each UI tab gets its own API namespace: REST `/api/<feature>/...` and RPC `<feature>.*`.
Never merge features into a single endpoint.
## Channel Message HandlingSignals
- Stars
- 2,906
- Forks
- 359
- Open issues
- 76
- Last commit (this folder)
- Aug 20, 2026 (2 months ago)
- Last release
- Oct 23, 2026 (6 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/moltis-org/moltis
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from moltis-org
Cite this page
CLAUDE.md · moltis-org/moltis. Agent Mart. https://agentmart.dev/templates/moltis-org-moltis-claude-md (last updated 2026-10-24)