{"owner":"superset-sh","repo":"superset","hasSkills":true,"totalSkillsCount":4,"totalTokensCount":4459,"categories":["root-instruction","mcp-config","marketplace","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"superset":{"command":"npx","args":["-y","@modelcontextprotocol/server-superset"]}}},"found":["AGENTS.md",".cursor/mcp.json",".claude-plugin/marketplace.json",".claude-plugin/plugin.json"],"skills":{"AGENTS.md":"# Superset Monorepo\n\nSuperset is an agent-first development platform, with an Electron desktop IDE, Next.js web apps, and an Expo mobile app as the main customer-facing surfaces. It's a Turborepo monorepo, deployed apps are in apps/ and supporting packages are in packages/, and we use tRPC for the api.\n\nYou're working inside a Superset workspace, an isolated checkout of this repo — a git worktree on a\nmachine someone owns, a plain clone at `/workspace` in a cloud workspace. \"Workspace\" in a user\nmessage means that, not an editor workspace.\n\n## Project Structure\n\nAll projects in this repo should be structured like this:\n\n```\napp/\n├── page.tsx\n├── dashboard/\n│   ├── page.tsx\n│   ├── components/\n│   │   └── MetricsChart/\n│   │       ├── MetricsChart.tsx\n│   │       ├── MetricsChart.test.tsx      # Tests co-located\n│   │       ├── index.ts\n│   │       └── constants.ts\n│   ├── hooks/                             # Hooks used only in dashboard\n│   │   └── useMetrics/\n│   │       ├── useMetrics.ts\n│   │       ├── useMetrics.test.ts\n│   │       └── index.ts\n│   ├── utils/                             # Utils used only in dashboard\n│   │   └── formatData/\n│   │       ├── formatData.ts\n│   │       ├── formatData.test.ts\n│   │       └── index.ts\n│   ├── stores/                            # Stores used only in dashboard\n│   │   └── dashboardStore/\n│   │       ├── dashboardStore.ts\n│   │       └── index.ts\n│   └── providers/                         # Providers for dashboard context\n│       └── DashboardProvider/\n│           ├── DashboardProvider.tsx\n│           └── index.ts\n└── components/\n    ├── Sidebar/\n    │   ├── Sidebar.tsx\n    │   ├── Sidebar.test.tsx               # Tests co-located\n    │   ├── index.ts\n    │   ├── components/                    # Used 2+ times IN Sidebar\n    │   │   └── SidebarButton/             # Shared by SidebarNav + SidebarFooter\n    │   │       ├── SidebarButton.tsx\n    │   │       ├── SidebarButton.test.tsx\n    │   │       └── index.ts\n    │   ├── SidebarNav/\n    │   │   ├── SidebarNav.tsx\n    │   │   └── index.ts\n    │   └── SidebarFooter/\n    │       ├── SidebarFooter.tsx\n    │       └── index.ts\n    └── HeroSection/\n        ├── HeroSection.tsx\n        ├── HeroSection.test.tsx           # Tests co-located\n        ├── index.ts\n        └── components/                    # Used ONLY by HeroSection\n            └── HeroCanvas/\n                ├── HeroCanvas.tsx\n                ├── HeroCanvas.test.tsx\n                ├── HeroCanvas.stories.tsx\n                ├── index.ts\n                └── config.ts\n\ncomponents/                                # Used in 2+ pages (last resort)\n└── Header/\n```\n\n1. **One folder per component**: `ComponentName/ComponentName.tsx` + `index.ts` for barrel export\n2. **Co-locate by usage**: If used once, nest under parent's `components/`. If used 2+ times, promote to **highest shared parent's** `components/` (or `components/` as last resort)\n3. **One component per file**: No multi-component files\n4. **Co-locate dependencies**: Utils, hooks, constants, config, tests, stories live next to the file using them\n\n### Exception: shadcn/ui Components\n\nThe `src/components/ui/` and `src/components/ai-elements` directories contain shadcn/ui components. These use **kebab-case single files** (e.g., `button.tsx`, `base-node.tsx`) instead of the folder structure above. This is intentional—shadcn CLI expects this format for updates via `bunx shadcn@latest add`.\n\n## Database\n\nDrizzle ORM, schema in `packages/db/src/`. Follow `.agents/skills/db-migrations/SKILL.md` to generate\nmigrations and to clear its production safety checklist before opening the PR. Never hand-edit `packages/db/drizzle/` (SQL, `meta/_journal.json`, snapshots) without\nexplicit user confirmation, and never apply migrations against a shared or production database.\n\n## Releases\n\nDesktop, host-service, and cli share one version; cut releases on a dedicated branch. Runbook:\n`scripts/release/README.md`. A *canary* is a separate thing: `bash scripts/release-canary.sh\n[commit]` builds the rolling internal `desktop-canary` prerelease, not a versioned release.\n\n## Plugins\n\nFirst-party plugins live in `plugins/<name>/`: a `plugin.json` manifest and `skills/`. A plugin\nships no code — agents reach its tools through `/mcp/plugins/<marketplace>/<plugin>` on the API,\nwhich proxies to the vendor's MCP server or, for the plugins named in the `SUPERSET_HOSTED_PLUGINS` constant,\nserves them from `packages/trpc/src/router/plugins/servers/`. A release is the git tag\n`<name>@<version>` on this repo — that tree is what a host\ndownloads — and `packages/shared/src/plugins/manifests.generated.ts` is the bundle the API resolves\nagainst, which is generated and must never be hand-edited. Change the source, then\n`superset plugins publish <name> --bump patch`, which rewrites the marketplace entry in\n`.agent-marketplace.json` and the generated manifests; commit and tag to publish it. `bun run check:plugins` is what CI\nruns to catch a change that skipped that step; run it before pushing.\n\nInstalled plugins are recorded once per machine in\n`$SUPERSET_HOME_DIR/plugins/installed_plugins.json` (`SUPERSET_HOME` is the CLI's install prefix and\nmeans nothing here). Every provisioner reads that one file — the desktop at boot, `plugins sync`,\nthe host-service — because provisioning is declarative and reaps whatever is absent from the desired\nset. A caller that passes its own list instead makes the last writer delete the others' skills.\nDetails: `docs/plugins.md`.\n\n## Orchestrating agents and workspaces\n\nWhen work wants a fresh isolated environment, a parallel agent, or a long-running job, reach for the\n`superset` CLI instead of hand-rolling git worktrees or doing it all serially in this one. It's\nalready on `PATH` in Superset terminals, and we dogfood it.\n\nReplace the capitalized placeholders before running these:\n\n```bash\nsuperset ws create --local --project PROJECT_ID --branch BRANCH --agent claude --prompt \"...\"\nsuperset agents create --workspace WORKSPACE_ID --agent claude --prompt \"...\"\nsuperset ws list --local\nsuperset terminals read --workspace WORKSPACE_ID --terminal TERMINAL_ID\nsuperset ws archive --local WORKSPACE_ID\n```\n\nIn order: an isolated workspace with an agent already working in it, another agent in an existing\nworkspace, what's running, what an agent is doing right now, and cleanup when you're done.\n\nSpawning several related workspaces? Add `--tag SOME_TAG` (repeatable) to `ws create` — tagged\nworkspaces group into a sidebar folder of that name automatically, so a batch files itself instead\nof scattering across the project. `ws list --local --tag SOME_TAG` filters to them, and\n`ws update WORKSPACE_ID --tag ...` retags (`--clear-tags` ungroups). Automation-created workspaces\nare tagged `automation` by default and collect in an \"automation\" folder.\n\n`superset schema` prints every command, option and argument as JSON; read it with `jq` to learn the\nrest (tasks, automations, hosts, settings) instead of parsing `--help` text. To check only that a\ncommand exists, the exit code of `superset <command> --help` is enough. Details and the version\ncaveat: `docs/agent-tooling.md`.\n\n```bash\nsuperset schema | jq '.commands[] | select(.path==[\"terminals\"]) | .commands[] | {path, options: [.options[].name]}'\n```\n\nPass `--json` for parsable output; it's on by default under agent environments.\n\n## Internationalization\n\nUser-facing strings use Lingui macros with the English text as the message id —\n`<Trans>Text</Trans>` or `useLingui()`'s `t({ message })` in React, `i18n._(msg({ message }))`\noutside React (Electron main). Identical English with different meanings gets a `context`\nso it translates separately. Numbers, currencies, and dates go through\n`@superset/i18n/format` helpers, never `new Intl.*(\"en-US\")` or `toLocale*` with a hardcoded\nlocale. After adding or changing strings, run `bun run check:i18n` (CI enforces it): it\nregenerates the catalogs and lists every untranslated message per locale. Write those\ntranslations yourself into each `locales/<locale>/messages.po` and commit the catalogs with\nthe change — nothing on CI fills translations for you. Conventions: `packages/i18n/README.md`;\nterms that never translate: `packages/i18n/glossary.md`; strategy and phasing:\n`plans/20260826-i18n-strategy.md`.\nDirectories listed in `packages/i18n/test/enforced-dirs.ts` must not contain hardcoded\nJSX text — add a directory there once it is fully converted. `errorMessage()` output is potentially\ntranslated and is display-only: logs, Sentry/PostHog, and error classification use\n`rawErrorMessage()` or the error object (enforced by `packages/i18n/test/display-only.test.ts`).\n\n**Shipping locales.** `SUPPORTED_LOCALES` in `packages/i18n/src/locales.ts` is the single\nsource of truth — adding a locale there is what makes it appear in the Settings picker and\nthe optional onboarding step, and what `lingui.config.ts` must list. Every enabled locale\nmust be **fully translated**: `compile --strict` fails the build on a missing message, so\nfinish a translation before adding its locale. Native language names live in `LOCALE_LABELS`\nand are never translated — someone stuck in the wrong language has to recognize their own.\nRelative times use `formatRelativeTime`/`formatCompactRelativeTime`, not hand-rolled\n\"3d ago\" helpers; `Intl` already knows every locale's wording.\n\nThree traps worth knowing before you touch catalogs:\n\n- **Editing English copy re-keys the message.** The text is the id, so an edit creates a\n  new entry that is empty in every locale and `check:i18n` lists it. If the edit was cosmetic,\n  the old translations are still in `git diff` on the catalogs to copy from.\n- **Regenerate from a clean tree.** `lingui.config.ts` keeps `messages.po` deterministic:\n  `orderBy: \"message\"` fixes entry order, and `origins: false` drops the `#:` file\n  references, whose order follows filesystem traversal and differs between macOS and\n  Linux. A catalog regenerated on top of local experiments will still commit noise.\n- **`bun test` runs uncompiled source.** The Lingui macro rewrites `` message: `${n} items` ``\n  into a placeholder message plus values at build time, so the catalog stores `{n} items`.\n  Tests see neither, which is why `apps/desktop/test-setup.ts` shims the macros and `i18n._`.\n  Mock that module with a Proxy, never a spread — `i18n` is a class instance and a spread\n  drops `load`/`activate`.\n\n## Comments\n\nNever comment unless the thing can never be self-describing in the code. Name it, structure it,\nor type it first; a comment is the last resort for what the code genuinely cannot say — a\nconstraint that lives outside the repo, or a trap the next reader would walk into. Rationale goes\nin the commit message and the PR.\n\n## Tests\n\nCI runs every suite on each push, and the whole run is meant to stay near two minutes. A test\nearns its place by catching a regression quickly.\n\n- **No real waiting.** A test that needs more than bun's default 5 s timeout is too slow. Do not\n  raise the timeout: pass the delay, clock or retry count in and test with a small value. Never\n  wait for a real network or process timeout to fire.\n- **One test per behaviour.** Stress, fuzz and \"adversarial\" suites that build many real git\n  repositories or processes do not go in the repo. When a probe finds a bug, keep the one\n  regression test for it.\n- **Any order, clean checkout.** Each package's suite runs in one process, in an order that differs\n  between machines, with no root `.env`. Do not `mock.module` a module that other files import for\n  real (`env`, a client, a logger). Give the code its input instead: a parameter, a placeholder in\n  the package's test preload, or a local server.\n- **A flaky test is a broken test.** Fix the cause or delete it. Do not add retries or longer\n  timeouts.\n- **Node-only suites** (real PTYs, `node:test`) are `*.node-test.ts` files run by a turbo task, so\n  they run beside the bun suites and not after them.\n\n## Further reading\n\n- `.agents/skills/`: CDP UI verification, mobile simulator verification, DB migrations, tRPC\n  compatibility, ticket format, and more. Read the matching `SKILL.md` when a task fits its\n  description.\n- `docs/agent-tooling.md`: where commands, skills, and per-agent-CLI config live.\n- `docs/plugins.md`: authoring, publishing, and installing marketplace plugins — the manifest\n  contract, the credential proxy, and which files are generated.\n- `docs/environment-variables.md`: read before adding an environment variable. Five places,\n  and missing one fails silently.\n- `docs/deploy-workflows.md`: read before writing or testing a deploy workflow step. `run:` has\n  no `pipefail` by default, and production secrets exist only in GitHub.\n- `packages/trpc/AGENTS.md`: read before changing any tRPC procedure, in `packages/trpc` or\n  `packages/host-service`. Released desktop, mobile, and CLI builds still call it.\n- `apps/desktop/AGENTS.md`: desktop specifics (notices, persisted renderer state).\n- `apps/mobile/AGENTS.md`: mobile structure and iOS-only scope.\n- `docs/cloud-sandbox-mismatches.md`: where cloud workspace sandboxes don't fit assumptions the\n  app makes about a machine someone owns. Read it before touching sandboxes, and add to it when\n  you find a new one.\n- `docs/cloud-sandbox-considerations.md`: what cloud sandboxes still owe before they leave the\n  team — billing, credential blast radius, untested behaviour.\n\n## Contributor responsibility\n\nContributors are responsible for every change they submit, including agent-generated code.\nThey must understand the changes, review the diff, and verify the behavior before requesting\nreview.\n\n- Ask for clarification when a request lacks enough context to make a correct change.\n- Explain changes and validation so the contributor can review and understand the result.\n- Agents may write commit messages and PR descriptions, commit changes, push branches, create\n  PRs, and address review feedback when authorized by the user.\n- Only post replies to reviewers when the user explicitly authorizes it.\n- Never claim that checks passed or behavior was verified unless it actually was.\n\n## Code standards\n\n- Keep code comments concise (usually 1-2 lines)\n- Avoid redundant or excessive inline commentary\n- Use ASD-STE100 Simplified Technical English, simple wordings\n\n### Examples\n\n```c++\n  // Good (no comment)\n\n  std::string module_name =\n    fmt::format(\"{}_{:x}\", name_, std::hash<std::string>{}(source_));\n\n  // Bad (excessive comment for explicit code)\n\n  // The module cache is keyed on this name, so it has to include the source:\n  // two kernels sharing a name but not a body would otherwise both run\n  // whichever was compiled first. Same fix as 3833 on the Metal side.\n```\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/plugin.json)"},"files":{"AGENTS.md":"# Superset Monorepo\n\nSuperset is an agent-first development platform, with an Electron desktop IDE, Next.js web apps, and an Expo mobile app as the main customer-facing surfaces. It's a Turborepo monorepo, deployed apps are in apps/ and supporting packages are in packages/, and we use tRPC for the api.\n\nYou're working inside a Superset workspace, an isolated checkout of this repo — a git worktree on a\nmachine someone owns, a plain clone at `/workspace` in a cloud workspace. \"Workspace\" in a user\nmessage means that, not an editor workspace.\n\n## Project Structure\n\nAll projects in this repo should be structured like this:\n\n```\napp/\n├── page.tsx\n├── dashboard/\n│   ├── page.tsx\n│   ├── components/\n│   │   └── MetricsChart/\n│   │       ├── MetricsChart.tsx\n│   │       ├── MetricsChart.test.tsx      # Tests co-located\n│   │       ├── index.ts\n│   │       └── constants.ts\n│   ├── hooks/                             # Hooks used only in dashboard\n│   │   └── useMetrics/\n│   │       ├── useMetrics.ts\n│   │       ├── useMetrics.test.ts\n│   │       └── index.ts\n│   ├── utils/                             # Utils used only in dashboard\n│   │   └── formatData/\n│   │       ├── formatData.ts\n│   │       ├── formatData.test.ts\n│   │       └── index.ts\n│   ├── stores/                            # Stores used only in dashboard\n│   │   └── dashboardStore/\n│   │       ├── dashboardStore.ts\n│   │       └── index.ts\n│   └── providers/                         # Providers for dashboard context\n│       └── DashboardProvider/\n│           ├── DashboardProvider.tsx\n│           └── index.ts\n└── components/\n    ├── Sidebar/\n    │   ├── Sidebar.tsx\n    │   ├── Sidebar.test.tsx               # Tests co-located\n    │   ├── index.ts\n    │   ├── components/                    # Used 2+ times IN Sidebar\n    │   │   └── SidebarButton/             # Shared by SidebarNav + SidebarFooter\n    │   │       ├── SidebarButton.tsx\n    │   │       ├── SidebarButton.test.tsx\n    │   │       └── index.ts\n    │   ├── SidebarNav/\n    │   │   ├── SidebarNav.tsx\n    │   │   └── index.ts\n    │   └── SidebarFooter/\n    │       ├── SidebarFooter.tsx\n    │       └── index.ts\n    └── HeroSection/\n        ├── HeroSection.tsx\n        ├── HeroSection.test.tsx           # Tests co-located\n        ├── index.ts\n        └── components/                    # Used ONLY by HeroSection\n            └── HeroCanvas/\n                ├── HeroCanvas.tsx\n                ├── HeroCanvas.test.tsx\n                ├── HeroCanvas.stories.tsx\n                ├── index.ts\n                └── config.ts\n\ncomponents/                                # Used in 2+ pages (last resort)\n└── Header/\n```\n\n1. **One folder per component**: `ComponentName/ComponentName.tsx` + `index.ts` for barrel export\n2. **Co-locate by usage**: If used once, nest under parent's `components/`. If used 2+ times, promote to **highest shared parent's** `components/` (or `components/` as last resort)\n3. **One component per file**: No multi-component files\n4. **Co-locate dependencies**: Utils, hooks, constants, config, tests, stories live next to the file using them\n\n### Exception: shadcn/ui Components\n\nThe `src/components/ui/` and `src/components/ai-elements` directories contain shadcn/ui components. These use **kebab-case single files** (e.g., `button.tsx`, `base-node.tsx`) instead of the folder structure above. This is intentional—shadcn CLI expects this format for updates via `bunx shadcn@latest add`.\n\n## Database\n\nDrizzle ORM, schema in `packages/db/src/`. Follow `.agents/skills/db-migrations/SKILL.md` to generate\nmigrations and to clear its production safety checklist before opening the PR. Never hand-edit `packages/db/drizzle/` (SQL, `meta/_journal.json`, snapshots) without\nexplicit user confirmation, and never apply migrations against a shared or production database.\n\n## Releases\n\nDesktop, host-service, and cli share one version; cut releases on a dedicated branch. Runbook:\n`scripts/release/README.md`. A *canary* is a separate thing: `bash scripts/release-canary.sh\n[commit]` builds the rolling internal `desktop-canary` prerelease, not a versioned release.\n\n## Plugins\n\nFirst-party plugins live in `plugins/<name>/`: a `plugin.json` manifest and `skills/`. A plugin\nships no code — agents reach its tools through `/mcp/plugins/<marketplace>/<plugin>` on the API,\nwhich proxies to the vendor's MCP server or, for the plugins named in the `SUPERSET_HOSTED_PLUGINS` constant,\nserves them from `packages/trpc/src/router/plugins/servers/`. A release is the git tag\n`<name>@<version>` on this repo — that tree is what a host\ndownloads — and `packages/shared/src/plugins/manifests.generated.ts` is the bundle the API resolves\nagainst, which is generated and must never be hand-edited. Change the source, then\n`superset plugins publish <name> --bump patch`, which rewrites the marketplace entry in\n`.agent-marketplace.json` and the generated manifests; commit and tag to publish it. `bun run check:plugins` is what CI\nruns to catch a change that skipped that step; run it before pushing.\n\nInstalled plugins are recorded once per machine in\n`$SUPERSET_HOME_DIR/plugins/installed_plugins.json` (`SUPERSET_HOME` is the CLI's install prefix and\nmeans nothing here). Every provisioner reads that one file — the desktop at boot, `plugins sync`,\nthe host-service — because provisioning is declarative and reaps whatever is absent from the desired\nset. A caller that passes its own list instead makes the last writer delete the others' skills.\nDetails: `docs/plugins.md`.\n\n## Orchestrating agents and workspaces\n\nWhen work wants a fresh isolated environment, a parallel agent, or a long-running job, reach for the\n`superset` CLI instead of hand-rolling git worktrees or doing it all serially in this one. It's\nalready on `PATH` in Superset terminals, and we dogfood it.\n\nReplace the capitalized placeholders before running these:\n\n```bash\nsuperset ws create --local --project PROJECT_ID --branch BRANCH --agent claude --prompt \"...\"\nsuperset agents create --workspace WORKSPACE_ID --agent claude --prompt \"...\"\nsuperset ws list --local\nsuperset terminals read --workspace WORKSPACE_ID --terminal TERMINAL_ID\nsuperset ws archive --local WORKSPACE_ID\n```\n\nIn order: an isolated workspace with an agent already working in it, another agent in an existing\nworkspace, what's running, what an agent is doing right now, and cleanup when you're done.\n\nSpawning several related workspaces? Add `--tag SOME_TAG` (repeatable) to `ws create` — tagged\nworkspaces group into a sidebar folder of that name automatically, so a batch files itself instead\nof scattering across the project. `ws list --local --tag SOME_TAG` filters to them, and\n`ws update WORKSPACE_ID --tag ...` retags (`--clear-tags` ungroups). Automation-created workspaces\nare tagged `automation` by default and collect in an \"automation\" folder.\n\n`superset schema` prints every command, option and argument as JSON; read it with `jq` to learn the\nrest (tasks, automations, hosts, settings) instead of parsing `--help` text. To check only that a\ncommand exists, the exit code of `superset <command> --help` is enough. Details and the version\ncaveat: `docs/agent-tooling.md`.\n\n```bash\nsuperset schema | jq '.commands[] | select(.path==[\"terminals\"]) | .commands[] | {path, options: [.options[].name]}'\n```\n\nPass `--json` for parsable output; it's on by default under agent environments.\n\n## Internationalization\n\nUser-facing strings use Lingui macros with the English text as the message id —\n`<Trans>Text</Trans>` or `useLingui()`'s `t({ message })` in React, `i18n._(msg({ message }))`\noutside React (Electron main). Identical English with different meanings gets a `context`\nso it translates separately. Numbers, currencies, and dates go through\n`@superset/i18n/format` helpers, never `new Intl.*(\"en-US\")` or `toLocale*` with a hardcoded\nlocale. After adding or changing strings, run `bun run check:i18n` (CI enforces it): it\nregenerates the catalogs and lists every untranslated message per locale. Write those\ntranslations yourself into each `locales/<locale>/messages.po` and commit the catalogs with\nthe change — nothing on CI fills translations for you. Conventions: `packages/i18n/README.md`;\nterms that never translate: `packages/i18n/glossary.md`; strategy and phasing:\n`plans/20260826-i18n-strategy.md`.\nDirectories listed in `packages/i18n/test/enforced-dirs.ts` must not contain hardcoded\nJSX text — add a directory there once it is fully converted. `errorMessage()` output is potentially\ntranslated and is display-only: logs, Sentry/PostHog, and error classification use\n`rawErrorMessage()` or the error object (enforced by `packages/i18n/test/display-only.test.ts`).\n\n**Shipping locales.** `SUPPORTED_LOCALES` in `packages/i18n/src/locales.ts` is the single\nsource of truth — adding a locale there is what makes it appear in the Settings picker and\nthe optional onboarding step, and what `lingui.config.ts` must list. Every enabled locale\nmust be **fully translated**: `compile --strict` fails the build on a missing message, so\nfinish a translation before adding its locale. Native language names live in `LOCALE_LABELS`\nand are never translated — someone stuck in the wrong language has to recognize their own.\nRelative times use `formatRelativeTime`/`formatCompactRelativeTime`, not hand-rolled\n\"3d ago\" helpers; `Intl` already knows every locale's wording.\n\nThree traps worth knowing before you touch catalogs:\n\n- **Editing English copy re-keys the message.** The text is the id, so an edit creates a\n  new entry that is empty in every locale and `check:i18n` lists it. If the edit was cosmetic,\n  the old translations are still in `git diff` on the catalogs to copy from.\n- **Regenerate from a clean tree.** `lingui.config.ts` keeps `messages.po` deterministic:\n  `orderBy: \"message\"` fixes entry order, and `origins: false` drops the `#:` file\n  references, whose order follows filesystem traversal and differs between macOS and\n  Linux. A catalog regenerated on top of local experiments will still commit noise.\n- **`bun test` runs uncompiled source.** The Lingui macro rewrites `` message: `${n} items` ``\n  into a placeholder message plus values at build time, so the catalog stores `{n} items`.\n  Tests see neither, which is why `apps/desktop/test-setup.ts` shims the macros and `i18n._`.\n  Mock that module with a Proxy, never a spread — `i18n` is a class instance and a spread\n  drops `load`/`activate`.\n\n## Comments\n\nNever comment unless the thing can never be self-describing in the code. Name it, structure it,\nor type it first; a comment is the last resort for what the code genuinely cannot say — a\nconstraint that lives outside the repo, or a trap the next reader would walk into. Rationale goes\nin the commit message and the PR.\n\n## Tests\n\nCI runs every suite on each push, and the whole run is meant to stay near two minutes. A test\nearns its place by catching a regression quickly.\n\n- **No real waiting.** A test that needs more than bun's default 5 s timeout is too slow. Do not\n  raise the timeout: pass the delay, clock or retry count in and test with a small value. Never\n  wait for a real network or process timeout to fire.\n- **One test per behaviour.** Stress, fuzz and \"adversarial\" suites that build many real git\n  repositories or processes do not go in the repo. When a probe finds a bug, keep the one\n  regression test for it.\n- **Any order, clean checkout.** Each package's suite runs in one process, in an order that differs\n  between machines, with no root `.env`. Do not `mock.module` a module that other files import for\n  real (`env`, a client, a logger). Give the code its input instead: a parameter, a placeholder in\n  the package's test preload, or a local server.\n- **A flaky test is a broken test.** Fix the cause or delete it. Do not add retries or longer\n  timeouts.\n- **Node-only suites** (real PTYs, `node:test`) are `*.node-test.ts` files run by a turbo task, so\n  they run beside the bun suites and not after them.\n\n## Further reading\n\n- `.agents/skills/`: CDP UI verification, mobile simulator verification, DB migrations, tRPC\n  compatibility, ticket format, and more. Read the matching `SKILL.md` when a task fits its\n  description.\n- `docs/agent-tooling.md`: where commands, skills, and per-agent-CLI config live.\n- `docs/plugins.md`: authoring, publishing, and installing marketplace plugins — the manifest\n  contract, the credential proxy, and which files are generated.\n- `docs/environment-variables.md`: read before adding an environment variable. Five places,\n  and missing one fails silently.\n- `docs/deploy-workflows.md`: read before writing or testing a deploy workflow step. `run:` has\n  no `pipefail` by default, and production secrets exist only in GitHub.\n- `packages/trpc/AGENTS.md`: read before changing any tRPC procedure, in `packages/trpc` or\n  `packages/host-service`. Released desktop, mobile, and CLI builds still call it.\n- `apps/desktop/AGENTS.md`: desktop specifics (notices, persisted renderer state).\n- `apps/mobile/AGENTS.md`: mobile structure and iOS-only scope.\n- `docs/cloud-sandbox-mismatches.md`: where cloud workspace sandboxes don't fit assumptions the\n  app makes about a machine someone owns. Read it before touching sandboxes, and add to it when\n  you find a new one.\n- `docs/cloud-sandbox-considerations.md`: what cloud sandboxes still owe before they leave the\n  team — billing, credential blast radius, untested behaviour.\n\n## Contributor responsibility\n\nContributors are responsible for every change they submit, including agent-generated code.\nThey must understand the changes, review the diff, and verify the behavior before requesting\nreview.\n\n- Ask for clarification when a request lacks enough context to make a correct change.\n- Explain changes and validation so the contributor can review and understand the result.\n- Agents may write commit messages and PR descriptions, commit changes, push branches, create\n  PRs, and address review feedback when authorized by the user.\n- Only post replies to reviewers when the user explicitly authorizes it.\n- Never claim that checks passed or behavior was verified unless it actually was.\n\n## Code standards\n\n- Keep code comments concise (usually 1-2 lines)\n- Avoid redundant or excessive inline commentary\n- Use ASD-STE100 Simplified Technical English, simple wordings\n\n### Examples\n\n```c++\n  // Good (no comment)\n\n  std::string module_name =\n    fmt::format(\"{}_{:x}\", name_, std::hash<std::string>{}(source_));\n\n  // Bad (excessive comment for explicit code)\n\n  // The module cache is keyed on this name, so it has to include the source:\n  // two kernels sharing a name but not a body would otherwise both run\n  // whichever was compiled first. Same fix as 3833 on the Metal side.\n```\n",".cursor/mcp.json":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.cursor/mcp.json)",".claude-plugin/marketplace.json":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/marketplace.json)",".claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/plugin.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/superset-sh/superset/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Superset Monorepo\n\nSuperset is an agent-first development platform, with an Electron desktop IDE, Next.js web apps, and an Expo mobile app as the main customer-facing surfaces. It's a Turborepo monorepo, deployed apps are in apps/ and supporting packages are in packages/, and we use tRPC for the api.\n\nYou're working inside a Superset workspace, an isolated checkout of this repo — a git worktree on a\nmachine someone owns, a plain clone at `/workspace` in a cloud workspace. \"Workspace\" in a user\nmessage means that, not an editor workspace.\n\n## Project Structure\n\nAll projects in this repo should be structured like this:\n\n```\napp/\n├── page.tsx\n├── dashboard/\n│   ├── page.tsx\n│   ├── components/\n│   │   └── MetricsChart/\n│   │       ├── MetricsChart.tsx\n│   │       ├── MetricsChart.test.tsx      # Tests co-located\n│   │       ├── index.ts\n│   │       └── constants.ts\n│   ├── hooks/                             # Hooks used only in dashboard\n│   │   └── useMetrics/\n│   │       ├── useMetrics.ts\n│   │       ├── useMetrics.test.ts\n│   │       └── index.ts\n│   ├── utils/                             # Utils used only in dashboard\n│   │   └── formatData/\n│   │       ├── formatData.ts\n│   │       ├── formatData.test.ts\n│   │       └── index.ts\n│   ├── stores/                            # Stores used only in dashboard\n│   │   └── dashboardStore/\n│   │       ├── dashboardStore.ts\n│   │       └── index.ts\n│   └── providers/                         # Providers for dashboard context\n│       └── DashboardProvider/\n│           ├── DashboardProvider.tsx\n│           └── index.ts\n└── components/\n    ├── Sidebar/\n    │   ├── Sidebar.tsx\n    │   ├── Sidebar.test.tsx               # Tests co-located\n    │   ├── index.ts\n    │   ├── components/                    # Used 2+ times IN Sidebar\n    │   │   └── SidebarButton/             # Shared by SidebarNav + SidebarFooter\n    │   │       ├── SidebarButton.tsx\n    │   │       ├── SidebarButton.test.tsx\n    │   │       └── index.ts\n    │   ├── SidebarNav/\n    │   │   ├── SidebarNav.tsx\n    │   │   └── index.ts\n    │   └── SidebarFooter/\n    │       ├── SidebarFooter.tsx\n    │       └── index.ts\n    └── HeroSection/\n        ├── HeroSection.tsx\n        ├── HeroSection.test.tsx           # Tests co-located\n        ├── index.ts\n        └── components/                    # Used ONLY by HeroSection\n            └── HeroCanvas/\n                ├── HeroCanvas.tsx\n                ├── HeroCanvas.test.tsx\n                ├── HeroCanvas.stories.tsx\n                ├── index.ts\n                └── config.ts\n\ncomponents/                                # Used in 2+ pages (last resort)\n└── Header/\n```\n\n1. **One folder per component**: `ComponentName/ComponentName.tsx` + `index.ts` for barrel export\n2. **Co-locate by usage**: If used once, nest under parent's `components/`. If used 2+ times, promote to **highest shared parent's** `components/` (or `components/` as last resort)\n3. **One component per file**: No multi-component files\n4. **Co-locate dependencies**: Utils, hooks, constants, config, tests, stories live next to the file using them\n\n### Exception: shadcn/ui Components\n\nThe `src/components/ui/` and `src/components/ai-elements` directories contain shadcn/ui components. These use **kebab-case single files** (e.g., `button.tsx`, `base-node.tsx`) instead of the folder structure above. This is intentional—shadcn CLI expects this format for updates via `bunx shadcn@latest add`.\n\n## Database\n\nDrizzle ORM, schema in `packages/db/src/`. Follow `.agents/skills/db-migrations/SKILL.md` to generate\nmigrations and to clear its production safety checklist before opening the PR. Never hand-edit `packages/db/drizzle/` (SQL, `meta/_journal.json`, snapshots) without\nexplicit user confirmation, and never apply migrations against a shared or production database.\n\n## Releases\n\nDesktop, host-service, and cli share one version; cut releases on a dedicated branch. Runbook:\n`scripts/release/README.md`. A *canary* is a separate thing: `bash scripts/release-canary.sh\n[commit]` builds the rolling internal `desktop-canary` prerelease, not a versioned release.\n\n## Plugins\n\nFirst-party plugins live in `plugins/<name>/`: a `plugin.json` manifest and `skills/`. A plugin\nships no code — agents reach its tools through `/mcp/plugins/<marketplace>/<plugin>` on the API,\nwhich proxies to the vendor's MCP server or, for the plugins named in the `SUPERSET_HOSTED_PLUGINS` constant,\nserves them from `packages/trpc/src/router/plugins/servers/`. A release is the git tag\n`<name>@<version>` on this repo — that tree is what a host\ndownloads — and `packages/shared/src/plugins/manifests.generated.ts` is the bundle the API resolves\nagainst, which is generated and must never be hand-edited. Change the source, then\n`superset plugins publish <name> --bump patch`, which rewrites the marketplace entry in\n`.agent-marketplace.json` and the generated manifests; commit and tag to publish it. `bun run check:plugins` is what CI\nruns to catch a change that skipped that step; run it before pushing.\n\nInstalled plugins are recorded once per machine in\n`$SUPERSET_HOME_DIR/plugins/installed_plugins.json` (`SUPERSET_HOME` is the CLI's install prefix and\nmeans nothing here). Every provisioner reads that one file — the desktop at boot, `plugins sync`,\nthe host-service — because provisioning is declarative and reaps whatever is absent from the desired\nset. A caller that passes its own list instead makes the last writer delete the others' skills.\nDetails: `docs/plugins.md`.\n\n## Orchestrating agents and workspaces\n\nWhen work wants a fresh isolated environment, a parallel agent, or a long-running job, reach for the\n`superset` CLI instead of hand-rolling git worktrees or doing it all serially in this one. It's\nalready on `PATH` in Superset terminals, and we dogfood it.\n\nReplace the capitalized placeholders before running these:\n\n```bash\nsuperset ws create --local --project PROJECT_ID --branch BRANCH --agent claude --prompt \"...\"\nsuperset agents create --workspace WORKSPACE_ID --agent claude --prompt \"...\"\nsuperset ws list --local\nsuperset terminals read --workspace WORKSPACE_ID --terminal TERMINAL_ID\nsuperset ws archive --local WORKSPACE_ID\n```\n\nIn order: an isolated workspace with an agent already working in it, another agent in an existing\nworkspace, what's running, what an agent is doing right now, and cleanup when you're done.\n\nSpawning several related workspaces? Add `--tag SOME_TAG` (repeatable) to `ws create` — tagged\nworkspaces group into a sidebar folder of that name automatically, so a batch files itself instead\nof scattering across the project. `ws list --local --tag SOME_TAG` filters to them, and\n`ws update WORKSPACE_ID --tag ...` retags (`--clear-tags` ungroups). Automation-created workspaces\nare tagged `automation` by default and collect in an \"automation\" folder.\n\n`superset schema` prints every command, option and argument as JSON; read it with `jq` to learn the\nrest (tasks, automations, hosts, settings) instead of parsing `--help` text. To check only that a\ncommand exists, the exit code of `superset <command> --help` is enough. Details and the version\ncaveat: `docs/agent-tooling.md`.\n\n```bash\nsuperset schema | jq '.commands[] | select(.path==[\"terminals\"]) | .commands[] | {path, options: [.options[].name]}'\n```\n\nPass `--json` for parsable output; it's on by default under agent environments.\n\n## Internationalization\n\nUser-facing strings use Lingui macros with the English text as the message id —\n`<Trans>Text</Trans>` or `useLingui()`'s `t({ message })` in React, `i18n._(msg({ message }))`\noutside React (Electron main). Identical English with different meanings gets a `context`\nso it translates separately. Numbers, currencies, and dates go through\n`@superset/i18n/format` helpers, never `new Intl.*(\"en-US\")` or `toLocale*` with a hardcoded\nlocale. After adding or changing strings, run `bun run check:i18n` (CI enforces it): it\nregenerates the catalogs and lists every untranslated message per locale. Write those\ntranslations yourself into each `locales/<locale>/messages.po` and commit the catalogs with\nthe change — nothing on CI fills translations for you. Conventions: `packages/i18n/README.md`;\nterms that never translate: `packages/i18n/glossary.md`; strategy and phasing:\n`plans/20260826-i18n-strategy.md`.\nDirectories listed in `packages/i18n/test/enforced-dirs.ts` must not contain hardcoded\nJSX text — add a directory there once it is fully converted. `errorMessage()` output is potentially\ntranslated and is display-only: logs, Sentry/PostHog, and error classification use\n`rawErrorMessage()` or the error object (enforced by `packages/i18n/test/display-only.test.ts`).\n\n**Shipping locales.** `SUPPORTED_LOCALES` in `packages/i18n/src/locales.ts` is the single\nsource of truth — adding a locale there is what makes it appear in the Settings picker and\nthe optional onboarding step, and what `lingui.config.ts` must list. Every enabled locale\nmust be **fully translated**: `compile --strict` fails the build on a missing message, so\nfinish a translation before adding its locale. Native language names live in `LOCALE_LABELS`\nand are never translated — someone stuck in the wrong language has to recognize their own.\nRelative times use `formatRelativeTime`/`formatCompactRelativeTime`, not hand-rolled\n\"3d ago\" helpers; `Intl` already knows every locale's wording.\n\nThree traps worth knowing before you touch catalogs:\n\n- **Editing English copy re-keys the message.** The text is the id, so an edit creates a\n  new entry that is empty in every locale and `check:i18n` lists it. If the edit was cosmetic,\n  the old translations are still in `git diff` on the catalogs to copy from.\n- **Regenerate from a clean tree.** `lingui.config.ts` keeps `messages.po` deterministic:\n  `orderBy: \"message\"` fixes entry order, and `origins: false` drops the `#:` file\n  references, whose order follows filesystem traversal and differs between macOS and\n  Linux. A catalog regenerated on top of local experiments will still commit noise.\n- **`bun test` runs uncompiled source.** The Lingui macro rewrites `` message: `${n} items` ``\n  into a placeholder message plus values at build time, so the catalog stores `{n} items`.\n  Tests see neither, which is why `apps/desktop/test-setup.ts` shims the macros and `i18n._`.\n  Mock that module with a Proxy, never a spread — `i18n` is a class instance and a spread\n  drops `load`/`activate`.\n\n## Comments\n\nNever comment unless the thing can never be self-describing in the code. Name it, structure it,\nor type it first; a comment is the last resort for what the code genuinely cannot say — a\nconstraint that lives outside the repo, or a trap the next reader would walk into. Rationale goes\nin the commit message and the PR.\n\n## Tests\n\nCI runs every suite on each push, and the whole run is meant to stay near two minutes. A test\nearns its place by catching a regression quickly.\n\n- **No real waiting.** A test that needs more than bun's default 5 s timeout is too slow. Do not\n  raise the timeout: pass the delay, clock or retry count in and test with a small value. Never\n  wait for a real network or process timeout to fire.\n- **One test per behaviour.** Stress, fuzz and \"adversarial\" suites that build many real git\n  repositories or processes do not go in the repo. When a probe finds a bug, keep the one\n  regression test for it.\n- **Any order, clean checkout.** Each package's suite runs in one process, in an order that differs\n  between machines, with no root `.env`. Do not `mock.module` a module that other files import for\n  real (`env`, a client, a logger). Give the code its input instead: a parameter, a placeholder in\n  the package's test preload, or a local server.\n- **A flaky test is a broken test.** Fix the cause or delete it. Do not add retries or longer\n  timeouts.\n- **Node-only suites** (real PTYs, `node:test`) are `*.node-test.ts` files run by a turbo task, so\n  they run beside the bun suites and not after them.\n\n## Further reading\n\n- `.agents/skills/`: CDP UI verification, mobile simulator verification, DB migrations, tRPC\n  compatibility, ticket format, and more. Read the matching `SKILL.md` when a task fits its\n  description.\n- `docs/agent-tooling.md`: where commands, skills, and per-agent-CLI config live.\n- `docs/plugins.md`: authoring, publishing, and installing marketplace plugins — the manifest\n  contract, the credential proxy, and which files are generated.\n- `docs/environment-variables.md`: read before adding an environment variable. Five places,\n  and missing one fails silently.\n- `docs/deploy-workflows.md`: read before writing or testing a deploy workflow step. `run:` has\n  no `pipefail` by default, and production secrets exist only in GitHub.\n- `packages/trpc/AGENTS.md`: read before changing any tRPC procedure, in `packages/trpc` or\n  `packages/host-service`. Released desktop, mobile, and CLI builds still call it.\n- `apps/desktop/AGENTS.md`: desktop specifics (notices, persisted renderer state).\n- `apps/mobile/AGENTS.md`: mobile structure and iOS-only scope.\n- `docs/cloud-sandbox-mismatches.md`: where cloud workspace sandboxes don't fit assumptions the\n  app makes about a machine someone owns. Read it before touching sandboxes, and add to it when\n  you find a new one.\n- `docs/cloud-sandbox-considerations.md`: what cloud sandboxes still owe before they leave the\n  team — billing, credential blast radius, untested behaviour.\n\n## Contributor responsibility\n\nContributors are responsible for every change they submit, including agent-generated code.\nThey must understand the changes, review the diff, and verify the behavior before requesting\nreview.\n\n- Ask for clarification when a request lacks enough context to make a correct change.\n- Explain changes and validation so the contributor can review and understand the result.\n- Agents may write commit messages and PR descriptions, commit changes, push branches, create\n  PRs, and address review feedback when authorized by the user.\n- Only post replies to reviewers when the user explicitly authorizes it.\n- Never claim that checks passed or behavior was verified unless it actually was.\n\n## Code standards\n\n- Keep code comments concise (usually 1-2 lines)\n- Avoid redundant or excessive inline commentary\n- Use ASD-STE100 Simplified Technical English, simple wordings\n\n### Examples\n\n```c++\n  // Good (no comment)\n\n  std::string module_name =\n    fmt::format(\"{}_{:x}\", name_, std::hash<std::string>{}(source_));\n\n  // Bad (excessive comment for explicit code)\n\n  // The module cache is keyed on this name, so it has to include the source:\n  // two kernels sharing a name but not a body would otherwise both run\n  // whichever was compiled first. Same fix as 3833 on the Metal side.\n```\n","isInternal":false,"tokens":3559,"sizeBytes":15229},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/marketplace.json","title":"Claude Plugin Marketplace Catalog","category":"marketplace","format":"json","content":"# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/marketplace.json)","tokens":300,"sizeBytes":199},{"name":"plugin.json","path":".claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":185},{"name":"mcp.json","path":".cursor/mcp.json","rawUrl":"https://raw.githubusercontent.com/superset-sh/superset/HEAD/.cursor/mcp.json","title":"Model Context Protocol (MCP) Configuration","category":"mcp-config","format":"json","content":"# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.cursor/mcp.json)","tokens":300,"sizeBytes":178}],"systemPromptSnippet":"<yakaai_skills repo=\"superset-sh/superset\">\n<!-- File: AGENTS.md (Tokens: ~3559 | Category: root-instruction) -->\n# Superset Monorepo\n\nSuperset is an agent-first development platform, with an Electron desktop IDE, Next.js web apps, and an Expo mobile app as the main customer-facing surfaces. It's a Turborepo monorepo, deployed apps are in apps/ and supporting packages are in packages/, and we use tRPC for the api.\n\nYou're working inside a Superset workspace, an isolated checkout of this repo — a git worktree on a\nmachine someone owns, a plain clone at `/workspace` in a cloud workspace. \"Workspace\" in a user\nmessage means that, not an editor workspace.\n\n## Project Structure\n\nAll projects in this repo should be structured like this:\n\n```\napp/\n├── page.tsx\n├── dashboard/\n│   ├── page.tsx\n│   ├── components/\n│   │   └── MetricsChart/\n│   │       ├── MetricsChart.tsx\n│   │       ├── MetricsChart.test.tsx      # Tests co-located\n│   │       ├── index.ts\n│   │       └── constants.ts\n│   ├── hooks/                             # Hooks used only in dashboard\n│   │   └── useMetrics/\n│   │       ├── useMetrics.ts\n│   │       ├── useMetrics.test.ts\n│   │       └── index.ts\n│   ├── utils/                             # Utils used only in dashboard\n│   │   └── formatData/\n│   │       ├── formatData.ts\n│   │       ├── formatData.test.ts\n│   │       └── index.ts\n│   ├── stores/                            # Stores used only in dashboard\n│   │   └── dashboardStore/\n│   │       ├── dashboardStore.ts\n│   │       └── index.ts\n│   └── providers/                         # Providers for dashboard context\n│       └── DashboardProvider/\n│           ├── DashboardProvider.tsx\n│           └── index.ts\n└── components/\n    ├── Sidebar/\n    │   ├── Sidebar.tsx\n    │   ├── Sidebar.test.tsx               # Tests co-located\n    │   ├── index.ts\n    │   ├── components/                    # Used 2+ times IN Sidebar\n    │   │   └── SidebarButton/             # Shared by SidebarNav + SidebarFooter\n    │   │       ├── SidebarButton.tsx\n    │   │       ├── SidebarButton.test.tsx\n    │   │       └── index.ts\n    │   ├── SidebarNav/\n    │   │   ├── SidebarNav.tsx\n    │   │   └── index.ts\n    │   └── SidebarFooter/\n    │       ├── SidebarFooter.tsx\n    │       └── index.ts\n    └── HeroSection/\n        ├── HeroSection.tsx\n        ├── HeroSection.test.tsx           # Tests co-located\n        ├── index.ts\n        └── components/                    # Used ONLY by HeroSection\n            └── HeroCanvas/\n                ├── HeroCanvas.tsx\n                ├── HeroCanvas.test.tsx\n                ├── HeroCanvas.stories.tsx\n                ├── index.ts\n                └── config.ts\n\ncomponents/                                # Used in 2+ pages (last resort)\n└── Header/\n```\n\n1. **One folder per component**: `ComponentName/ComponentName.tsx` + `index.ts` for barrel export\n2. **Co-locate by usage**: If used once, nest under parent's `components/`. If used 2+ times, promote to **highest shared parent's** `components/` (or `components/` as last resort)\n3. **One component per file**: No multi-component files\n4. **Co-locate dependencies**: Utils, hooks, constants, config, tests, stories live next to the file using them\n\n### Exception: shadcn/ui Components\n\nThe `src/components/ui/` and `src/components/ai-elements` directories contain shadcn/ui components. These use **kebab-case single files** (e.g., `button.tsx`, `base-node.tsx`) instead of the folder structure above. This is intentional—shadcn CLI expects this format for updates via `bunx shadcn@latest add`.\n\n## Database\n\nDrizzle ORM, schema in `packages/db/src/`. Follow `.agents/skills/db-migrations/SKILL.md` to generate\nmigrations and to clear its production safety checklist before opening the PR. Never hand-edit `packages/db/drizzle/` (SQL, `meta/_journal.json`, snapshots) without\nexplicit user confirmation, and never apply migrations against a shared or production database.\n\n## Releases\n\nDesktop, host-service, and cli share one version; cut releases on a dedicated branch. Runbook:\n`scripts/release/README.md`. A *canary* is a separate thing: `bash scripts/release-canary.sh\n[commit]` builds the rolling internal `desktop-canary` prerelease, not a versioned release.\n\n## Plugins\n\nFirst-party plugins live in `plugins/<name>/`: a `plugin.json` manifest and `skills/`. A plugin\nships no code — agents reach its tools through `/mcp/plugins/<marketplace>/<plugin>` on the API,\nwhich proxies to the vendor's MCP server or, for the plugins named in the `SUPERSET_HOSTED_PLUGINS` constant,\nserves them from `packages/trpc/src/router/plugins/servers/`. A release is the git tag\n`<name>@<version>` on this repo — that tree is what a host\ndownloads — and `packages/shared/src/plugins/manifests.generated.ts` is the bundle the API resolves\nagainst, which is generated and must never be hand-edited. Change the source, then\n`superset plugins publish <name> --bump patch`, which rewrites the marketplace entry in\n`.agent-marketplace.json` and the generated manifests; commit and tag to publish it. `bun run check:plugins` is what CI\nruns to catch a change that skipped that step; run it before pushing.\n\nInstalled plugins are recorded once per machine in\n`$SUPERSET_HOME_DIR/plugins/installed_plugins.json` (`SUPERSET_HOME` is the CLI's install prefix and\nmeans nothing here). Every provisioner reads that one file — the desktop at boot, `plugins sync`,\nthe host-service — because provisioning is declarative and reaps whatever is absent from the desired\nset. A caller that passes its own list instead makes the last writer delete the others' skills.\nDetails: `docs/plugins.md`.\n\n## Orchestrating agents and workspaces\n\nWhen work wants a fresh isolated environment, a parallel agent, or a long-running job, reach for the\n`superset` CLI instead of hand-rolling git worktrees or doing it all serially in this one. It's\nalready on `PATH` in Superset terminals, and we dogfood it.\n\nReplace the capitalized placeholders before running these:\n\n```bash\nsuperset ws create --local --project PROJECT_ID --branch BRANCH --agent claude --prompt \"...\"\nsuperset agents create --workspace WORKSPACE_ID --agent claude --prompt \"...\"\nsuperset ws list --local\nsuperset terminals read --workspace WORKSPACE_ID --terminal TERMINAL_ID\nsuperset ws archive --local WORKSPACE_ID\n```\n\nIn order: an isolated workspace with an agent already working in it, another agent in an existing\nworkspace, what's running, what an agent is doing right now, and cleanup when you're done.\n\nSpawning several related workspaces? Add `--tag SOME_TAG` (repeatable) to `ws create` — tagged\nworkspaces group into a sidebar folder of that name automatically, so a batch files itself instead\nof scattering across the project. `ws list --local --tag SOME_TAG` filters to them, and\n`ws update WORKSPACE_ID --tag ...` retags (`--clear-tags` ungroups). Automation-created workspaces\nare tagged `automation` by default and collect in an \"automation\" folder.\n\n`superset schema` prints every command, option and argument as JSON; read it with `jq` to learn the\nrest (tasks, automations, hosts, settings) instead of parsing `--help` text. To check only that a\ncommand exists, the exit code of `superset <command> --help` is enough. Details and the version\ncaveat: `docs/agent-tooling.md`.\n\n```bash\nsuperset schema | jq '.commands[] | select(.path==[\"terminals\"]) | .commands[] | {path, options: [.options[].name]}'\n```\n\nPass `--json` for parsable output; it's on by default under agent environments.\n\n## Internationalization\n\nUser-facing strings use Lingui macros with the English text as the message id —\n`<Trans>Text</Trans>` or `useLingui()`'s `t({ message })` in React, `i18n._(msg({ message }))`\noutside React (Electron main). Identical English with different meanings gets a `context`\nso it translates separately. Numbers, currencies, and dates go through\n`@superset/i18n/format` helpers, never `new Intl.*(\"en-US\")` or `toLocale*` with a hardcoded\nlocale. After adding or changing strings, run `bun run check:i18n` (CI enforces it): it\nregenerates the catalogs and lists every untranslated message per locale. Write those\ntranslations yourself into each `locales/<locale>/messages.po` and commit the catalogs with\nthe change — nothing on CI fills translations for you. Conventions: `packages/i18n/README.md`;\nterms that never translate: `packages/i18n/glossary.md`; strategy and phasing:\n`plans/20260826-i18n-strategy.md`.\nDirectories listed in `packages/i18n/test/enforced-dirs.ts` must not contain hardcoded\nJSX text — add a directory there once it is fully converted. `errorMessage()` output is potentially\ntranslated and is display-only: logs, Sentry/PostHog, and error classification use\n`rawErrorMessage()` or the error object (enforced by `packages/i18n/test/display-only.test.ts`).\n\n**Shipping locales.** `SUPPORTED_LOCALES` in `packages/i18n/src/locales.ts` is the single\nsource of truth — adding a locale there is what makes it appear in the Settings picker and\nthe optional onboarding step, and what `lingui.config.ts` must list. Every enabled locale\nmust be **fully translated**: `compile --strict` fails the build on a missing message, so\nfinish a translation before adding its locale. Native language names live in `LOCALE_LABELS`\nand are never translated — someone stuck in the wrong language has to recognize their own.\nRelative times use `formatRelativeTime`/`formatCompactRelativeTime`, not hand-rolled\n\"3d ago\" helpers; `Intl` already knows every locale's wording.\n\nThree traps worth knowing before you touch catalogs:\n\n- **Editing English copy re-keys the message.** The text is the id, so an edit creates a\n  new entry that is empty in every locale and `check:i18n` lists it. If the edit was cosmetic,\n  the old translations are still in `git diff` on the catalogs to copy from.\n- **Regenerate from a clean tree.** `lingui.config.ts` keeps `messages.po` deterministic:\n  `orderBy: \"message\"` fixes entry order, and `origins: false` drops the `#:` file\n  references, whose order follows filesystem traversal and differs between macOS and\n  Linux. A catalog regenerated on top of local experiments will still commit noise.\n- **`bun test` runs uncompiled source.** The Lingui macro rewrites `` message: `${n} items` ``\n  into a placeholder message plus values at build time, so the catalog stores `{n} items`.\n  Tests see neither, which is why `apps/desktop/test-setup.ts` shims the macros and `i18n._`.\n  Mock that module with a Proxy, never a spread — `i18n` is a class instance and a spread\n  drops `load`/`activate`.\n\n## Comments\n\nNever comment unless the thing can never be self-describing in the code. Name it, structure it,\nor type it first; a comment is the last resort for what the code genuinely cannot say — a\nconstraint that lives outside the repo, or a trap the next reader would walk into. Rationale goes\nin the commit message and the PR.\n\n## Tests\n\nCI runs every suite on each push, and the whole run is meant to stay near two minutes. A test\nearns its place by catching a regression quickly.\n\n- **No real waiting.** A test that needs more than bun's default 5 s timeout is too slow. Do not\n  raise the timeout: pass the delay, clock or retry count in and test with a small value. Never\n  wait for a real network or process timeout to fire.\n- **One test per behaviour.** Stress, fuzz and \"adversarial\" suites that build many real git\n  repositories or processes do not go in the repo. When a probe finds a bug, keep the one\n  regression test for it.\n- **Any order, clean checkout.** Each package's suite runs in one process, in an order that differs\n  between machines, with no root `.env`. Do not `mock.module` a module that other files import for\n  real (`env`, a client, a logger). Give the code its input instead: a parameter, a placeholder in\n  the package's test preload, or a local server.\n- **A flaky test is a broken test.** Fix the cause or delete it. Do not add retries or longer\n  timeouts.\n- **Node-only suites** (real PTYs, `node:test`) are `*.node-test.ts` files run by a turbo task, so\n  they run beside the bun suites and not after them.\n\n## Further reading\n\n- `.agents/skills/`: CDP UI verification, mobile simulator verification, DB migrations, tRPC\n  compatibility, ticket format, and more. Read the matching `SKILL.md` when a task fits its\n  description.\n- `docs/agent-tooling.md`: where commands, skills, and per-agent-CLI config live.\n- `docs/plugins.md`: authoring, publishing, and installing marketplace plugins — the manifest\n  contract, the credential proxy, and which files are generated.\n- `docs/environment-variables.md`: read before adding an environment variable. Five places,\n  and missing one fails silently.\n- `docs/deploy-workflows.md`: read before writing or testing a deploy workflow step. `run:` has\n  no `pipefail` by default, and production secrets exist only in GitHub.\n- `packages/trpc/AGENTS.md`: read before changing any tRPC procedure, in `packages/trpc` or\n  `packages/host-service`. Released desktop, mobile, and CLI builds still call it.\n- `apps/desktop/AGENTS.md`: desktop specifics (notices, persisted renderer state).\n- `apps/mobile/AGENTS.md`: mobile structure and iOS-only scope.\n- `docs/cloud-sandbox-mismatches.md`: where cloud workspace sandboxes don't fit assumptions the\n  app makes about a machine someone owns. Read it before touching sandboxes, and add to it when\n  you find a new one.\n- `docs/cloud-sandbox-considerations.md`: what cloud sandboxes still owe before they leave the\n  team — billing, credential blast radius, untested behaviour.\n\n## Contributor responsibility\n\nContributors are responsible for every change they submit, including agent-generated code.\nThey must understand the changes, review the diff, and verify the behavior before requesting\nreview.\n\n- Ask for clarification when a request lacks enough context to make a correct change.\n- Explain changes and validation so the contributor can review and understand the result.\n- Agents may write commit messages and PR descriptions, commit changes, push branches, create\n  PRs, and address review feedback when authorized by the user.\n- Only post replies to reviewers when the user explicitly authorizes it.\n- Never claim that checks passed or behavior was verified unless it actually was.\n\n## Code standards\n\n- Keep code comments concise (usually 1-2 lines)\n- Avoid redundant or excessive inline commentary\n- Use ASD-STE100 Simplified Technical English, simple wordings\n\n### Examples\n\n```c++\n  // Good (no comment)\n\n  std::string module_name =\n    fmt::format(\"{}_{:x}\", name_, std::hash<std::string>{}(source_));\n\n  // Bad (excessive comment for explicit code)\n\n  // The module cache is keyed on this name, so it has to include the source:\n  // two kernels sharing a name but not a body would otherwise both run\n  // whichever was compiled first. Same fix as 3833 on the Metal side.\n```\n\n<!-- File: .claude-plugin/marketplace.json (Tokens: ~300 | Category: marketplace) -->\n# Claude Plugin Marketplace Catalog\n\nPath: `.claude-plugin/marketplace.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/marketplace.json)\n\n<!-- File: .claude-plugin/plugin.json (Tokens: ~300 | Category: plugin-manifest) -->\n# claude-plugin Plugin Manifest\n\nPath: `.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.claude-plugin/plugin.json)\n\n<!-- File: .cursor/mcp.json (Tokens: ~300 | Category: mcp-config) -->\n# Model Context Protocol (MCP) Configuration\n\nPath: `.cursor/mcp.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/superset-sh/superset/HEAD/.cursor/mcp.json)\n</yakaai_skills>"}