internal: Improve instructions for claude (#7921)
* Improve CLAUDE.md instructions and compact DB schema summary - Add code validation instructions (cargo check, npm run check) to all CLAUDE.md files with guidance to use only relevant feature flags - Reference backend/CLAUDE.md and frontend/CLAUDE.md paths from root - Add database querying guidance (psql commands for exact table info) - Compact summarize_schema.py output: inline columns, shorten types, one-line enums, drop indexes (use psql \d for exact info) - Fix FK parsing for multi-line ALTER TABLE statements - Result: schema summary reduced from 1514 lines/40KB to 194 lines/23KB * cleaning * fix: use prefix-based type abbreviations and filter CONSTRAINT pseudo-columns - Change TYPE_ABBREVIATIONS matching from exact to prefix-based so parametrized types (character(64) -> char(64)) and array types (integer[] -> int[], real[] -> float[]) are properly abbreviated - Skip CONSTRAINT lines inside CREATE TABLE blocks that were being incorrectly matched as columns by the column regex - Update summarized_schema.txt to reflect both changes Co-authored-by: centdix <centdix@users.noreply.github.com> --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: centdix <centdix@users.noreply.github.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
---
|
||||
description:
|
||||
globs: frontend/src/**/*.svelte
|
||||
alwaysApply: false
|
||||
name: svelte-frontend
|
||||
description: Svelte coding guidelines for the Windmill frontend. MUST use when writing or modifying code in the frontend directory.
|
||||
---
|
||||
|
||||
# Svelte 5 Best Practices
|
||||
|
||||
This guide outlines best practices for developing with Svelte 5, incorporating the new Runes API and other modern Svelte features. These rules MUST NOT be applied on svelte 4 files unless explicitly asked to do so.
|
||||
21
CLAUDE.md
21
CLAUDE.md
@@ -17,19 +17,32 @@ When implementing new features in Windmill, follow these best practices:
|
||||
|
||||
## Language-Specific Guides
|
||||
|
||||
- Backend (Rust): @backend/rust-best-practices.mdc + @backend/summarized_schema.txt
|
||||
- Frontend (Svelte 5): @frontend/svelte5-best-practices.mdc
|
||||
- Backend (Rust): see `backend/CLAUDE.md` and the `rust-backend` skill: `.claude/skills/rust-backend/SKILL.md`
|
||||
- Frontend (Svelte 5): see `frontend/CLAUDE.md` and the `svelte-frontend` skill: `.claude/skills/svelte-frontend/SKILL.md`
|
||||
|
||||
## Code Validation (MUST DO)
|
||||
|
||||
After making code changes, you MUST run the appropriate checks and fix all errors before considering the work done:
|
||||
|
||||
- **Backend**: Run `cargo check` from the `backend/` directory. Only enable the feature flags needed for the code you changed — check `backend/Cargo.toml` `[features]` section to identify which flags gate the crates/modules you modified. For example: `cargo check --features enterprise,parquet` if you only touched enterprise and parquet code.
|
||||
- **Frontend**: Run `npm run check` from the `frontend/` directory.
|
||||
|
||||
## Querying the Database
|
||||
|
||||
To query the database directly, use psql with the following connection string:
|
||||
`backend/summarized_schema.txt` provides a compact overview of all tables, columns, types, ENUMs, and foreign keys. Use it to quickly understand the data model and relationships. Note: this file is a simplified summary — it omits indexes, constraints details, and other metadata.
|
||||
|
||||
For exact table definitions (indexes, constraints, column defaults, etc.), query the database directly:
|
||||
|
||||
```bash
|
||||
psql postgres://postgres:changeme@localhost:5432/windmill
|
||||
```
|
||||
|
||||
This can be helpful for:
|
||||
Useful psql commands:
|
||||
- `\d <table_name>` — full table definition with indexes and constraints
|
||||
- `\di <table_name>*` — list indexes for a table
|
||||
- `\d+ <table_name>` — extended table info including storage and descriptions
|
||||
|
||||
This is also helpful for:
|
||||
- Inspecting database state during development
|
||||
- Testing queries before implementing them in Rust
|
||||
- Debugging data-related issues
|
||||
|
||||
@@ -49,6 +49,24 @@ Windmill uses a workspace-based architecture with multiple crates:
|
||||
- Use feature flags: `#[cfg(feature = "enterprise")]`
|
||||
- Isolate enterprise code in separate modules
|
||||
|
||||
## Code Validation (MUST DO)
|
||||
|
||||
After making backend changes, you MUST run `cargo check` and fix all errors and warnings before considering the work done.
|
||||
|
||||
Only enable the feature flags relevant to your changes — do NOT use `all_sqlx_features` as it compiles the entire codebase and is very slow. Check the `[features]` section in `Cargo.toml` to identify which flags gate the crates/modules you modified.
|
||||
|
||||
Examples:
|
||||
```bash
|
||||
# Changed core code (no feature-gated modules)
|
||||
cargo check
|
||||
|
||||
# Changed code behind the enterprise feature
|
||||
cargo check --features enterprise
|
||||
|
||||
# Changed kafka trigger code
|
||||
cargo check --features kafka
|
||||
```
|
||||
|
||||
## Git Workflow
|
||||
|
||||
- **Never push directly to main** — always create a branch and open a pull request
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This script is used to summarize the database schema.
|
||||
# You can use pg_dump to dump the schema to a file.
|
||||
# pg_dump --file "schema.sql" --host "localhost" --port "5432" --username "postgres" --no-password --format=c --large-objects --schema-only --no-owner --no-privileges --no-tablespaces --no-unlogged-table-data --no-comments --no-publications --no-subscriptions --no-security-labels --no-toast-compression --no-table-access-method --verbose --schema "public" "windmill"
|
||||
# pg_dump --file "schema.sql" --format=p --large-objects --schema-only --no-owner --no-privileges --no-tablespaces --no-unlogged-table-data --no-comments --no-publications --no-subscriptions --no-security-labels --no-toast-compression --no-table-access-method --verbose --schema "public" "postgresql://postgres:changeme@localhost:5432/windmill"
|
||||
# Then you can run python summarize_schema.py schema.sql to get the summarized schema.
|
||||
|
||||
import re
|
||||
@@ -17,6 +17,7 @@ def summarize_schema(file_path):
|
||||
# Use state variables to parse multi-line definitions
|
||||
current_table = None
|
||||
current_enum = None
|
||||
pending_alter_table = None # For multi-line ALTER TABLE ... ADD CONSTRAINT
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
for line in f:
|
||||
@@ -54,6 +55,9 @@ def summarize_schema(file_path):
|
||||
match_column = re.match(r'^"?(\w+)"?\s+([\w\d\.\[\]\(\)]+)', line)
|
||||
if match_column:
|
||||
col_name = match_column.group(1)
|
||||
# Skip CONSTRAINT definitions (e.g., CHECK, UNIQUE) mistakenly matched as columns
|
||||
if col_name.upper() == 'CONSTRAINT':
|
||||
continue
|
||||
col_type = match_column.group(2)
|
||||
tables[current_table]['columns'].append(f"{col_name} ({col_type})")
|
||||
|
||||
@@ -65,16 +69,22 @@ def summarize_schema(file_path):
|
||||
tables[current_table]['pks'].update(pk_cols)
|
||||
continue
|
||||
|
||||
# --- Parse Foreign Keys (defined outside CREATE TABLE) ---
|
||||
match_fk = re.match(r"ALTER TABLE ONLY public\.(\w+)\s+ADD CONSTRAINT \w+ FOREIGN KEY \(([\w,\s\"]+)\) REFERENCES public\.(\w+)\(([\w,\s\"]+)\);", line)
|
||||
if match_fk:
|
||||
from_table, from_cols, to_table, to_cols = match_fk.groups()
|
||||
# Clean up column names
|
||||
from_cols_clean = ', '.join([c.strip().strip('"') for c in from_cols.split(',')])
|
||||
to_cols_clean = ', '.join([c.strip().strip('"') for c in to_cols.split(',')])
|
||||
|
||||
fk_string = f"({from_cols_clean}) -> {to_table}({to_cols_clean})"
|
||||
tables[from_table]['fks'].append(fk_string)
|
||||
# --- Parse Foreign Keys (defined outside CREATE TABLE, may span 2 lines) ---
|
||||
match_alter = re.match(r"ALTER TABLE ONLY public\.(\w+)$", line)
|
||||
if match_alter:
|
||||
pending_alter_table = match_alter.group(1)
|
||||
continue
|
||||
|
||||
if pending_alter_table:
|
||||
match_fk = re.match(r"ADD CONSTRAINT \w+ FOREIGN KEY \(([\w,\s\"]+)\) REFERENCES public\.(\w+)\(([\w,\s\"]+)\)", line)
|
||||
if match_fk:
|
||||
from_cols, to_table, to_cols = match_fk.groups()
|
||||
from_cols_clean = ', '.join([c.strip().strip('"') for c in from_cols.split(',')])
|
||||
to_cols_clean = ', '.join([c.strip().strip('"') for c in to_cols.split(',')])
|
||||
fk_string = f"({from_cols_clean}) -> {to_table}({to_cols_clean})"
|
||||
tables[pending_alter_table]['fks'].append(fk_string)
|
||||
pending_alter_table = None
|
||||
continue
|
||||
|
||||
# --- Parse Index definitions ---
|
||||
match_index = re.match(r"CREATE (UNIQUE )?INDEX (\w+) ON public\.(\w+) USING (\w+) \((.+)\);", line)
|
||||
@@ -94,44 +104,73 @@ def summarize_schema(file_path):
|
||||
|
||||
return enums, tables
|
||||
|
||||
TYPE_ABBREVIATIONS = {
|
||||
'character': 'char',
|
||||
'integer': 'int',
|
||||
'bigint': 'bigint',
|
||||
'smallint': 'smallint',
|
||||
'boolean': 'bool',
|
||||
'timestamp': 'ts',
|
||||
'bytea': 'bytes',
|
||||
'real': 'float',
|
||||
'json': 'json',
|
||||
'jsonb': 'jsonb',
|
||||
'text': 'text',
|
||||
'uuid': 'uuid',
|
||||
'bit(64)': 'bit64',
|
||||
}
|
||||
|
||||
def shorten_type(col_str):
|
||||
"""Shorten a 'name (type)' string to 'name(short_type)'."""
|
||||
match = re.match(r'^(\w+) \((.+)\)$', col_str)
|
||||
if not match:
|
||||
return col_str
|
||||
name, typ = match.group(1), match.group(2)
|
||||
# Strip public. prefix from enum types
|
||||
typ = re.sub(r'^public\.', '', typ)
|
||||
# Apply abbreviations (prefix-based to handle parametrized types like character(64) and array types like integer[])
|
||||
for prefix, abbr in TYPE_ABBREVIATIONS.items():
|
||||
if typ.startswith(prefix):
|
||||
typ = abbr + typ[len(prefix):]
|
||||
break
|
||||
return f"{name}({typ})"
|
||||
|
||||
def format_output(enums, tables):
|
||||
"""
|
||||
Formats the parsed schema data into a clean, readable string.
|
||||
Formats the parsed schema data into a compact, LLM-friendly string.
|
||||
"""
|
||||
output = []
|
||||
|
||||
output.append("### Simplified Database Schema ###")
|
||||
output.append("\n--- Custom Data Types (ENUMs) ---\n")
|
||||
|
||||
output.append("# Database Schema")
|
||||
output.append("")
|
||||
output.append("## ENUMs")
|
||||
if not enums:
|
||||
output.append("No custom ENUM types found.")
|
||||
output.append("(none)")
|
||||
else:
|
||||
for name, values in sorted(enums.items()):
|
||||
output.append(f"{name}:")
|
||||
for v in values:
|
||||
output.append(f" - {v}")
|
||||
output.append("")
|
||||
output.append(f"{name}: {', '.join(values)}")
|
||||
|
||||
output.append("\n--- Tables and Relationships ---\n")
|
||||
output.append("")
|
||||
output.append("## Tables")
|
||||
if not tables:
|
||||
output.append("No tables found.")
|
||||
output.append("(none)")
|
||||
else:
|
||||
for name, data in sorted(tables.items()):
|
||||
output.append(f"TABLE: {name}")
|
||||
# Columns: inline, comma-separated, with PK marker and shortened types
|
||||
cols = []
|
||||
for col in data['columns']:
|
||||
col_short = shorten_type(col)
|
||||
col_name = col.split(' ')[0]
|
||||
marker = " (PK)" if col_name in data['pks'] else ""
|
||||
output.append(f" - {col}{marker}")
|
||||
|
||||
if col_name in data['pks']:
|
||||
col_short += " PK"
|
||||
cols.append(col_short)
|
||||
output.append(f"{name}: {', '.join(cols)}")
|
||||
|
||||
# Foreign keys on one indented line
|
||||
if data['fks']:
|
||||
output.append(" Relationships:")
|
||||
for fk in data['fks']:
|
||||
output.append(f" - {fk}")
|
||||
|
||||
if data['indexes']:
|
||||
output.append(" Indexes:")
|
||||
for idx in data['indexes']:
|
||||
output.append(f" - {idx}")
|
||||
output.append("-" * 20)
|
||||
output.append(f" FK: {' | '.join(data['fks'])}")
|
||||
|
||||
# Indexes omitted for brevity — query the database for exact index info
|
||||
|
||||
return "\n".join(output)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
|
||||
## Core Principles
|
||||
|
||||
- Follow @svelte5-best-practices.mdc for detailed guidelines
|
||||
- Follow the `svelte-frontend` skill for best practices: .claude/skills/svelte-frontend/SKILL.md
|
||||
- Use Runes ($state, $derived, $effect) for reactivity
|
||||
- Keep components small and focused
|
||||
- Always use keys in {#each} blocks
|
||||
@@ -93,6 +93,14 @@ The `resource()` utility:
|
||||
- Form components (TextInputs, ToggleButtons, Select ...) should all use the same size when put together, using the unified size system.
|
||||
- Read carefully components props JSDoc before using them
|
||||
|
||||
## Code Validation (MUST DO)
|
||||
|
||||
After making frontend changes, you MUST run the following and fix all errors and warnings before considering the work done:
|
||||
|
||||
```bash
|
||||
npm run check
|
||||
```
|
||||
|
||||
## Backend API
|
||||
|
||||
- If you need to call the backend API, you can find the available routes in ../backend/windmill-api/openapi.yaml
|
||||
|
||||
Reference in New Issue
Block a user