Files
windmill/CLAUDE.md
hugocasa 96229575e6 chore: dev tooling — wm-ts-nav navigator, format hooks, review skill (#8337)
* chore: remove wm-cursor, add local-review skill, update PR skill for EE

- Remove the unused wm-cursor script and all references to it in
  README_WORKMUX_DEV.md and worktree-common.sh
- Add /local-review skill for code review (bugs + CLAUDE.md compliance)
- Add EE companion PR workflow to the /pr skill

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: add wm-ts-nav tree-sitter navigator and fix format hooks

- Add wm-ts-nav: standalone tree-sitter code navigator with SQLite index
  for fast symbol search, definition lookup, and file outlines across
  Rust, TypeScript, and Svelte files (~12ms warm, ~1s cold for 482 files)
- Fix format hooks: surface errors instead of swallowing with 2>/dev/null,
  use direct prettier path with svelte plugin, add success feedback
- Add wm-ts-nav commands to settings allow list
- Document wm-ts-nav usage in CLAUDE.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(wm-ts-nav): add refs command and --parent filter

- refs: find usages of a symbol in code, skipping comments and strings
  (tree-sitter AST walk, ~46ms for 482 files vs grep's 4ms but no noise)
- --parent filter on search: find all methods on a type across all files
  (e.g. search "%" --kind function --parent ServiceName)
- Update CLAUDE.md with clearer when-to-use guidance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(wm-ts-nav): index refs in DB with import-path resolution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(wm-ts-nav): add body, callers, callees commands and refs --file/--caller

- body: extract a symbol's source code from disk using indexed line ranges
- callers: cross-file call graph via SQL join of refs + symbols tables
- callees: list all identifiers referenced within a symbol's body
- refs --file: scope results to files matching a substring
- refs --caller: annotate each ref with the containing function name

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat(wm-ts-nav): add auto-rebuilding wrapper script

The `wm-ts-nav/nav` wrapper checks if source files are newer than the
binary and rebuilds automatically. Invoked via `sh wm-ts-nav/nav` to
avoid needing executable permissions after clone.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: tighten CLAUDE.md nav section for actionable guidance

Remove redundant question→command mapping, latency numbers, and
excessive examples. Lead with "prefer wm-ts-nav over Read to save
context window" and keep only the patterns that change behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: revert backend/Cargo.lock to main

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: promote wm-ts-nav in workflow, copy binary to worktrees

- CLAUDE.md: integrate wm-ts-nav into Workflow step 1 and Core
  Principles so agents use outline/body before full file reads
- workmux: copy built binary via files.copy
- worktree-common.sh: copy binary in wm_copy_dependencies for webmux

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(wm-ts-nav): fix double indexing, add TSX grammar, remove needless clone

- Reuse index stats from the pre-query update instead of indexing twice
  on the Index command
- Add Lang::Tsx variant so .tsx/.jsx files use LANGUAGE_TSX instead of
  LANGUAGE_TYPESCRIPT (Svelte stays on TS since script blocks are pure TS)
- Remove source.clone() for non-Svelte files — move directly instead

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(wm-ts-nav): fix svelte line numbers, add class methods, innermost caller

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:07:49 +00:00

93 lines
4.8 KiB
Markdown

# Windmill
Open-source platform for internal tools, workflows, API integrations, background jobs, and UIs. Rust backend + Svelte 5 frontend.
## Workflow
1. **Understand**: Before coding, use `wm-ts-nav` to explore (see Code Navigation below). Use `outline` to understand file structure, `body` to read specific symbols, `def`/`callers`/`callees` to trace code. Read `docs/` for domain context.
2. **Plan**: For non-trivial changes, use plan mode. For large features, break into reviewable stages
3. **Execute**: Follow coding patterns from skills (`rust-backend`, `svelte-frontend`)
4. **Validate**: After every change, run the appropriate checks per `docs/validation.md`
## Documentation
- **Validation**: `docs/validation.md` — what checks to run based on what you changed
- **Enterprise**: `docs/enterprise.md` — EE file conventions and PR workflow
- **Backend patterns**: use the `rust-backend` skill when writing Rust code
- **Frontend patterns**: use the `svelte-frontend` skill when writing Svelte code. Do NOT edit svelte files unless you have read that skill.
- **Code review**: use `/local-review` to review a PR for bugs and CLAUDE.md compliance
- **Domain guides**: `.claude/skills/native-trigger/` and `frontend/tutorial-system-guide.mdc`
- **Brand/UI guidelines**: `frontend/brand-guidelines.md`
## Dev Environment
- **Backend**: `cargo run` from `backend/` (API at http://localhost:8000)
- **Frontend**: `REMOTE=http://localhost:8000 npm run dev` from `frontend/` (port 3000+)
- **DB**: `psql postgres://postgres:changeme@localhost:5432/windmill`
- **Login**: `admin@windmill.dev` / `changeme`
- **Instance settings**: navigate to `/#superadmin-settings`
## Banned Patterns
### `$bindable(default_value)` on optional props
Using `$bindable(default_value)` on props that can be `undefined` is **banned**. This pattern causes subtle bugs because the default value masks the `undefined` state.
**Bad:**
```svelte
let { my_prop = $bindable(default_value) }: { my_prop?: string } = $props()
```
**Correct alternatives:**
1. **Use `$derived` with nullish coalescing** — handle the potential `undefined` at the usage site:
```svelte
let { my_prop = $bindable() }: { my_prop?: string } = $props()
let effective_value = $derived(my_prop ?? default_value)
```
2. **Create a `useMyPropState()` helper** — encapsulate the undefined-handling logic in a reusable function and call it higher in the component tree, so the child component always receives a defined value.
## Code Navigation
`wm-ts-nav` is an AST-aware code navigator. Use **Grep** for regex/pattern search. Use **wm-ts-nav** for structural queries — it skips comments/strings and understands symbol boundaries.
**Prefer wm-ts-nav over Read** to save context window:
- `outline <file>` instead of reading a full file — understand structure first, then `body` or Read for specifics
- `body "X"` instead of reading a full file to see one function/struct
- `refs "X" --caller` instead of reading files to find which function contains each reference
- `callers "X"` / `callees "X"` for call-graph questions
```bash
NAV="sh wm-ts-nav/nav"
# Use --root backend for Rust, --root frontend/src for TS/Svelte
$NAV --root backend outline backend/path/to/file.rs # file structure
$NAV --root backend def "ServiceName" # find definition
$NAV --root backend body "decrypt_oauth_data" # extract source code
$NAV --root backend search "%" --parent ServiceName # methods on a type
$NAV --root backend search "Trigger" --kind struct # find by kind
$NAV --root backend refs "X" --file handler.rs --caller # scoped refs with caller
$NAV --root backend callers "X" # who calls X?
$NAV --root backend callees "X" # what does X call?
```
**Limitations** — syntax-level analysis, no type inference:
- Import paths are stored literally — `crate::X` and `super::X` pointing to the same type won't be linked
- Re-export chains (`pub use`) aren't followed — refs through different re-export paths won't connect
- Trait methods can't be resolved to their trait definition
- Nested `use` trees (`use foo::{bar::{A, B}, baz::C}`) aren't parsed correctly
- Glob imports (`use foo::*`) — refs won't show import origin
- Macro-generated symbols (e.g. `sqlx::FromRow`) — invisible to tree-sitter
- Single-char identifiers — intentionally filtered out of refs
- `callees` shows all identifiers in a function body, not just actual calls
- `import * as ns` namespace imports — member accesses through `ns.X` aren't resolved
## Core Principles
- **Use `outline`/`body` to explore, then `Read` with offset/limit from the results before editing** — avoid reading full files
- Search for existing code to reuse before writing new code
- Follow established patterns in the codebase
- Keep changes focused — don't refactor beyond what's asked