Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .agents/skills/db-migrate/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ The lint flags risky *shapes*; it cannot know whether a given drop is *safe righ
```
The reason must be specific and name the PR/version that removed the dependency. An empty reason fails the lint.
- **Warnings** (`data-backfill`): non-blocking, but confirm the batching/idempotency before merging.
4. Verify locally: `cd packages/db && bun run db:migrate` against a dev DB.
4. Regenerate the test schema mock: `bun run scripts/generate-schema-mock.ts` (`check:schema-mock` in `check:audits` fails after any `schema.ts` change until you do).
5. Re-run `(cd packages/db && bunx drizzle-kit generate)` once your migration is written: it must report no schema changes and write no new file, or CI fails on the schema and migrations disagreeing.
6. Verify locally: `cd packages/db && bun run db:migrate` against a dev DB.

## Hard rule

Expand Down
10 changes: 10 additions & 0 deletions .claude/rules/constitution.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
---
description: Sim product language, positioning, and tone guidelines
paths:
- "apps/sim/app/(landing)/**"
- "apps/sim/lib/landing/**"
- "apps/sim/content/**"
- "apps/sim/emails/broadcasts/**"
- "apps/sim/app/layout.tsx"
- "apps/sim/app/manifest.ts"
- "apps/sim/app/llms*.txt/**"
Comment thread
waleedlatif1 marked this conversation as resolved.
- "apps/sim/app/changelog.xml/**"
- "apps/docs/**"
---

# Sim — Language & Positioning
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/emcn-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ paths:

# EMCN Components

Import components, `cn`, and tokens from the `@sim/emcn` barrel; icons come from the `@sim/emcn/icons` subpath, and CSS modules from their file path. Never deep-import other component subpaths. The **chip family** is the platform's primary chrome — always reach for it over the legacy primitives it is progressively replacing (`Input`→`ChipInput`, `Textarea`→`ChipTextarea`, `Modal`→`ChipModal`, `Select`/`Combobox`→`ChipSelect`/`ChipCombobox`/`ChipDropdown`, `Switch`→`ChipSwitch`, date field→`ChipDatePicker`). For context/action menus the canonical control is `DropdownMenu` — the standard menu (not a chip, and never a hand-rolled popover).
Import components, `cn`, and tokens from the `@sim/emcn` barrel; icons come from the `@sim/emcn/icons` subpath, and CSS modules from their file path. Never deep-import other component subpaths. The **chip family** is the platform's primary chrome — always reach for it over the legacy primitives it is progressively replacing (`Input`→`ChipInput`, `Textarea`→`ChipTextarea`, `Modal`→`ChipModal`, `Select`/`Combobox`→`ChipSelect`/`ChipCombobox`/`ChipDropdown`, date field→`ChipDatePicker`). `ChipSwitch` is a segmented choice between options, not a replacement for `Switch`: a boolean on/off toggle stays `Switch`. For context/action menus the canonical control is `DropdownMenu` — the standard menu (not a chip, and never a hand-rolled popover).

## Chip chrome — single source of truth

Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/sim-queries.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,4 @@ Hooks import named type aliases from `@/lib/api/contracts/**` and never import `

## Enforcement

`scripts/check-react-query-patterns.ts` (`bun run check:react-query`, run in CI) statically enforces these conventions: every `useQuery`/`useInfiniteQuery`/`useSuspenseQuery` declares an explicit `staleTime`, inline `queryFn`s destructure `signal`, `queryKey`s reference a colocated factory rather than an inline literal, every `*Keys` factory in `hooks/queries/**` exposes an `all` root key, and every identifier the `queryFn` forwards into the fetch also appears in the `queryKey` (`key-fetch-arg-drift`). `hooks/queries/**` is a zero-tolerance zone; the rest of `apps/sim/**` is ratcheted against `scripts/check-react-query-patterns.baseline.json`. For a genuine exception, put `// rq-lint-allow: <reason>` on the line directly above the flagged construct.
`scripts/check-react-query-patterns.ts` (`bun run check:react-query`, run in CI) statically enforces these conventions: every `useQuery`/`useInfiniteQuery`/`useSuspenseQuery` declares an explicit `staleTime`, inline `queryFn`s destructure `signal`, `queryKey`s reference a colocated factory rather than an inline literal, every `*Keys` factory in `hooks/queries/**` exposes an `all` root key, and every identifier the `queryFn` forwards into the fetch also appears in the `queryKey` (`key-fetch-arg-drift`). Any violation under `apps/sim/**` fails. For a genuine exception, put `// rq-lint-allow: <reason>` on the line directly above the flagged construct.
5 changes: 5 additions & 0 deletions .claude/rules/sim-react-performance.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
---
description: Behavior-preserving React render-performance idioms
paths:
- "apps/sim/**/*.ts"
- "apps/sim/**/*.tsx"
- "packages/emcn/**"
- "packages/workflow-renderer/**"
---

# React & Render Performance
Expand Down
5 changes: 3 additions & 2 deletions .claude/rules/sim-settings-pages.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,9 @@ and — on activatable rows only — the hover band. Never hand-roll any of it,
divider, body. Also carries `headerAccessory` and `action` slots. Never
re-derive the label/divider chrome; `sim-styling.md` owns those tokens.
- **`SettingsField`** (`…/components/settings-field`) — a read-only label/value
pair in a detail body: muted caption over the value. Pair it with
`SETTINGS_FIELD_VALUE_CLASSES` for the value text.
pair in a detail body: muted caption over the value. Pass the value as text and it
renders the value paragraph itself; pass a node when the value needs its own
presentation (a control, an icon beside the value, status styling).
- **`SettingsEmptyState`** (`…/components/settings-empty-state`) — the canonical
muted status message, for empty lists, "no results", loading gates, **and
failed loads** (`tone='error'`). `variant='fill'` (default) centers in the
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/sim-styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Layout/sizing ONLY: `flex-1`, `w-full`, `w-[Npx]`, `min-w-0`, `max-w-*`, margins
- **Modal body** (`ChipModalBody`): `gap-4` between fields, padding `px-2 pt-4 pb-4.5`.
- **Header/footer**: horizontal gutter `px-4` (header `pt-3`; footer `px-4 pt-2 pb-2`, tinted bar).
- **Every body field MUST be a `ChipModalField`** — NEVER hand-roll a field row (raw `<div>` + hand-rolled `<p>`/`<label>` title + bare `ChipInput`/`ChipTextarea`). WHY: body `px-2` + field `px-2` = effective `px-4`, exactly matching the `px-4` header/footer. A hand-rolled row skips the field gutter, sits at `px-2`, and is visibly misaligned. Inline errors go through the `error` prop, not a hand-rolled `<p>`.
- **Uncovered controls** (`ChipCombobox`, `ChipSelect`, `DatePicker`, `TimePicker`, `ButtonGroup`, arbitrary JSX) → `ChipModalField type='custom'` with a `title`. It still applies the `px-2` gutter and renders the canonical `Label`, so it stays aligned. Never drop such a control into a raw `<div>`, and never add a body-level wrapper `<div>` with a custom `gap-*` that fights `gap-4`.
- **Uncovered controls** (`ChipCombobox`, `ChipSelect`, `ChipDatePicker`, `ChipTimePicker`, `ChipButtonGroup`, arbitrary JSX) → `ChipModalField type='custom'` with a `title`. It still applies the `px-2` gutter and renders the canonical `Label`, so it stays aligned. Never drop such a control into a raw `<div>`, and never add a body-level wrapper `<div>` with a custom `gap-*` that fights `gap-4`.
- **Page section rhythm** (integrations/skills/settings): muted `text-small` label + `mt-[9px] mb-3 h-px bg-[var(--border)]` divider, sections stacked `gap-7`. Reuse `SettingsSection` (`app/workspace/[workspaceId]/settings/components/settings-section/settings-section.tsx`) rather than re-deriving it.

When a standalone labeled field outside a `ChipModal` needs the same look (e.g. `SkillImport`), match the field rhythm by hand: `flex flex-col gap-[9px]`, muted label, `ChipInput`/`ChipTextarea` control, `text-caption` error below.
12 changes: 8 additions & 4 deletions .claude/rules/sim-url-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
description: Shareable client view-state lives in the URL via nuqs
paths:
- "apps/sim/app/**/*.tsx"
- "apps/sim/app/**/*.ts"
- "apps/sim/app/**/search-params.ts"
- "apps/sim/ee/**/*.tsx"
- "apps/sim/ee/**/*.ts"
- "apps/sim/app/workspace/**/*.ts"
- "apps/sim/app/o/**/*.ts"
- "apps/sim/ee/**"
- "apps/sim/hooks/**"
- "apps/sim/stores/**"
- "apps/sim/lib/url-state/**"
- "apps/sim/**/search-params.ts"
- "apps/sim/**/*navigation.ts"
---

# URL / Query-Param State (nuqs)
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/constitution.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: "Sim product language, positioning, and tone guidelines"
alwaysApply: true
globs: ["apps/sim/app/(landing)/**","apps/sim/lib/landing/**","apps/sim/content/**","apps/sim/emails/broadcasts/**","apps/sim/app/layout.tsx","apps/sim/app/manifest.ts","apps/sim/app/llms*.txt/**","apps/sim/app/changelog.xml/**","apps/docs/**"]
---

<!-- Generated from .claude/rules/constitution.md by `bun run skills:sync`. Edit the source, not this file. -->
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/emcn-components.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ globs: ["packages/emcn/**"]

# EMCN Components

Import components, `cn`, and tokens from the `@sim/emcn` barrel; icons come from the `@sim/emcn/icons` subpath, and CSS modules from their file path. Never deep-import other component subpaths. The **chip family** is the platform's primary chrome — always reach for it over the legacy primitives it is progressively replacing (`Input`→`ChipInput`, `Textarea`→`ChipTextarea`, `Modal`→`ChipModal`, `Select`/`Combobox`→`ChipSelect`/`ChipCombobox`/`ChipDropdown`, `Switch`→`ChipSwitch`, date field→`ChipDatePicker`). For context/action menus the canonical control is `DropdownMenu` — the standard menu (not a chip, and never a hand-rolled popover).
Import components, `cn`, and tokens from the `@sim/emcn` barrel; icons come from the `@sim/emcn/icons` subpath, and CSS modules from their file path. Never deep-import other component subpaths. The **chip family** is the platform's primary chrome — always reach for it over the legacy primitives it is progressively replacing (`Input`→`ChipInput`, `Textarea`→`ChipTextarea`, `Modal`→`ChipModal`, `Select`/`Combobox`→`ChipSelect`/`ChipCombobox`/`ChipDropdown`, date field→`ChipDatePicker`). `ChipSwitch` is a segmented choice between options, not a replacement for `Switch`: a boolean on/off toggle stays `Switch`. For context/action menus the canonical control is `DropdownMenu` — the standard menu (not a chip, and never a hand-rolled popover).

## Chip chrome — single source of truth

Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/sim-queries.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,4 @@ Hooks import named type aliases from `@/lib/api/contracts/**` and never import `

## Enforcement

`scripts/check-react-query-patterns.ts` (`bun run check:react-query`, run in CI) statically enforces these conventions: every `useQuery`/`useInfiniteQuery`/`useSuspenseQuery` declares an explicit `staleTime`, inline `queryFn`s destructure `signal`, `queryKey`s reference a colocated factory rather than an inline literal, every `*Keys` factory in `hooks/queries/**` exposes an `all` root key, and every identifier the `queryFn` forwards into the fetch also appears in the `queryKey` (`key-fetch-arg-drift`). `hooks/queries/**` is a zero-tolerance zone; the rest of `apps/sim/**` is ratcheted against `scripts/check-react-query-patterns.baseline.json`. For a genuine exception, put `// rq-lint-allow: <reason>` on the line directly above the flagged construct.
`scripts/check-react-query-patterns.ts` (`bun run check:react-query`, run in CI) statically enforces these conventions: every `useQuery`/`useInfiniteQuery`/`useSuspenseQuery` declares an explicit `staleTime`, inline `queryFn`s destructure `signal`, `queryKey`s reference a colocated factory rather than an inline literal, every `*Keys` factory in `hooks/queries/**` exposes an `all` root key, and every identifier the `queryFn` forwards into the fetch also appears in the `queryKey` (`key-fetch-arg-drift`). Any violation under `apps/sim/**` fails. For a genuine exception, put `// rq-lint-allow: <reason>` on the line directly above the flagged construct.
2 changes: 1 addition & 1 deletion .cursor/rules/sim-react-performance.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: "Behavior-preserving React render-performance idioms"
alwaysApply: true
globs: ["apps/sim/**/*.ts","apps/sim/**/*.tsx","packages/emcn/**","packages/workflow-renderer/**"]
---

<!-- Generated from .claude/rules/sim-react-performance.md by `bun run skills:sync`. Edit the source, not this file. -->
Expand Down
5 changes: 3 additions & 2 deletions .cursor/rules/sim-settings-pages.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ and — on activatable rows only — the hover band. Never hand-roll any of it,
divider, body. Also carries `headerAccessory` and `action` slots. Never
re-derive the label/divider chrome; `sim-styling.md` owns those tokens.
- **`SettingsField`** (`…/components/settings-field`) — a read-only label/value
pair in a detail body: muted caption over the value. Pair it with
`SETTINGS_FIELD_VALUE_CLASSES` for the value text.
pair in a detail body: muted caption over the value. Pass the value as text and it
renders the value paragraph itself; pass a node when the value needs its own
presentation (a control, an icon beside the value, status styling).
- **`SettingsEmptyState`** (`…/components/settings-empty-state`) — the canonical
muted status message, for empty lists, "no results", loading gates, **and
failed loads** (`tone='error'`). `variant='fill'` (default) centers in the
Expand Down
2 changes: 1 addition & 1 deletion .cursor/rules/sim-styling.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ Layout/sizing ONLY: `flex-1`, `w-full`, `w-[Npx]`, `min-w-0`, `max-w-*`, margins
- **Modal body** (`ChipModalBody`): `gap-4` between fields, padding `px-2 pt-4 pb-4.5`.
- **Header/footer**: horizontal gutter `px-4` (header `pt-3`; footer `px-4 pt-2 pb-2`, tinted bar).
- **Every body field MUST be a `ChipModalField`** — NEVER hand-roll a field row (raw `<div>` + hand-rolled `<p>`/`<label>` title + bare `ChipInput`/`ChipTextarea`). WHY: body `px-2` + field `px-2` = effective `px-4`, exactly matching the `px-4` header/footer. A hand-rolled row skips the field gutter, sits at `px-2`, and is visibly misaligned. Inline errors go through the `error` prop, not a hand-rolled `<p>`.
- **Uncovered controls** (`ChipCombobox`, `ChipSelect`, `DatePicker`, `TimePicker`, `ButtonGroup`, arbitrary JSX) → `ChipModalField type='custom'` with a `title`. It still applies the `px-2` gutter and renders the canonical `Label`, so it stays aligned. Never drop such a control into a raw `<div>`, and never add a body-level wrapper `<div>` with a custom `gap-*` that fights `gap-4`.
- **Uncovered controls** (`ChipCombobox`, `ChipSelect`, `ChipDatePicker`, `ChipTimePicker`, `ChipButtonGroup`, arbitrary JSX) → `ChipModalField type='custom'` with a `title`. It still applies the `px-2` gutter and renders the canonical `Label`, so it stays aligned. Never drop such a control into a raw `<div>`, and never add a body-level wrapper `<div>` with a custom `gap-*` that fights `gap-4`.
- **Page section rhythm** (integrations/skills/settings): muted `text-small` label + `mt-[9px] mb-3 h-px bg-[var(--border)]` divider, sections stacked `gap-7`. Reuse `SettingsSection` (`app/workspace/[workspaceId]/settings/components/settings-section/settings-section.tsx`) rather than re-deriving it.

When a standalone labeled field outside a `ChipModal` needs the same look (e.g. `SkillImport`), match the field rhythm by hand: `flex flex-col gap-[9px]`, muted label, `ChipInput`/`ChipTextarea` control, `text-caption` error below.
2 changes: 1 addition & 1 deletion .cursor/rules/sim-url-state.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: "Shareable client view-state lives in the URL via nuqs"
globs: ["apps/sim/app/**/*.tsx","apps/sim/app/**/*.ts","apps/sim/app/**/search-params.ts","apps/sim/ee/**/*.tsx","apps/sim/ee/**/*.ts"]
globs: ["apps/sim/app/**/*.tsx","apps/sim/app/workspace/**/*.ts","apps/sim/app/o/**/*.ts","apps/sim/ee/**","apps/sim/hooks/**","apps/sim/stores/**","apps/sim/lib/url-state/**","apps/sim/**/search-params.ts","apps/sim/**/*navigation.ts"]
---

<!-- Generated from .claude/rules/sim-url-state.md by `bun run skills:sync`. Edit the source, not this file. -->
Expand Down
Loading
Loading