| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 26 | 1 | 0% |
| Commands | 0 | 26 | 0 | 0% |
| Section tags | 1 | 13 | 0 | 7% |
What each file covers
Sections
0 shared · 26 only in A · 1 only in B- − AGENTS.md
- − Project Overview
- − Prerequisites
- − Common Commands
- − Development Setup
- − Development Mode (Hot Reload)
- − Code Quality
- − Testing
- − Database Migrations
- − Architecture
- − Monorepo Structure
- − Key Packages
- − Service Layer
- − Authorization (RBAC)
- − Component Development
- − Component Structure
- − Component Testing
- − Frontend Development
- − Custom Icons
- − Testing Notes
- − Graph Testing Pattern
- − Testing Best Practices
- − Version Management
- − Pre-commit Workflow
- − Pull Request Guidelines
- − Documentation
- + CLAUDE.md
Commands
0 shared · 26 only in A · 0 only in B- − make init
- − make run_cli
- − make run_clic
- − make backend
- − make frontend
- − make format_backend
- − make format_frontend
- − make format
- − make lint
- − make unit_tests
- − make unit_tests async=false
- − uv run pytest path/to/test.py
- − uv run pytest path/to/test.py::test_name
- − make test_frontend
- − make tests_frontend
- − make alembic-revision message="Description"
- − make alembic-upgrade
- − make alembic-downgrade
- − make patch v=1.5.0
- − yarn install
- − yarn start
- − uv run git commit
- − uv run
- − uv sync --group dev --package langflow-base
- − uv sync
- − git commit
Section tags
1 shared · 13 only in A · 0 only in B- − setup
- − test
- − lint-format
- − code-style
- − architecture
- − git-pr
- − security
- − dependencies
- − database
- − ui
- − deployment
- − monorepo
- − docs
- agent-behaviour
Line diff
langflow-ai/langflow · AGENTS.md
@@ −1 @@
1# AGENTS.md
2
3This file provides guidance to AI coding agents when working with code in this repository.
4
5## Project Overview
6
7Langflow is a visual workflow builder for AI-powered agents. It has a Python/FastAPI backend, React/TypeScript frontend, and a lightweight executor CLI (lfx).
8
9## Prerequisites
10
11- **Python:** 3.10-3.14
12- **uv:** >=0.4 (Python package manager)
13- **Node.js:** >=20.19.0 (v22.12 LTS recommended)
14- **npm:** v10.9+
15- **make:** For build coordination
16
17## Common Commands
18
19### Development Setup
20```bash
21make init # Install all dependencies + pre-commit hooks
22make run_cli # Build and run Langflow (http://localhost:7860)
23make run_clic # Clean build and run (use when frontend issues occur)
24```
25
26### Development Mode (Hot Reload)
27```bash
28make backend # FastAPI on port 7860 (terminal 1)
29make frontend # Vite dev server on port 3000 (terminal 2)
30```
31
32For component development, enable dynamic loading:
33```bash
34LFX_DEV=1 make backend # Load all components dynamically
35LFX_DEV=mistral,openai make backend # Load only specific modules
36```
37
38### Code Quality
39```bash
40make format_backend # Format Python (ruff) - run FIRST before lint
41make format_frontend # Format TypeScript (biome)
42make format # Both
43make lint # mypy type checking
44```
45
46### Testing
47```bash
48make unit_tests # Backend unit tests (pytest, parallel)
49make unit_tests async=false # Sequential tests
50uv run pytest path/to/test.py # Single test file
51uv run pytest path/to/test.py::test_name # Single test
52
53make test_frontend # Jest unit tests
54make tests_frontend # Playwright e2e tests
55```
56
57### Database Migrations
58```bash
59make alembic-revision message="Description" # Create migration
60make alembic-upgrade # Apply migrations
61make alembic-downgrade # Rollback one version
62```
63
64## Architecture
65
66### Monorepo Structure
67```
68src/
69├── backend/
70│ ├── base/langflow/ # Core backend package (langflow-base)
71│ │ ├── api/ # FastAPI routes (v1/, v2/)
72│ │ ├── components/ # Built-in Langflow components
73│ │ ├── services/ # Service layer (auth, database, cache, etc.)
74│ │ ├── graph/ # Flow graph execution engine
75│ │ └── custom/ # Custom component framework
76│ └── tests/ # Backend tests
77├── frontend/ # React/TypeScript UI
78│ └── src/
79│ ├── components/ # UI components
80│ ├── stores/ # Zustand state management
81│ └── icons/ # Component icons
82└── lfx/ # Lightweight executor CLI
83```
84
85### Key Packages
86- **langflow**: Main package with all integrations
87- **langflow-base**: Core framework (api, services, graph engine)
88- **lfx**: Standalone CLI for running flows (`lfx serve`, `lfx run`)
89
90### Service Layer
91Backend services in `src/backend/base/langflow/services/`:
92- `auth/` - Authentication
93- `authorization/` - Authorization (RBAC) plugin layer — see below
94- `database/` - SQLAlchemy models and migrations
95- `cache/` - Caching layer
96- `storage/` - File storage
97- `tracing/` - Observability integrations
98
99### Authorization (RBAC)
100
101Authorization is a pluggable layer separate from authentication:
102
103- **OSS** ships the interface (`BaseAuthorizationService` in `lfx`) + a pass-through implementation (`LangflowAuthorizationService`) + the `authz_*` and `casbin_rule` DB schema + route guards.
104- Implementations register via the `lfx.services` entry point `authorization_service` in `lfx.toml` (same pattern as the SSO `auth_service`). A registered plugin reads the `authz_*` admin tables and writes compiled rules to `casbin_rule`.
105
106Default is **off**: `LANGFLOW_AUTHZ_ENABLED=false`. When enabled with only the OSS stub registered, every check returns allow — the stub is a no-op so routes stay wired and audit rows still flow. Real allow/deny requires a registered authorization plugin.
107
108Route guards live in `langflow.services.authorization.guards` (the legacy `langflow.services.authorization.utils` path re-exports them for backward compatibility):
109- `ensure_flow_permission(user, FlowAction.*, flow_id=..., flow_user_id=..., workspace_id=..., folder_id=...)` — single-flow CRUD + execute
110- `ensure_deployment_permission(user, DeploymentAction.*, deployment_id=..., deployment_user_id=..., workspace_id=..., project_id=...)`
111- `ensure_project_permission(user, ProjectAction.*, project_id=..., project_user_id=..., workspace_id=...)`
112- `ensure_knowledge_base_permission(user, KnowledgeBaseAction.*, kb_name=..., kb_user_id=...)`
113- `ensure_variable_permission(user, VariableAction.*, variable_id=..., variable_user_id=...)`
114- `ensure_file_permission(user, FileAction.*, file_id=..., file_user_id=...)`
115- `ensure_share_permission(user, ShareAction.*, share_id=..., share_user_id=...)`
116- `filter_visible_resources(user, resource_type=..., candidates=..., act=...)` — list-endpoint filter; safe no-op in OSS
117
118The enforcement request shape is `(subject, domain, object, action)`:
119- subject = `user:{uuid}`
120- domain = `project:{uuid}` → `workspace:{uuid}` → `*` (resolved by `_resolve_flow_domain`; the more specific domain wins so project-scoped grants match directly while workspace-scoped grants still flow down via plugin-side role inheritance)
121- object = `flow:{uuid}` / `deployment:{uuid}` / `project:{uuid}` / `flow:*` / etc.
122- action = `read` / `write` / `create` / `delete` / `execute` / `deploy`
123
124**Share-aware fetch (Phase 3):** route fetch helpers (`_read_flow`, `get_flow_by_id_or_endpoint_name`, `get_deployment`, project reads in `projects.py`, v2 file fetcher, variable PATCH/DELETE in `variable.py`) branch on `BaseAuthorizationService.supports_cross_user_fetch()`. The OSS pass-through reports `False` so the existing owner-scoped queries are preserved — enabling `LANGFLOW_AUTHZ_ENABLED=true` without a registered plugin cannot widen visibility. Plugins set `SUPPORTS_CROSS_USER_FETCH=True` so resources load by id alone and `ensure_*_permission` decides access; route handlers can convert a plugin-deny `HTTPException(403)` to `HTTPException(404)` via `langflow.services.authorization.fetch.deny_to_404` to preserve UUID privacy.
125
126**Share CRUD API (Phase 3):** `/api/v1/authz/shares` provides POST / GET / PATCH / DELETE on `authz_share` rows. The handler enforces an OSS floor (resource owner or superuser may administer shares for that resource) so the OSS pass-through cannot let a non-owner mint share rows. Each write fires `BaseAuthorizationService.invalidate_user` / `invalidate_all` so a registered enforcer can drop cached policy. Audit rows are written via `audit_decision` with `share:create` / `share:update` / `share:delete` actions.
127
128**Audit query API (Phase 4):** `GET /api/v1/authz/audit` (superuser-only) exposes a paginated, filterable view of `authz_audit_log`. Supports `user_id`, `resource_type`, `resource_id`, `action`, `result`, `since`, `until` filters; page size capped at 200.
129
130**Default role catalog (Phase 4):** the consolidated foundations migration `7c8d9e0f1a2b_authz_foundations` seeds the three built-in `is_system=True` roles (viewer / developer / admin) with `"{resource}:{action}"` permission slugs. OSS does not interpret these — they exist so a registered plugin's policy sync has a stable bootstrap source.
131
132## Component Development
133
134Components live in `src/backend/base/langflow/components/`. To add a new component:
135
1361. Create component class inheriting from `Component`
1372. Define `display_name`, `description`, `icon`, `inputs`, `outputs`
1383. Add to `__init__.py` (alphabetical order)
1394. Run with `LFX_DEV=1 make backend` for hot reload
140
141**IMPORTANT:** Changing a component's class name is a breaking change and should never be done. The class name serves as an identifier used to match components in saved flows and to flag them for updates in the UI. Renaming it will break existing flows that use that component.
142
143### Component Structure
144```python
145from langflow.custom import Component
146from langflow.io import MessageTextInput, Output
147
148class MyComponent(Component):
149 display_name = "My Component"
150 description = "What it does"
151 icon = "component-icon" # Lucide icon name or custom
152
153 inputs = [
154 MessageTextInput(name="input_value", display_name="Input"),
155 ]
156 outputs = [
157 Output(display_name="Output", name="output", method="process"),
158 ]
159
160 def process(self) -> Message:
161 # Component logic
162 return Message(text=self.input_value)
163```
164
165### Component Testing
166Tests go in `src/backend/tests/unit/components/`. Use base classes:
167- `ComponentTestBaseWithClient` - Components needing API access
168- `ComponentTestBaseWithoutClient` - Pure logic components
169
170Required fixtures: `component_class`, `default_kwargs`, `file_names_mapping`
171
172## Frontend Development
173
174- **React 19** + TypeScript + Vite
175- **Zustand** for state management
176- **@xyflow/react** for graph visualization
177- **Tailwind CSS** for styling
178
179### Custom Icons
1801. Create SVG component in `src/frontend/src/icons/YourIcon/`
1812. Export with `forwardRef` and `isDark` prop support
1823. Add to `lazyIconImports.ts`
1834. Set `icon = "YourIcon"` in Python component
184
185## Testing Notes
186
187- `@pytest.mark.api_key_required` - Tests requiring external API keys
188- `@pytest.mark.no_blockbuster` - Skip blockbuster plugin
189- Database tests may fail in batch but pass individually
190- Pre-commit hooks require `uv run git commit`
191- Always use `uv run` when running Python commands
192- When running tests inside a sub-package (e.g. `langflow-base`, `lfx`), sync that package's dev group first: `uv sync --group dev --package langflow-base`. The default `uv sync` only resolves the top-level workspace and may leave dev-only test deps (e.g. `fakeredis`) uninstalled.
193
194### Graph Testing Pattern
195
196Proper Graph tests follow this pattern:
1971. Build graph with connected components
1982. Connect them via `.set()` calls
1993. Call `async_start` and iterate over the results
2004. Validate the results
201
202### Testing Best Practices
203
204- Avoid mocking in tests when possible
205- Prefer real integrations for more reliable tests
206
207## Version Management
208```bash
209make patch v=1.5.0 # Update version across all packages
210```
211
212This updates: `pyproject.toml`, `src/backend/base/pyproject.toml`, `src/frontend/package.json`
213
214## Pre-commit Workflow
215
216Pre-commit hooks run ruff and biome automatically on `git commit`, so manual
217formatting is not required. To avoid an extra commit cycle when you have many
218changes:
219
2201. Run `make format_backend` once before staging - fixes most ruff issues up front.
2212. Run `uv run git commit` (the `uv run` ensures pre-commit finds the right Python).
2223. If you touched backend code, run `make unit_tests` locally for faster feedback than CI.
223
224## Pull Request Guidelines
225
226- Follow [semantic commit conventions](https://www.conventionalcommits.org/)
227- Reference any issues fixed (e.g., `Fixes #1234`)
228- Ensure all tests pass before submitting
229
230## Documentation
231
232Documentation uses Docusaurus and lives in `docs/`:
233```bash
234cd docs
235yarn install
236yarn start # Dev server on port 3000 (prompts for 3001 if 3000 is in use)
237```
238
langflow-ai/langflow · CLAUDE.md
@@ +1 @@
1# CLAUDE.md
2
3@AGENTS.md
4@.claude/CLAUDE.md
5
6This project uses [AGENTS.md](https://agents.md/) as the standard for providing context to AI coding agents. The `@AGENTS.md` import above tells Claude Code to load `AGENTS.md` automatically; other tools that natively support `AGENTS.md` will pick it up directly. The `@.claude/CLAUDE.md` import loads the local hard-rules file (gitignored) that mirrors the PostToolUse hook policy.
7
@@ −1 +1 @@
1−# AGENTS.md
1+# CLAUDE.md
22
3−This file provides guidance to AI coding agents when working with code in this repository.
3+@AGENTS.md
4+@.claude/CLAUDE.md
45
5−## Project Overview
6−
7−Langflow is a visual workflow builder for AI-powered agents. It has a Python/FastAPI backend, React/TypeScript frontend, and a lightweight executor CLI (lfx).
8−
9−## Prerequisites
10−
11−- **Python:** 3.10-3.14
12−- **uv:** >=0.4 (Python package manager)
13−- **Node.js:** >=20.19.0 (v22.12 LTS recommended)
14−- **npm:** v10.9+
15−- **make:** For build coordination
16−
17−## Common Commands
18−
19−### Development Setup
20−```bash
21−make init # Install all dependencies + pre-commit hooks
22−make run_cli # Build and run Langflow (http://localhost:7860)
23−make run_clic # Clean build and run (use when frontend issues occur)
24−```
25−
26−### Development Mode (Hot Reload)
27−```bash
28−make backend # FastAPI on port 7860 (terminal 1)
29−make frontend # Vite dev server on port 3000 (terminal 2)
30−```
31−
32−For component development, enable dynamic loading:
33−```bash
34−LFX_DEV=1 make backend # Load all components dynamically
35−LFX_DEV=mistral,openai make backend # Load only specific modules
36−```
37−
38−### Code Quality
39−```bash
40−make format_backend # Format Python (ruff) - run FIRST before lint
41−make format_frontend # Format TypeScript (biome)
42−make format # Both
43−make lint # mypy type checking
44−```
45−
46−### Testing
47−```bash
48−make unit_tests # Backend unit tests (pytest, parallel)
49−make unit_tests async=false # Sequential tests
50−uv run pytest path/to/test.py # Single test file
51−uv run pytest path/to/test.py::test_name # Single test
52−
53−make test_frontend # Jest unit tests
54−make tests_frontend # Playwright e2e tests
55−```
56−
57−### Database Migrations
58−```bash
59−make alembic-revision message="Description" # Create migration
60−make alembic-upgrade # Apply migrations
61−make alembic-downgrade # Rollback one version
62−```
63−
64−## Architecture
65−
66−### Monorepo Structure
67−```
68−src/
69−├── backend/
70−│ ├── base/langflow/ # Core backend package (langflow-base)
71−│ │ ├── api/ # FastAPI routes (v1/, v2/)
72−│ │ ├── components/ # Built-in Langflow components
73−│ │ ├── services/ # Service layer (auth, database, cache, etc.)
74−│ │ ├── graph/ # Flow graph execution engine
75−│ │ └── custom/ # Custom component framework
76−│ └── tests/ # Backend tests
77−├── frontend/ # React/TypeScript UI
78−│ └── src/
79−│ ├── components/ # UI components
80−│ ├── stores/ # Zustand state management
81−│ └── icons/ # Component icons
82−└── lfx/ # Lightweight executor CLI
83−```
84−
85−### Key Packages
86−- **langflow**: Main package with all integrations
87−- **langflow-base**: Core framework (api, services, graph engine)
88−- **lfx**: Standalone CLI for running flows (`lfx serve`, `lfx run`)
89−
90−### Service Layer
91−Backend services in `src/backend/base/langflow/services/`:
92−- `auth/` - Authentication
93−- `authorization/` - Authorization (RBAC) plugin layer — see below
94−- `database/` - SQLAlchemy models and migrations
95−- `cache/` - Caching layer
96−- `storage/` - File storage
97−- `tracing/` - Observability integrations
98−
99−### Authorization (RBAC)
100−
101−Authorization is a pluggable layer separate from authentication:
102−
103−- **OSS** ships the interface (`BaseAuthorizationService` in `lfx`) + a pass-through implementation (`LangflowAuthorizationService`) + the `authz_*` and `casbin_rule` DB schema + route guards.
104−- Implementations register via the `lfx.services` entry point `authorization_service` in `lfx.toml` (same pattern as the SSO `auth_service`). A registered plugin reads the `authz_*` admin tables and writes compiled rules to `casbin_rule`.
105−
106−Default is **off**: `LANGFLOW_AUTHZ_ENABLED=false`. When enabled with only the OSS stub registered, every check returns allow — the stub is a no-op so routes stay wired and audit rows still flow. Real allow/deny requires a registered authorization plugin.
107−
108−Route guards live in `langflow.services.authorization.guards` (the legacy `langflow.services.authorization.utils` path re-exports them for backward compatibility):
109−- `ensure_flow_permission(user, FlowAction.*, flow_id=..., flow_user_id=..., workspace_id=..., folder_id=...)` — single-flow CRUD + execute
110−- `ensure_deployment_permission(user, DeploymentAction.*, deployment_id=..., deployment_user_id=..., workspace_id=..., project_id=...)`
111−- `ensure_project_permission(user, ProjectAction.*, project_id=..., project_user_id=..., workspace_id=...)`
112−- `ensure_knowledge_base_permission(user, KnowledgeBaseAction.*, kb_name=..., kb_user_id=...)`
113−- `ensure_variable_permission(user, VariableAction.*, variable_id=..., variable_user_id=...)`
114−- `ensure_file_permission(user, FileAction.*, file_id=..., file_user_id=...)`
115−- `ensure_share_permission(user, ShareAction.*, share_id=..., share_user_id=...)`
116−- `filter_visible_resources(user, resource_type=..., candidates=..., act=...)` — list-endpoint filter; safe no-op in OSS
117−
118−The enforcement request shape is `(subject, domain, object, action)`:
119−- subject = `user:{uuid}`
120−- domain = `project:{uuid}` → `workspace:{uuid}` → `*` (resolved by `_resolve_flow_domain`; the more specific domain wins so project-scoped grants match directly while workspace-scoped grants still flow down via plugin-side role inheritance)
121−- object = `flow:{uuid}` / `deployment:{uuid}` / `project:{uuid}` / `flow:*` / etc.
122−- action = `read` / `write` / `create` / `delete` / `execute` / `deploy`
123−
124−**Share-aware fetch (Phase 3):** route fetch helpers (`_read_flow`, `get_flow_by_id_or_endpoint_name`, `get_deployment`, project reads in `projects.py`, v2 file fetcher, variable PATCH/DELETE in `variable.py`) branch on `BaseAuthorizationService.supports_cross_user_fetch()`. The OSS pass-through reports `False` so the existing owner-scoped queries are preserved — enabling `LANGFLOW_AUTHZ_ENABLED=true` without a registered plugin cannot widen visibility. Plugins set `SUPPORTS_CROSS_USER_FETCH=True` so resources load by id alone and `ensure_*_permission` decides access; route handlers can convert a plugin-deny `HTTPException(403)` to `HTTPException(404)` via `langflow.services.authorization.fetch.deny_to_404` to preserve UUID privacy.
125−
126−**Share CRUD API (Phase 3):** `/api/v1/authz/shares` provides POST / GET / PATCH / DELETE on `authz_share` rows. The handler enforces an OSS floor (resource owner or superuser may administer shares for that resource) so the OSS pass-through cannot let a non-owner mint share rows. Each write fires `BaseAuthorizationService.invalidate_user` / `invalidate_all` so a registered enforcer can drop cached policy. Audit rows are written via `audit_decision` with `share:create` / `share:update` / `share:delete` actions.
127−
128−**Audit query API (Phase 4):** `GET /api/v1/authz/audit` (superuser-only) exposes a paginated, filterable view of `authz_audit_log`. Supports `user_id`, `resource_type`, `resource_id`, `action`, `result`, `since`, `until` filters; page size capped at 200.
129−
130−**Default role catalog (Phase 4):** the consolidated foundations migration `7c8d9e0f1a2b_authz_foundations` seeds the three built-in `is_system=True` roles (viewer / developer / admin) with `"{resource}:{action}"` permission slugs. OSS does not interpret these — they exist so a registered plugin's policy sync has a stable bootstrap source.
131−
132−## Component Development
133−
134−Components live in `src/backend/base/langflow/components/`. To add a new component:
135−
136−1. Create component class inheriting from `Component`
137−2. Define `display_name`, `description`, `icon`, `inputs`, `outputs`
138−3. Add to `__init__.py` (alphabetical order)
139−4. Run with `LFX_DEV=1 make backend` for hot reload
140−
141−**IMPORTANT:** Changing a component's class name is a breaking change and should never be done. The class name serves as an identifier used to match components in saved flows and to flag them for updates in the UI. Renaming it will break existing flows that use that component.
142−
143−### Component Structure
144−```python
145−from langflow.custom import Component
146−from langflow.io import MessageTextInput, Output
147−
148−class MyComponent(Component):
149− display_name = "My Component"
150− description = "What it does"
151− icon = "component-icon" # Lucide icon name or custom
152−
153− inputs = [
154− MessageTextInput(name="input_value", display_name="Input"),
155− ]
156− outputs = [
157− Output(display_name="Output", name="output", method="process"),
158− ]
159−
160− def process(self) -> Message:
161− # Component logic
162− return Message(text=self.input_value)
163−```
164−
165−### Component Testing
166−Tests go in `src/backend/tests/unit/components/`. Use base classes:
167−- `ComponentTestBaseWithClient` - Components needing API access
168−- `ComponentTestBaseWithoutClient` - Pure logic components
169−
170−Required fixtures: `component_class`, `default_kwargs`, `file_names_mapping`
171−
172−## Frontend Development
173−
174−- **React 19** + TypeScript + Vite
175−- **Zustand** for state management
176−- **@xyflow/react** for graph visualization
177−- **Tailwind CSS** for styling
178−
179−### Custom Icons
180−1. Create SVG component in `src/frontend/src/icons/YourIcon/`
181−2. Export with `forwardRef` and `isDark` prop support
182−3. Add to `lazyIconImports.ts`
183−4. Set `icon = "YourIcon"` in Python component
184−
185−## Testing Notes
186−
187−- `@pytest.mark.api_key_required` - Tests requiring external API keys
188−- `@pytest.mark.no_blockbuster` - Skip blockbuster plugin
189−- Database tests may fail in batch but pass individually
190−- Pre-commit hooks require `uv run git commit`
191−- Always use `uv run` when running Python commands
192−- When running tests inside a sub-package (e.g. `langflow-base`, `lfx`), sync that package's dev group first: `uv sync --group dev --package langflow-base`. The default `uv sync` only resolves the top-level workspace and may leave dev-only test deps (e.g. `fakeredis`) uninstalled.
193−
194−### Graph Testing Pattern
195−
196−Proper Graph tests follow this pattern:
197−1. Build graph with connected components
198−2. Connect them via `.set()` calls
199−3. Call `async_start` and iterate over the results
200−4. Validate the results
201−
202−### Testing Best Practices
203−
204−- Avoid mocking in tests when possible
205−- Prefer real integrations for more reliable tests
206−
207−## Version Management
208−```bash
209−make patch v=1.5.0 # Update version across all packages
210−```
211−
212−This updates: `pyproject.toml`, `src/backend/base/pyproject.toml`, `src/frontend/package.json`
213−
214−## Pre-commit Workflow
215−
216−Pre-commit hooks run ruff and biome automatically on `git commit`, so manual
217−formatting is not required. To avoid an extra commit cycle when you have many
218−changes:
219−
220−1. Run `make format_backend` once before staging - fixes most ruff issues up front.
221−2. Run `uv run git commit` (the `uv run` ensures pre-commit finds the right Python).
222−3. If you touched backend code, run `make unit_tests` locally for faster feedback than CI.
223−
224−## Pull Request Guidelines
225−
226−- Follow [semantic commit conventions](https://www.conventionalcommits.org/)
227−- Reference any issues fixed (e.g., `Fixes #1234`)
228−- Ensure all tests pass before submitting
229−
230−## Documentation
231−
232−Documentation uses Docusaurus and lives in `docs/`:
233−```bash
234−cd docs
235−yarn install
236−yarn start # Dev server on port 3000 (prompts for 3001 if 3000 is in use)
237−```
6+This project uses [AGENTS.md](https://agents.md/) as the standard for providing context to AI coding agents. The `@AGENTS.md` import above tells Claude Code to load `AGENTS.md` automatically; other tools that natively support `AGENTS.md` will pick it up directly. The `@.claude/CLAUDE.md` import loads the local hard-rules file (gitignored) that mirrors the PostToolUse hook policy.
2387
