{"owner":"tambo-ai","repo":"tambo","hasSkills":true,"totalSkillsCount":193,"totalTokensCount":75106,"categories":["anthropic-skill","marketplace","root-instruction","claude-rule","subagent-persona","command-prompt","plugin-manifest"],"hasMcp":true,"mcpConfig":{"mcpServers":{"tambo":{"command":"npx","args":["-y","@modelcontextprotocol/server-tambo"]}}},"found":[".claude/skills/ai-sdk-model-manager/SKILL.md",".claude/skills/creating-styled-wrappers/SKILL.md",".claude/skills/api-resource-lifecycle/SKILL.md",".claude/skills/compound-components/SKILL.md",".claude/skills/validating-accessibility/SKILL.md",".claude-plugin/marketplace.json",".claude/skills/building-settings-ui/SKILL.md","plugins/tambo/skills/generative-ui/SKILL.md",".github/AGENTS.md","CLAUDE.md","AGENTS.md","cli/AGENTS.md","cli/CLAUDE.md","create-tambo-app/AGENTS.md","create-tambo-app/CLAUDE.md","docs/AGENTS.md","docs/CLAUDE.md","react-sdk/AGENTS.md","react-sdk/CLAUDE.md","showcase/AGENTS.md","showcase/CLAUDE.md",".claude/agents/planner.md",".claude/agents/researcher.md",".claude/commands/commit.md",".claude/commands/create-pr.md",".claude/commands/execute.md",".claude/commands/plan.md","packages/backend/README.md","packages/backend/package.json","packages/backend/tsconfig.build.json","packages/backend/tsconfig.json","packages/client/AGENTS.md","packages/client/CHANGELOG.md","packages/client/CLAUDE.md","packages/client/README.md","packages/client/package.json","packages/client/tsconfig.cjs.json","packages/client/tsconfig.esm.json","packages/client/tsconfig.json","packages/core/README.md","packages/core/package.json","packages/core/tsconfig.json","packages/db/README.md","packages/db/package.json","packages/db/tsconfig.json","packages/eslint-config/README.md","packages/eslint-config/package.json","packages/react-ui-base/CHANGELOG.md","packages/react-ui-base/README.md","packages/react-ui-base/package.json","packages/react-ui-base/tsconfig.json","packages/testing/package.json","packages/testing/tsconfig.json","packages/typescript-config/base.json","packages/typescript-config/nextjs.json","packages/typescript-config/package.json","packages/typescript-config/react-library.json","packages/ui-registry/AGENTS.md","packages/ui-registry/package.json","packages/ui-registry/tsconfig.json","packages/vite-config/package.json","packages/vite-config/tsconfig.json","plugins/tambo/README.md",".claude/skills/compound-components/examples.md","plugins/tambo/.claude-plugin/plugin.json",".claude/skills/creating-styled-wrappers/references/real-world-example.md","packages/db/migrations/meta/0000_snapshot.json","packages/db/migrations/meta/0001_snapshot.json","packages/db/migrations/meta/0002_snapshot.json","packages/db/migrations/meta/0003_snapshot.json","packages/db/migrations/meta/0004_snapshot.json","packages/db/migrations/meta/0005_snapshot.json","packages/db/migrations/meta/0006_snapshot.json","packages/db/migrations/meta/0007_snapshot.json","packages/db/migrations/meta/0008_snapshot.json","packages/db/migrations/meta/0009_snapshot.json","packages/db/migrations/meta/0010_snapshot.json","packages/db/migrations/meta/0011_snapshot.json","packages/db/migrations/meta/0012_snapshot.json","packages/db/migrations/meta/0013_snapshot.json","packages/db/migrations/meta/0014_snapshot.json","packages/db/migrations/meta/0015_snapshot.json","packages/db/migrations/meta/0016_snapshot.json","packages/db/migrations/meta/0017_snapshot.json","packages/db/migrations/meta/0018_snapshot.json","packages/db/migrations/meta/0019_snapshot.json","packages/db/migrations/meta/0020_snapshot.json","packages/db/migrations/meta/0021_snapshot.json","packages/db/migrations/meta/0022_snapshot.json","packages/db/migrations/meta/0023_snapshot.json","packages/db/migrations/meta/0024_snapshot.json","packages/db/migrations/meta/0025_snapshot.json","packages/db/migrations/meta/0026_snapshot.json","packages/db/migrations/meta/0027_snapshot.json","packages/db/migrations/meta/0028_snapshot.json","packages/db/migrations/meta/0029_snapshot.json","packages/db/migrations/meta/0030_snapshot.json","packages/db/migrations/meta/0031_snapshot.json","packages/db/migrations/meta/0032_snapshot.json","packages/db/migrations/meta/0033_snapshot.json","packages/db/migrations/meta/0034_snapshot.json","packages/db/migrations/meta/0035_snapshot.json","packages/db/migrations/meta/0036_snapshot.json","packages/db/migrations/meta/0037_snapshot.json","packages/db/migrations/meta/0038_snapshot.json","packages/db/migrations/meta/0039_snapshot.json","packages/db/migrations/meta/0040_snapshot.json","packages/db/migrations/meta/0041_snapshot.json","packages/db/migrations/meta/0042_snapshot.json","packages/db/migrations/meta/0043_snapshot.json","packages/db/migrations/meta/0044_snapshot.json","packages/db/migrations/meta/0045_snapshot.json","packages/db/migrations/meta/0046_snapshot.json","packages/db/migrations/meta/0047_snapshot.json","packages/db/migrations/meta/0048_snapshot.json","packages/db/migrations/meta/0049_snapshot.json","packages/db/migrations/meta/0050_snapshot.json","packages/db/migrations/meta/0052_snapshot.json","packages/db/migrations/meta/0053_snapshot.json","packages/db/migrations/meta/0054_snapshot.json","packages/db/migrations/meta/0055_snapshot.json","packages/db/migrations/meta/0056_snapshot.json","packages/db/migrations/meta/0057_snapshot.json","packages/db/migrations/meta/0058_snapshot.json","packages/db/migrations/meta/0059_snapshot.json","packages/db/migrations/meta/0060_snapshot.json","packages/db/migrations/meta/0061_snapshot.json","packages/db/migrations/meta/0062_snapshot.json","packages/db/migrations/meta/0063_snapshot.json","packages/db/migrations/meta/0064_snapshot.json","packages/db/migrations/meta/0065_snapshot.json","packages/db/migrations/meta/0066_snapshot.json","packages/db/migrations/meta/0067_snapshot.json","packages/db/migrations/meta/0068_snapshot.json","packages/db/migrations/meta/0069_snapshot.json","packages/db/migrations/meta/0070_snapshot.json","packages/db/migrations/meta/0071_snapshot.json","packages/db/migrations/meta/0072_snapshot.json","packages/db/migrations/meta/0073_snapshot.json","packages/db/migrations/meta/0074_snapshot.json","packages/db/migrations/meta/0075_snapshot.json","packages/db/migrations/meta/0076_snapshot.json","packages/db/migrations/meta/0077_snapshot.json","packages/db/migrations/meta/0078_snapshot.json","packages/db/migrations/meta/0079_snapshot.json","packages/db/migrations/meta/0080_snapshot.json","packages/db/migrations/meta/0081_snapshot.json","packages/db/migrations/meta/0082_snapshot.json","packages/db/migrations/meta/0083_snapshot.json","packages/db/migrations/meta/0084_snapshot.json","packages/db/migrations/meta/0085_snapshot.json","packages/db/migrations/meta/0086_snapshot.json","packages/db/migrations/meta/0087_snapshot.json","packages/db/migrations/meta/0088_snapshot.json","packages/db/migrations/meta/0089_snapshot.json","packages/db/migrations/meta/0090_snapshot.json","packages/db/migrations/meta/0091_snapshot.json","packages/db/migrations/meta/0092_snapshot.json","packages/db/migrations/meta/0093_snapshot.json","packages/db/migrations/meta/0094_snapshot.json","packages/db/migrations/meta/_journal.json","packages/ui-registry/src/components/control-bar/config.json","packages/ui-registry/src/components/edit-with-tambo-button/config.json","packages/ui-registry/src/components/elicitation-ui/config.json","packages/ui-registry/src/components/form/config.json","packages/ui-registry/src/components/graph/config.json","packages/ui-registry/src/components/input-fields/config.json","packages/ui-registry/src/components/map/config.json","packages/ui-registry/src/components/mcp-components/config.json","packages/ui-registry/src/components/message-input/config.json","packages/ui-registry/src/components/message-suggestions/config.json","packages/ui-registry/src/components/message-thread-collapsible/config.json","packages/ui-registry/src/components/message-thread-full/config.json","packages/ui-registry/src/components/message-thread-panel/config.json","packages/ui-registry/src/components/message/config.json","packages/ui-registry/src/components/scrollable-message-container/config.json","packages/ui-registry/src/components/thread-content/config.json","packages/ui-registry/src/components/thread-dropdown/config.json","packages/ui-registry/src/components/thread-history/config.json","plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md","plugins/tambo/skills/building-with-tambo/references/cli.md","plugins/tambo/skills/building-with-tambo/references/component-rendering.md","plugins/tambo/skills/building-with-tambo/references/components.md","plugins/tambo/skills/building-with-tambo/references/skills.md","plugins/tambo/skills/building-with-tambo/references/threads.md","plugins/tambo/skills/building-with-tambo/references/tools-and-context.md","plugins/tambo/skills/generative-ui/references/cli.md","plugins/tambo/skills/generative-ui/references/component-rendering.md","plugins/tambo/skills/generative-ui/references/components.md","plugins/tambo/skills/generative-ui/references/skills.md","plugins/tambo/skills/generative-ui/references/threads.md","plugins/tambo/skills/generative-ui/references/tools-and-context.md","docs/content/docs/reference/cli/commands/meta.json"],"skills":{".claude/skills/ai-sdk-model-manager/SKILL.md":"---\nname: ai-sdk-model-manager\ndescription: Manages AI SDK model configurations - updates packages, identifies missing models, adds new models with research, and updates documentation\nmetadata:\n  internal: true\n---\n\n# AI SDK Model Manager\n\nThis skill helps maintain AI SDK model configurations in the Tambo Cloud codebase. It automates the process of keeping model definitions up-to-date with the latest AI SDK releases.\n\n## What This Skill Does\n\n1. **Updates AI SDK Packages** - Checks and updates @ai-sdk/openai, @ai-sdk/google, @ai-sdk/groq, and other provider packages to their latest versions\n2. **Identifies Missing Models** - Compares TypeScript definitions in the SDKs against configured models to find newly available models\n3. **Researches Models** - Gathers information about new models including capabilities, context windows, pricing, and use cases\n4. **Prompts User** - Asks which models to add before making changes\n5. **Adds Models** - Updates model configuration files with proper TypeScript types and metadata\n6. **Updates Documentation** - Updates relevant docs and README files to reflect new model availability\n\n## When to Use This Skill\n\nUse this skill when:\n\n- You want to check if AI SDK packages need updating\n- New models have been released by OpenAI, Google, Anthropic, or other providers\n- You're getting TypeScript errors about model IDs not being in SDK types\n- You want to ensure Tambo supports the latest models\n\n## Files This Skill Works With\n\n- `packages/core/src/llms/models/*.ts` - Model configuration files\n- `packages/backend/package.json` - AI SDK dependencies (source of truth for versions)\n- `docs/content/docs/models/*.mdx` - Model documentation\n- `README.md` - Main documentation file\n\n## Process\n\n### Step 1: Update AI SDK Packages\n\nCheck current versions and update to latest:\n\n```bash\ncd packages/backend\nnpm outdated | grep '@ai-sdk'\nnpm install @ai-sdk/openai@latest @ai-sdk/google@latest @ai-sdk/groq@latest @ai-sdk/anthropic@latest @ai-sdk/mistral@latest\n```\n\n### Step 2: Identify Missing Models\n\nFor each provider, inspect the TypeScript definitions:\n\n```bash\n# Check what models are in the SDK types\ncat node_modules/@ai-sdk/openai/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/google/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/groq/dist/index.d.ts | grep 'type.*ModelId'\n```\n\nCompare against current model configurations in:\n\n- `packages/core/src/llms/models/openai.ts`\n- `packages/core/src/llms/models/gemini.ts`\n- `packages/core/src/llms/models/groq.ts`\n- `packages/core/src/llms/models/anthropic.ts`\n- `packages/core/src/llms/models/mistral.ts`\n\n### Step 3: Research New Models\n\n**Use the researcher subagent to gather information about each missing model:**\n\n```\nLaunch a researcher subagent to find:\n- Official documentation link\n- Model capabilities (reasoning, vision, function calling, etc.)\n- Context window size (inputTokenLimit)\n- Pricing tier\n- Best use cases\n- Release date and status (experimental, stable, deprecated)\n```\n\nThe researcher subagent has access to web search and can efficiently gather this information for multiple models in parallel.\n\n### Step 4: Prompt User\n\nPresent findings:\n\n```\nFound the following new models in updated AI SDK packages:\n\nOpenAI:\n- gpt-6-preview (200k context, experimental reasoning model)\n- gpt-4.2-turbo (1M context, improved function calling)\n\nGoogle:\n- gemini-3.5-pro (2M context, advanced reasoning)\n\nWhich models would you like to add? (all/none/specific)\n```\n\nWait for user response before proceeding.\n\n### Step 5: Add Selected Models\n\n**Consider launching parallel subagents to add models to each provider file:**\n\nFor models spread across multiple providers (OpenAI, Google, Groq), launch separate subagents to edit each file concurrently. This is faster than doing them sequentially.\n\nFor each model being added, ensure these required fields:\n\n- `apiName`: Exact model ID string from SDK\n- `displayName`: Human-friendly name\n- `status`: \"untested\" | \"tested\" | \"known-issues\"\n- `notes`: Brief description of capabilities and use cases\n- `docLink`: Official provider documentation URL\n- `tamboDocLink`: \"https://docs.tambo.co\"\n- `inputTokenLimit`: Context window size in tokens\n- `modelSpecificParams`: Any special parameters (reasoning, thinking, etc.)\n\nFollow existing patterns in each file and ensure model IDs match SDK type definitions exactly.\n\nExample:\n\n```typescript\n\"gpt-6-preview\": {\n  apiName: \"gpt-6-preview\",\n  displayName: \"gpt-6-preview\",\n  status: \"untested\",\n  notes: \"Experimental next-generation reasoning model with extended context\",\n  docLink: \"https://platform.openai.com/docs/models/gpt-6-preview\",\n  tamboDocLink: \"https://docs.tambo.co\",\n  inputTokenLimit: 200000,\n  modelSpecificParams: reasoningParameters,\n},\n```\n\n### Step 6: Verify TypeScript\n\nRun type checking to ensure all model IDs are valid:\n\n```bash\ncd packages/core\nnpm run check-types\n```\n\nIf there are type errors, fix model IDs to match SDK definitions exactly.\n\n### Step 7: Update Documentation\n\n**Consider using subagents to update documentation in parallel:**\n\nIf updating multiple documentation files, launch parallel subagents to handle:\n\n1. **README.md** - Update the \"Supported LLM Providers\" section if new providers or significant models were added\n2. **docs/content/docs/models/\\*.mdx** - Add new models to appropriate documentation pages with:\n   - Model name and description\n   - Key capabilities\n   - Context window\n   - Example use cases\n   - Links to provider docs\n\n### Step 8: Run Quality Checks\n\nBefore completing:\n\n```bash\ncd packages/core\nnpm run lint\nnpm run check-types\nnpm run test\n```\n\n### Step 9: Create Pull Request\n\n**Create a PR with proper conventional commit format:**\n\n```bash\ngh pr create --title \"feat(models): add [model names] support\" --body \"$(cat <<'EOF'\nUpdated AI SDK packages and added support for newly released models:\n\nModels added:\n- [list models here]\n\nPackage updates:\n- @ai-sdk/openai: X.X.X → X.X.X\n- @ai-sdk/groq: X.X.X → X.X.X\n\nAll type checks passing, documentation updated.\nEOF\n)\"\n```\n\n**PR title format:** `feat(models): add [model names] support`\n\nUse `feat(models):` for new models or `deps(core):` for package updates only.\n\n## Guidelines\n\n- **Use subagents for efficiency** - Launch researcher subagents for gathering information and parallel subagents for editing multiple files\n- **Always research before adding** - Don't guess at model capabilities or context limits\n- **Match SDK types exactly** - Model IDs must match the TypeScript definitions in node_modules\n- **Mark new models as \"untested\"** - Let the team test before marking as \"tested\"\n- **Include official doc links** - Always link to provider's official documentation\n- **Be conservative** - Only add models the user explicitly approves\n- **Update docs comprehensively** - Don't just update code, update all relevant documentation\n\n## Error Handling\n\nIf you encounter:\n\n- **Type errors after adding models** - Double-check the model ID matches the SDK's TypeScript definition exactly\n- **Missing model in SDK** - The provider may not have released it yet, suggest waiting for next SDK update\n- **Conflicting model names** - Use the SDK's preferred naming convention\n- **Unknown context limits** - Research provider docs or mark as \"unknown\" and note it needs verification\n\n## Notes\n\n- This skill should be run periodically (monthly or when new models are announced)\n- Always check the git diff before committing to ensure only intended changes were made\n- Some models may have special requirements (API access, pricing tier, etc.) - note these in the model's `notes` field\n- If a model is renamed in the SDK, update both the key and apiName, and consider adding a deprecation note to the old entry\n",".claude/skills/creating-styled-wrappers/SKILL.md":"---\nname: creating-styled-wrappers\ndescription: Creates styled wrapper components that compose headless/base compound components. Use when refactoring styled components to use base primitives, implementing opinionated design systems on top of headless components, or when the user mentions \"use base components\", \"compose primitives\", \"styled wrapper\", or \"refactor to use base\".\nmetadata:\n  internal: true\n---\n\n# Styling Compound Wrappers\n\nCreate styled wrapper components that compose headless base compound components. This skill complements `building-compound-components` (which builds the base primitives) by focusing on **how to properly consume and wrap them** with styling and additional behavior.\n\n**Real-world example**: See [references/real-world-example.md](references/real-world-example.md) for a complete before/after MessageInput refactoring.\n\n## Core Principle: Compose, Don't Duplicate\n\nStyled wrappers should **compose** base components, not **re-implement** their logic.\n\n```tsx\n// WRONG - re-implementing what base already does\nconst StyledInput = ({ children, className }) => {\n  const { value, setValue, submit } = useTamboThreadInput(); // Duplicated!\n  const [isDragging, setIsDragging] = useState(false); // Duplicated!\n  const handleDrop = useCallback(/* ... */); // Duplicated!\n\n  return (\n    <form onDrop={handleDrop} className={className}>\n      {children}\n    </form>\n  );\n};\n\n// CORRECT - compose the base component\nconst StyledInput = ({ children, className, variant }) => {\n  return (\n    <BaseInput.Root className={cn(inputVariants({ variant }), className)}>\n      <BaseInput.Content className=\"rounded-xl data-[dragging]:border-dashed\">\n        {children}\n      </BaseInput.Content>\n    </BaseInput.Root>\n  );\n};\n```\n\n## Refactoring Workflow\n\nCopy this checklist and track progress:\n\n```\nStyled Wrapper Refactoring:\n- [ ] Step 1: Identify duplicated logic\n- [ ] Step 2: Import base components\n- [ ] Step 3: Wrap with Base Root\n- [ ] Step 4: Apply state-based styling and behavior\n- [ ] Step 5: Wrap sub-components with styling\n- [ ] Step 6: Final verification\n```\n\n### Step 1: Identify Duplicated Logic\n\nLook for patterns that indicate logic should come from base:\n\n- SDK hooks (`useTamboThread`, `useTamboThreadInput`, etc.)\n- Context creation (`React.createContext`)\n- State management that mirrors base component state\n- Event handlers (drag, submit, etc.) that base components handle\n\n### Step 2: Import Base Components\n\n```tsx\nimport { MessageInput as MessageInputBase } from \"@tambo-ai/react-ui-base/message-input\";\n```\n\n### Step 3: Wrap with Base Root\n\nReplace custom context/state management with the base Root:\n\n```tsx\n// Before\nconst MessageInput = ({ children, variant }) => {\n  return (\n    <MessageInputInternal variant={variant}>{children}</MessageInputInternal>\n  );\n};\n\n// After\nconst MessageInput = ({ children, variant, className }) => {\n  return (\n    <MessageInputBase.Root className={cn(variants({ variant }), className)}>\n      {children}\n    </MessageInputBase.Root>\n  );\n};\n```\n\n### Step 4: Apply State-Based Styling and Behavior\n\nState access follows a hierarchy — use the simplest option that works:\n\n1. **Data attributes** (preferred for styling) — base components expose `data-*` attributes\n2. **Render props** (for behavior changes) — use when rendering different components\n3. **Context hooks** (for sub-components) — OK for styled sub-components needing deep context access\n\n```tsx\n// BEST - data-* classes for styling, render props only for behavior\n// Note: use `data-[dragging]:*` syntax (v3-compatible), not `data-dragging:*` (v4 only)\nconst StyledContent = ({ children }) => (\n  <BaseComponent.Content\n    className={cn(\n      \"group rounded-xl border\",\n      \"data-[dragging]:border-dashed data-[dragging]:border-emerald-400\",\n    )}\n  >\n    {({ elicitation, resolveElicitation }) => (\n      <>\n        {/* Drop overlay uses group-data-* for styling */}\n        <div className=\"hidden group-data-[dragging]:flex absolute inset-0 bg-emerald-50/90\">\n          <p>Drop files here</p>\n        </div>\n\n        {elicitation ? (\n          <ElicitationUI\n            request={elicitation}\n            onResponse={resolveElicitation}\n          />\n        ) : (\n          children\n        )}\n      </>\n    )}\n  </BaseComponent.Content>\n);\n\n// OK - styled sub-components can use context hook for deep access\nconst StyledTextarea = ({ placeholder }) => {\n  const { value, setValue, handleSubmit, editorRef } = useMessageInputContext();\n  return (\n    <CustomEditor\n      ref={editorRef}\n      value={value}\n      onChange={setValue}\n      onSubmit={handleSubmit}\n      placeholder={placeholder}\n    />\n  );\n};\n```\n\n**When to use context hooks vs render props:**\n\n- Render props: when the parent wrapper needs state for behavior changes\n- Context hooks: when a styled sub-component needs values not exposed via render props\n\n### Step 5: Wrap Sub-Components\n\n```tsx\n// Submit button\nconst SubmitButton = ({ className, children }) => (\n  <BaseComponent.SubmitButton className={cn(\"w-10 h-10 rounded-lg\", className)}>\n    {({ showCancelButton }) =>\n      children ?? (showCancelButton ? <Square /> : <ArrowUp />)\n    }\n  </BaseComponent.SubmitButton>\n);\n\n// Error\nconst Error = ({ className }) => (\n  <BaseComponent.Error className={cn(\"text-sm text-destructive\", className)} />\n);\n\n// Staged images - base pre-computes props array, just iterate\nconst StagedImages = ({ className }) => (\n  <BaseComponent.StagedImages className={cn(\"flex gap-2\", className)}>\n    {({ images }) =>\n      images.map((imageProps) => (\n        <ImageBadge key={imageProps.image.id} {...imageProps} />\n      ))\n    }\n  </BaseComponent.StagedImages>\n);\n```\n\n### Step 6: Final Verification\n\n```\nFinal Checks:\n- [ ] No duplicate context creation\n- [ ] No duplicate SDK hooks in root wrappers\n- [ ] No duplicate state management or event handlers\n- [ ] Base namespace imported and `Base.Root` used as wrapper\n- [ ] `data-*` classes used for styling (with `group-data-*` for children)\n- [ ] Render props used only for rendering behavior changes\n- [ ] Base sub-components wrapped with styling\n- [ ] Icon factories passed from styled layer to base hooks\n- [ ] Visual sub-components and CSS variants stay in styled layer\n```\n\n## What Belongs in Styled Layer\n\n### Icon Factories\n\nWhen base hooks need icons, pass a factory function:\n\n```tsx\n// Base hook accepts optional icon factory\nexport function useCombinedResourceList(\n  providers: ResourceProvider[] | undefined,\n  search: string,\n  createMcpIcon?: (serverName: string) => React.ReactNode,\n) {\n  /* ... */\n}\n\n// Styled layer provides the factory\nconst resources = useCombinedResourceList(providers, search, (serverName) => (\n  <McpServerIcon name={serverName} className=\"w-4 h-4\" />\n));\n```\n\n### CSS Variants\n\n```tsx\nconst inputVariants = cva(\"w-full\", {\n  variants: {\n    variant: {\n      default: \"\",\n      solid: \"[&>div]:shadow-xl [&>div]:ring-1\",\n      bordered: \"[&>div]:border-2\",\n    },\n  },\n});\n```\n\n### Layout Logic, Visual Sub-Components, Custom Data Fetching\n\nThese all stay in the styled layer. Base handles behavior; styled handles presentation.\n\n## Type Handling\n\nHandle ref type differences between base and styled components:\n\n```tsx\n// Base context may have RefObject<T | null>\n// Styled component may need RefObject<T>\n<TextEditor ref={editorRef as React.RefObject<TamboEditor>} />\n```\n\n## Anti-Patterns\n\n- **Re-implementing base logic** - if base handles it, compose it\n- **Using render props for styling** - prefer `data-*` classes; render props are for behavior changes\n- **Duplicating context in wrapper** - use base Root which provides context\n- **Hardcoding icons in base hooks** - use factory functions to keep styling in styled layer\n",".claude/skills/api-resource-lifecycle/SKILL.md":"---\nname: api-resource-lifecycle\ndescription: Guides CRUD operations for API resources with cascading dependencies, descriptive validation, and orphan prevention. Use when adding delete/remove operations, creating validation logic, building resources that depend on other resources, or when the user mentions \"cascade delete\", \"orphan records\", \"duplicate detection\", \"validation errors\", \"resource cleanup\", or \"rollback on failure\".\nmetadata:\n  internal: true\n---\n\n# API Resource Lifecycle\n\nPatterns for building reliable CRUD operations in Tambo Cloud.\n\n## Gotchas\n\n- The codebase uses `CONFLICT` for duplicate name errors in skills but `BAD_REQUEST` for the same pattern in MCP servers. Always use `CONFLICT` for duplicates.\n- PostgreSQL unique violation code is `23505`. Catch it and map to a domain-specific exception rather than letting the raw DB error propagate.\n- When replacing a provider key, all skills with `externalSkillMetadata` for that provider must have their metadata cleared, or they'll reference a stale key.\n- Skills are silently skipped (not errored) at runtime when the provider doesn't support them. This is intentional -- don't add validation that blocks skill creation for unsupported providers.\n- `Promise.allSettled` (not `Promise.all`) for batch external API calls -- partial failures need cleanup, not an all-or-nothing abort.\n\n## Cascading Deletes\n\nDefault to `onDelete: \"cascade\"` in the schema. Only use manual transaction cascades when deletion requires external API calls, metadata cleanup, or cross-reference logic.\n\n```typescript\n// packages/db/src/schema.ts\nexport const skills = pgTable(\"skills\", {\n  id: text(\"id\").primaryKey(),\n  projectId: text(\"project_id\")\n    .notNull()\n    .references(() => projects.id, { onDelete: \"cascade\" }),\n  // ...\n});\n```\n\n### Manual cascades in transactions\n\nWhen deletion requires cleanup beyond FK cascades (external APIs, metadata, cross-references), wrap in a transaction:\n\n```typescript\n// packages/db/src/operations/project.ts\nexport async function deleteProject(db: HydraDb, id: string): Promise<boolean> {\n  return await db.transaction(async (tx) => {\n    await tx\n      .delete(schema.providerKeys)\n      .where(eq(schema.providerKeys.projectId, id));\n    await tx.delete(schema.apiKeys).where(eq(schema.apiKeys.projectId, id));\n    await tx\n      .delete(schema.projectMembers)\n      .where(eq(schema.projectMembers.projectId, id));\n    const deleted = await tx\n      .delete(schema.projects)\n      .where(eq(schema.projects.id, id))\n      .returning();\n    return deleted.length > 0;\n  });\n}\n```\n\n**Reference:** `packages/db/src/operations/project.ts` lines 255-278\n\n### Metadata cleanup on replacement\n\nWhen a resource is replaced (not deleted), clear dependent metadata so dependents re-sync under the new resource:\n\n```typescript\n// apps/web/server/api/routers/project.ts - addProviderKey\n// When replacing a provider key, clear skill metadata for that provider\nconst skills = await operations.listSkillsForProject(ctx.db, projectId);\nawait Promise.all(\n  skills\n    .filter((s) => s.externalSkillMetadata?.[providerName])\n    .map(async (s) => {\n      const { [providerName]: _, ...remaining } = s.externalSkillMetadata ?? {};\n      return operations.updateSkill(ctx.db, {\n        projectId,\n        skillId: s.id,\n        externalSkillMetadata: remaining,\n      });\n    }),\n);\n```\n\n**Reference:** `apps/web/server/api/routers/project.ts` lines 863-880\n\n### Rules\n\n- If a child record has no meaning without its parent, use `onDelete: \"cascade\"` in the schema\n- If deletion requires multi-step cleanup or external API calls, wrap in a transaction\n- When replacing a resource, clear dependent metadata so dependents re-sync\n- Always delete children before the parent in manual cascades\n- Check for affected dependents and document the cascade chain in code comments\n\n## Validation Errors\n\nEvery error must say what went wrong and what to do instead. Include the specific value that failed and an example of what's valid.\n\n```typescript\n// Zod: include format example\nname: z.string().min(1, \"Name is required\").max(64)\n  .regex(SKILL_NAME_PATTERN, \"Name must be kebab-case (e.g. scheduling-assistant)\"),\n\n// tRPC: include the conflicting value\nthrow new TRPCError({\n  code: \"CONFLICT\",\n  message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n});\n```\n\n### Error code mapping\n\n| Situation               | tRPC Code               | When to use                           |\n| ----------------------- | ----------------------- | ------------------------------------- |\n| Resource not found      | `NOT_FOUND`             | ID lookup returned null               |\n| Input validation failed | `BAD_REQUEST`           | Zod schema or business rule violation |\n| Duplicate resource      | `CONFLICT`              | Name/key already exists               |\n| Unexpected failure      | `INTERNAL_SERVER_ERROR` | Catch-all for unhandled errors        |\n\n## Duplicate Detection\n\nDefault to database unique constraints with custom exception mapping. Only use pre-creation queries when no DB constraint exists.\n\n```typescript\n// packages/db/src/operations/skills.ts\nconst PG_UNIQUE_VIOLATION = \"23505\";\nconst SKILLS_NAME_UNIQUE_CONSTRAINT = \"skills_project_id_name_idx\";\n\nexport class SkillNameConflictError extends Error {\n  constructor(name: string) {\n    super(`A skill named \"${name}\" already exists in this project`);\n    this.name = \"SkillNameConflictError\";\n  }\n}\n\nexport async function createSkill(\n  db: HydraDb,\n  data: NewSkill,\n): Promise<DBSkill> {\n  try {\n    const [skill] = await db.insert(schema.skills).values(data).returning();\n    return skill;\n  } catch (error) {\n    if (isSkillNameConflict(error)) {\n      throw new SkillNameConflictError(data.name);\n    }\n    throw error;\n  }\n}\n```\n\n### Pre-creation queries (fallback)\n\nWhen no unique DB constraint exists, query before inserting:\n\n```typescript\nconst existingKeys = await getExistingServerKeys(ctx.db, projectId);\nif (existingKeys.includes(serverKey)) {\n  throw new TRPCError({\n    code: \"CONFLICT\",\n    message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n  });\n}\n```\n\n**Reference:** `apps/web/server/api/routers/tools.ts` lines 119-126\n\n## Orphan Prevention\n\nWhen creating a resource that syncs to an external API, roll back on failure:\n\n```typescript\n// apps/web/server/api/routers/skills.ts\n// Create in DB first, then sync to provider\nconst skill = await operations.createSkill(ctx.db, { ... });\n\n// If provider sync fails, delete the DB record\ntry {\n  await createSkillOnProviderAndPersist(ctx.db, input.projectId, skill);\n} catch (error) {\n  await operations.deleteSkill(ctx.db, input.projectId, skill.id);\n  throw error;\n}\n```\n\n**Rules:**\n\n- Create the DB record first (gives you an ID for the external API call)\n- If the external sync fails, delete the DB record to avoid orphans\n- The user sees an error and can retry, rather than seeing a broken record\n- For batch operations, use `Promise.allSettled` and clean up partial failures\n\n**Reference:** `apps/web/server/api/routers/skills.ts` lines 195-204\n\n## Checklist\n\nWhen building a new CRUD operation:\n\n```\nResource Lifecycle Checklist:\n- [ ] Delete cascades documented (which dependents are affected?)\n- [ ] Database-level cascades set up for simple parent-child FK relationships\n- [ ] Manual cascade logic wrapped in a transaction for complex cleanup\n- [ ] All Zod validation messages are descriptive with examples\n- [ ] TRPCError messages include the specific value that caused the error\n- [ ] Duplicate detection before creation (custom exception or pre-query)\n- [ ] Error codes are correct (CONFLICT for duplicates, NOT_FOUND for missing)\n- [ ] External API sync failures roll back the DB record\n- [ ] Resource replacement clears dependent metadata\n```\n",".claude/skills/compound-components/SKILL.md":"---\nname: building-compound-components\ndescription: Creates unstyled compound components that separate business logic from styles. Use when building headless UI primitives, creating component libraries, implementing Radix-style namespaced components, or when the user mentions \"compound components\", \"headless\", \"unstyled\", \"primitives\", or \"render props\".\nmetadata:\n  internal: true\n---\n\n# Building Compound Components\n\nCreate unstyled, composable React components following the Radix UI / Base UI pattern. Components expose behavior via context while consumers control rendering.\n\n## Project Rules\n\nThese rules are specific to this codebase and override general patterns.\n\n### Hooks Are Internal\n\nHooks are implementation details, not public API. **Never export hooks from the index.**\n\n```tsx\n// index.tsx - CORRECT\nexport const Component = {\n  Root: ComponentRoot,\n  Content: ComponentContent,\n};\nexport type { ComponentRootProps, ComponentContentRenderProps };\n\n// index.tsx - WRONG\nexport { useComponentContext }; // Don't export hooks\n```\n\nConsumers access state via **render props**, not hooks. When styled wrappers in the **same package** need hook access, import directly from the source file:\n\n```tsx\nimport { useComponentContext } from \"../base/component/component-context\";\n```\n\n### No Custom Data Fetching in Primitives\n\nBase components can use `@tambo-ai/react` SDK hooks (components require Tambo provider anyway). **Custom data fetching logic** (combining sources, external providers) belongs in the styled layer.\n\n```tsx\n// OK - SDK hooks in primitive\nconst Root = ({ children }) => {\n  const { value, setValue, submit } = useTamboThreadInput();\n  const { isIdle, cancel } = useTamboThread();\n  return <Context.Provider value={{ value, setValue, isIdle }}>{children}</Context.Provider>;\n};\n\n// WRONG - custom data fetching in primitive\nconst Textarea = ({ resourceProvider }) => {\n  const { data: mcpResources } = useTamboMcpResourceList(search);\n  const externalResources = useFetchExternal(resourceProvider);\n  const combined = [...mcpResources, ...externalResources];\n  return <div>{combined.map(...)}</div>;\n};\n```\n\n### Pre-computed Props Arrays for Collections\n\nWhen exposing collections via render props, **pre-compute all props in a memoized array** rather than providing a getter function.\n\n```tsx\n// AVOID - getter function pattern\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n  const getItemProps = (index: number) => ({\n    /* new object every call */\n  });\n  return children({ items: rawItems, getItemProps });\n};\n\n// PREFERRED - pre-computed array\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n\n  const items = React.useMemo<ItemRenderProps[]>(\n    () =>\n      rawItems.map((item, index) => ({\n        item,\n        index,\n        isSelected: selectedId === item.id,\n        onSelect: () => setSelectedId(item.id),\n        onRemove: () => removeItem(item.id),\n      })),\n    [rawItems, selectedId, removeItem],\n  );\n\n  return children({ items });\n};\n```\n\n## Workflow\n\nCopy this checklist and track progress:\n\n```\nCompound Component Progress:\n- [ ] Step 1: Create context file\n- [ ] Step 2: Create Root component\n- [ ] Step 3: Create consumer components\n- [ ] Step 4: Create namespace export (index.tsx)\n- [ ] Step 5: Verify all guidelines met\n```\n\n### Step 1: Create context file\n\n```\nmy-component/\n├── index.tsx\n├── component-context.tsx\n├── component-root.tsx\n├── component-item.tsx\n└── component-content.tsx\n```\n\nCreate a context with a null default and a hook that throws on missing provider:\n\n```tsx\n// component-context.tsx\nconst ComponentContext = React.createContext<ComponentContextValue | null>(\n  null,\n);\n\nexport function useComponentContext() {\n  const context = React.useContext(ComponentContext);\n  if (!context) {\n    throw new Error(\"Component parts must be used within Component.Root\");\n  }\n  return context;\n}\n\nexport { ComponentContext };\n```\n\n### Step 2: Create Root component\n\nRoot manages state and provides context. Use `forwardRef`, support `asChild` via Radix `Slot`, and expose state via data attributes:\n\n```tsx\n// component-root.tsx\nexport const ComponentRoot = React.forwardRef<\n  HTMLDivElement,\n  ComponentRootProps\n>(({ asChild, defaultOpen = false, children, ...props }, ref) => {\n  const [isOpen, setIsOpen] = React.useState(defaultOpen);\n  const Comp = asChild ? Slot : \"div\";\n\n  return (\n    <ComponentContext.Provider\n      value={{ isOpen, toggle: () => setIsOpen(!isOpen) }}\n    >\n      <Comp ref={ref} data-state={isOpen ? \"open\" : \"closed\"} {...props}>\n        {children}\n      </Comp>\n    </ComponentContext.Provider>\n  );\n});\nComponentRoot.displayName = \"Component.Root\";\n```\n\n### Step 3: Create consumer components\n\nChoose the composition pattern based on need:\n\n**Direct children** (simplest, for static content):\n\n```tsx\nconst Content = ({ children, className, ...props }) => {\n  const { data } = useComponentContext();\n  return (\n    <div className={className} {...props}>\n      {children}\n    </div>\n  );\n};\n```\n\n**Render prop** (when consumer needs internal state):\n\n```tsx\nconst Content = ({ children, ...props }) => {\n  const { data, isLoading } = useComponentContext();\n  const content =\n    typeof children === \"function\" ? children({ data, isLoading }) : children;\n  return <div {...props}>{content}</div>;\n};\n```\n\n**Sub-context** (for lists where each item needs own context):\n\n```tsx\nconst Steps = ({ children }) => {\n  const { reasoning } = useMessageContext();\n  return (\n    <StepsContext.Provider value={{ steps: reasoning }}>\n      {children}\n    </StepsContext.Provider>\n  );\n};\n\nconst Step = ({ children, index }) => {\n  const { steps } = useStepsContext();\n  return (\n    <StepContext.Provider value={{ step: steps[index], index }}>\n      {children}\n    </StepContext.Provider>\n  );\n};\n```\n\n### Step 4: Create namespace export\n\n```tsx\n// index.tsx\nexport const Component = {\n  Root: ComponentRoot,\n  Trigger: ComponentTrigger,\n  Content: ComponentContent,\n};\n\n// Re-export types only - never hooks\nexport type { ComponentRootProps } from \"./component-root\";\nexport type { ComponentContentProps } from \"./component-content\";\n```\n\n### Step 5: Verify guidelines\n\n- **No styles in primitives** - consumers control all styling via className/props\n- **Data attributes for CSS** - expose state like `data-state=\"open\"`, `data-disabled`, `data-loading`\n- **Support asChild** - let consumers swap the underlying element via Radix `Slot`\n- **Forward refs** - always use `forwardRef`\n- **Display names** - set for DevTools (`Component.Root`, `Component.Item`)\n- **Throw on missing context** - fail fast with clear error messages\n- **Export types** - consumers need `ComponentProps`, `RenderProps` interfaces\n- **Hooks stay internal** - never export from index, expose state via render props\n- **SDK hooks OK, custom fetching not** - `@tambo-ai/react` hooks are fine, combining logic goes in styled layer\n- **Pre-compute collection props** - use `useMemo` arrays, not getter functions\n\n## Pattern Selection\n\n| Scenario             | Pattern         | Why                             |\n| -------------------- | --------------- | ------------------------------- |\n| Static content       | Direct children | Simplest, most flexible         |\n| Need internal state  | Render prop     | Explicit state access           |\n| List/iteration       | Sub-context     | Each item gets own context      |\n| Element polymorphism | asChild         | Change underlying element       |\n| CSS-only styling     | Data attributes | No JS needed for style variants |\n\n## Anti-Patterns\n\n- **Hardcoded styles** - primitives should be unstyled\n- **Prop drilling** - use context instead\n- **Missing error boundaries** - throw when context is missing\n- **Inline functions in render prop types** - define proper interfaces\n- **Default exports** - use named exports in namespace object\n- **Exporting hooks** - hooks are internal; expose state via render props\n- **Custom data fetching in primitives** - SDK hooks are fine, but combining/external fetching belongs in styled layer\n- **Re-implementing base logic** - styled wrappers should compose, not duplicate\n- **Getter functions for collections** - pre-compute props arrays in useMemo instead\n",".claude/skills/validating-accessibility/SKILL.md":"---\nname: validating-accessibility\ndescription: >-\n  Use this skill when creating, modifying, or reviewing any .tsx component in apps/web, even if\n  the user doesn't mention \"accessibility.\" Covers semantic HTML, aria labels, navigation landmarks,\n  forms, dialogs, and keyboard navigation. Trigger on: adding buttons, links, toggles, icons, or\n  any interactive element; building or editing forms; adding dialogs or modals; reviewing UI code.\n  Includes inline verification patterns for scanning violations. Not for styling or layout changes\n  that don't involve interactive elements.\nmetadata:\n  internal: true\n---\n\n# Accessibility Checklist\n\nEvery UI component in `apps/web` must meet these standards. No partial compliance.\n\n## Gotchas\n\n- **`role=\"button\"` divs may exist in the codebase** -- fix them when touching affected files. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n- **Nested interactive elements** -- when replacing a `<div role=\"button\">` that contains a child `<button>` (e.g., a copy button inside a collapsible toggle), do not just swap the outer div to `<button>`. That creates invalid nested buttons. Instead, restructure into sibling elements: a toggle `<button>` and a separate action `<button>` side by side in a flex container.\n- **Standalone inputs outside react-hook-form need manual ID pairing** -- use `useId()` with `htmlFor`/`id`. The shadcn `<FormField>` handles this automatically, but raw `<Input>` does not.\n- **AlertDialog vs Dialog** -- use `AlertDialog` for destructive confirmations (requires `AlertDialogTitle` + `AlertDialogDescription`). Use `Dialog` for content/forms. Never build custom modal overlays.\n- **Icon-only buttons without `aria-label`** are common in new code. Every icon-only button needs one, and it must include context: `Delete API key ${keyName}`, not just \"Delete\".\n\n## Semantic HTML\n\nUse native elements. Never recreate `<button>` behavior with `<div role=\"button\">` + keyboard handlers.\n\n| Interaction      | Element                                                |\n| ---------------- | ------------------------------------------------------ |\n| Clickable action | `<button>` or `<Button>` from `@/components/ui/button` |\n| Navigation link  | `<Link>` (Next.js) or `<a>`                            |\n| Navigation group | `<nav>` with descriptive `aria-label`                  |\n| Item list        | `<ul>`/`<ol>` + `<li>`                                 |\n| Section heading  | `<h1>`-`<h6>` in order, never skip levels              |\n\n## Aria Labels\n\nEvery interactive element without visible text needs `aria-label` with both action AND target:\n\n```tsx\n<Button size=\"icon\" aria-label={`Delete API key ${keyName}`}>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n\n<Switch aria-label={`${enabled ? \"Disable\" : \"Enable\"} skill ${skillName}`} />\n```\n\nPrefer state-aware labels (\"Copied!\" vs \"Copy\"). Buttons with visible text skip `aria-label`.\n\n**Reference implementations:** `copy-button.tsx` (state-aware), `context-attachment-badge.tsx` (contextual remove), `thread-table-header.tsx` (sort state) -- all in `apps/web/components/`.\n\n## Navigation Landmarks\n\nWrap navigation groups in `<nav>` with a unique `aria-label` per region on the page.\n\n## Forms\n\nUse shadcn Form components from `@/components/ui/form` (`FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormMessage`). They handle ID generation, label association, `aria-describedby`, and `aria-invalid` automatically.\n\nFor standalone inputs outside react-hook-form, pair `useId()` with `htmlFor`/`id`. Never use placeholder as label substitute.\n\n## Keyboard Navigation\n\n- Only `tabIndex={0}` or `tabIndex={-1}` (never positive values)\n- Never remove focus outlines\n- Prefer `<button>` over manual Enter/Space handlers\n\n## Verification\n\nScan `apps/web/components` for common violations. For each check, grep for the pattern and fix any matches found.\n\n### Check 1: `role=\"button\"` on non-button elements\n\nSearch for `role=\"button\"` in `.tsx` files. Flag `<div` or `<span` elements with this attribute; they should be `<button>` or `<Button>` instead. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n\n**Pattern:** `role=\"button\"`\n\n### Check 2: `<div onClick>` patterns\n\nSearch for `<div` elements with `onClick` handlers. These should use `<button>` instead for proper keyboard support.\n\n**Pattern:** `<div[^>]*onClick`\n\n### Check 3: Positive tabIndex values\n\nSearch for `tabIndex` with values greater than 0. Only `tabIndex={0}` and `tabIndex={-1}` are allowed.\n\n**Pattern:** `tabIndex={[1-9]`\n\n### Check 4: Icon buttons missing aria-label\n\nSearch for `size=\"icon\"` in `.tsx` files. For each match, check surrounding lines (5-10 above and below) for `aria-label` on the same `<Button>` element or an `sr-only` span. Flag buttons that have neither.\n\n**Pattern:** `size=\"icon\"` without nearby `aria-label`\n\n### Manual checks\n\nThese cannot be detected by pattern matching:\n\n- [ ] Form inputs have associated `<label>` elements\n- [ ] Navigation groups use `<nav>` with unique `aria-label`\n- [ ] Dialogs use Radix-based components (AlertDialog or Dialog)\n- [ ] Focus outlines intact\n",".claude-plugin/marketplace.json":"{\n  \"name\": \"tambo-marketplace\",\n  \"owner\": {\n    \"name\": \"Tambo AI\",\n    \"email\": \"support@tambo.co\"\n  },\n  \"metadata\": {\n    \"description\": \"Official Tambo plugins for Claude Code\",\n    \"homepage\": \"https://tambo.co\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"tambo\",\n      \"source\": \"./plugins/tambo\",\n      \"description\": \"Build agents that speak your UI\",\n      \"version\": \"1.0.0\",\n      \"author\": {\n        \"name\": \"Tambo AI\",\n        \"email\": \"support@tambo.co\"\n      },\n      \"category\": \"frameworks\",\n      \"keywords\": [\"ai\", \"react\", \"generative-ui\", \"components\", \"streaming\"]\n    }\n  ]\n}\n",".claude/skills/building-settings-ui/SKILL.md":"---\nname: building-settings-ui\ndescription: >-\n  Use this skill when adding or modifying settings UI in Tambo Cloud. Covers where a new settings\n  section belongs (Agent tab vs Settings tab), and the component patterns used across both pages\n  (card layout, toasts, confirmation dialogs, destructive styling, save behavior conventions).\n  Triggers on \"add a new settings section\", \"where should X go?\", \"settings UI\", \"settings page\",\n  \"agent page\", or any work touching apps/web/components/dashboard-components/project-details/,\n  project-settings.tsx, or agent-settings.tsx.\n  Not for full-stack feature building (DB, tRPC, tests); those patterns will get their own skills.\nmetadata:\n  internal: true\n---\n\n# Building Settings UI\n\nGuide for placing and styling settings sections in the Tambo Cloud dashboard. Covers two concerns: where a feature belongs (which tab/page), and how to build the UI component to match existing patterns.\n\n## Architecture\n\nSettings are split across two top-level tabs in the project layout:\n\n- **Agent tab** (`/[projectId]/agent`) - How the AI agent behaves\n- **Settings tab** (`/[projectId]/settings`) - Project infrastructure and access\n\nEach tab renders a flat vertical stack of Card components. There is no sidebar navigation; each page is short enough to scroll naturally.\n\n### Tab layout\n\n```\nOverview | Observability | Agent | Settings\n```\n\n- Layout file: `apps/web/app/(authed)/(dashboard)/[projectId]/layout.tsx`\n- Agent page: `apps/web/app/(authed)/(dashboard)/[projectId]/agent/page.tsx`\n- Settings page: `apps/web/app/(authed)/(dashboard)/[projectId]/settings/page.tsx`\n\n## Gotchas\n\n1. **Do not add a new top-level tab** without explicit team alignment. Current tabs (Overview, Observability, Agent, Settings) have been stable.\n2. **`EditWithTamboButton` goes inside `CardTitle`**, not as a sibling of `CardHeader`. It must have a `description` prop explaining what the section configures.\n3. **Invalidate the query before toasting** in `onSuccess`. Reversing the order can show a success toast while the UI still displays old data.\n4. **Use `DeleteConfirmationDialog`**, never inline `AlertDialog` for destructive confirmations.\n5. **Use `text-destructive` semantic color**, never `text-red-500`. Cancel/discard buttons are NOT destructive.\n\n---\n\n## Feature Placement\n\n### Agent Tab Sections\n\n| #   | Section             | What it configures                                 | Component                        |\n| --- | ------------------- | -------------------------------------------------- | -------------------------------- |\n| 1   | Model               | Provider + model selection, API key, custom params | `provider-key-section.tsx`       |\n| 2   | Custom Instructions | System prompt, prompt override toggle              | `custom-instructions-editor.tsx` |\n| 3   | Skills              | Skill definitions and imports                      | `skills-section.tsx`             |\n| 4   | Tool Call Limit     | Max tool calls per response                        | `tool-call-limit-editor.tsx`     |\n| 5   | MCP                 | MCP server URLs + headers                          | `available-mcp-servers.tsx`      |\n\n**Container:** `apps/web/components/dashboard-components/agent-settings.tsx`\n\n### Settings Tab Sections\n\n| #   | Section        | What it configures             | Component                  |\n| --- | -------------- | ------------------------------ | -------------------------- |\n| 1   | Name           | Project display name           | `project-name-section.tsx` |\n| 2   | API Keys       | API key list + create          | `api-key-list.tsx`         |\n| 3   | Authentication | OAuth mode, token requirements | `oauth-settings.tsx`       |\n| 4   | Danger Zone    | Project deletion               | `danger-zone-section.tsx`  |\n\n**Container:** `apps/web/components/dashboard-components/project-settings.tsx`\n\nAll section components live in `apps/web/components/dashboard-components/project-details/`.\n\n### Placement Decision Tree\n\n1. **Configures AI agent behavior?** (model selection, prompts, tools, memory, context) -> **Agent tab**\n2. **Configures project infrastructure?** (API keys, naming, deletion, billing, webhooks) -> **Settings tab**\n3. **Configures who can access?** (auth, tokens, team members, permissions) -> **Settings tab**\n4. **Monitoring or debugging view?** -> **Observability tab**\n5. **High-level summary or status?** -> **Overview tab**\n6. **None of the above?** -> Ask the user.\n\n### Conditional and Dependent Settings\n\nSome settings only apply when another setting is in a specific state. Follow these patterns:\n\n**Show but warn (soft dependency).** The section renders normally but displays an `Alert` when the dependency isn't met. The user can still see and configure the setting. Use this when the feature exists but won't work at runtime.\n\nExample: Skills section shows a provider compatibility notice when the selected provider doesn't support skills:\n\n```tsx\n// skills-section.tsx\nconst isProviderSupported = SKILLS_SUPPORTED_PROVIDERS.has(\n  defaultLlmProviderName,\n);\n// Renders full skills UI + warning Alert if !isProviderSupported\n```\n\n**Conditionally pass props (data dependency).** The parent reads one setting and passes it as a prop so the child can adapt its behavior. Use this when the child's content or options change based on the parent's state.\n\nExample: MCP servers section receives `providerType` to toggle agent-mode-specific UI:\n\n```tsx\n// agent-settings.tsx\n<AvailableMcpServers providerType={projectData?.providerType} />;\n// available-mcp-servers.tsx\nconst isAgentMode = providerType === AiProviderType.AGENT;\n```\n\nExample: Custom LLM parameters change available suggestions based on provider and model:\n\n```tsx\n// provider-key-section.tsx passes selectedProvider to the parameter editor\n<CustomLlmParametersEditor selectedProvider={selectedProvider} />\n```\n\n**Rules for new dependent settings:**\n\n1. Never hide a section entirely based on another setting's state. Always render the card; use an Alert or disabled state to communicate the dependency.\n2. The warning message must name the dependency and tell the user what to change (e.g., \"Switch to a supported provider to enable skills\").\n3. Keep dependency checks in the section component, not the container. The container (`agent-settings.tsx`, `project-settings.tsx`) should pass data, not make visibility decisions.\n4. If a setting depends on state from a different tab, pass it through the shared project query (`api.project.getProject`) rather than cross-tab state.\n\n### Adding a New Section\n\n1. **Create the component** in `project-details/` following the Card layout pattern below.\n2. **Import and render** in the correct container (`agent-settings.tsx` or `project-settings.tsx`).\n3. **Update the skeleton** in `settings-skeletons.tsx` (either `AgentPageSkeleton` or `SettingsPageSkeleton`).\n\n---\n\n## Component Patterns\n\n### Card Layout\n\nEvery settings section uses `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardContent` from `@/components/ui/card`.\n\n```tsx\n<Card>\n  <CardHeader>\n    <CardTitle className=\"text-lg font-semibold\">\n      Section Name\n      <EditWithTamboButton description=\"Configure section settings...\" />\n    </CardTitle>\n    <CardDescription className=\"text-sm font-sans text-foreground\">\n      Description of what this section does.\n    </CardDescription>\n  </CardHeader>\n  <CardContent className=\"space-y-4\">{/* Content */}</CardContent>\n</Card>\n```\n\n### Toast Notifications\n\nEvery mutation shows a toast on both success and error. Import `useToast` from `@/hooks/use-toast`.\n\n```tsx\nconst mutation = api.someRoute.someMutation.useMutation({\n  onSuccess: async () => {\n    await utils.someRoute.someQuery.invalidate();\n    toast({ title: \"Success\", description: \"Setting updated successfully\" });\n  },\n  onError: () => {\n    toast({\n      title: \"Error\",\n      description: \"Failed to update setting\",\n      variant: \"destructive\",\n    });\n  },\n});\n```\n\nNever skip the error toast.\n\n### Confirmation Dialogs\n\nAll destructive actions use `DeleteConfirmationDialog` from `@/components/dashboard-components/delete-confirmation-dialog`:\n\n```tsx\nconst [alertState, setAlertState] = useState<{\n  show: boolean;\n  title: string;\n  description: string;\n  data?: { id: string };\n}>({ show: false, title: \"\", description: \"\" });\n\n<DeleteConfirmationDialog\n  mode=\"single\"\n  alertState={alertState}\n  setAlertState={setAlertState}\n  onConfirm={handleConfirmDelete}\n/>;\n```\n\nTitle includes the item name (`Delete \"${name}\"?`). Description warns the action cannot be undone.\n\n### Destructive Action Styling\n\n```tsx\n<Button\n  variant=\"ghost\"\n  size=\"icon\"\n  className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n```\n\nUse `Trash2` from `lucide-react`. Use `hover:bg-destructive/10` for ghost variant hover.\n\n### Save Behavior\n\n**Toggles: Immediate save.** `onCheckedChange` fires the mutation directly. Include `aria-label` with state context.\n\n**Form fields: Edit/Save/Cancel.** Track `isEditing`, `savedValue`, and `displayValue` state. Cancel reverts to `savedValue`. Save button disabled during mutation, shows \"Saving...\". `autoFocus` on first input when entering edit mode.\n\n**Reference implementations:** `custom-instructions-editor.tsx` (edit/save/cancel), `tool-call-limit-editor.tsx` (simpler form), `project-name-section.tsx` (basic edit/save/cancel).\n\n### Danger Zone Pattern\n\nFor irreversible destructive actions, use the Danger Zone card pattern:\n\n```tsx\n<Card className=\"border-destructive/50\">\n  <CardHeader>\n    <CardTitle>Danger Zone</CardTitle>\n    <CardDescription>Warning about permanence.</CardDescription>\n  </CardHeader>\n  <CardContent>\n    <Button\n      variant=\"ghost\"\n      className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n      aria-label=\"Delete this project\"\n    >\n      Delete this project\n    </Button>\n  </CardContent>\n</Card>\n```\n\nThe `DeleteConfirmationDialog` should be owned by the parent component that handles the mutation and post-delete navigation.\n","plugins/tambo/skills/generative-ui/SKILL.md":"---\nname: generative-ui\ndescription: Creates a new Tambo generative UI app from scratch. Scaffolds with tambo create-app, wires TamboProvider, registers starter components. Triggers on \"new Tambo app\", \"create a generative UI app\", \"build an AI app from scratch\", \"start a new project with Tambo\". For existing apps, use building-with-tambo.\n---\n\n# Generative UI\n\nBuild generative UI apps with Tambo — create rich, interactive React components from natural language.\n\n## Reference Guides\n\nLoad these when you need deeper implementation details beyond the bootstrap flow:\n\n- [Components](references/components.md) - **Load when creating custom components.** Generative vs interactable, propsSchema, ComponentRenderer.\n- [Component Rendering](references/component-rendering.md) - Streaming props, loading states, persistent state. Load when customizing rendering.\n- [Threads and Input](references/threads.md) - **Load when building custom chat UI.** useTambo(), useTamboThreadInput(), userKey/userToken auth, suggestions, voice.\n- [Tools and Context](references/tools-and-context.md) - **Load when adding tools or MCP.** defineTool(), MCP servers, contextHelpers.\n- [CLI Reference](references/cli.md) - **Load for `tambo add` components.** Component library, non-interactive flags, exit codes.\n- [Skills](references/skills.md) - **Mention as a next step after setup.** Project-scoped agent skills via CLI and dashboard.\n\nThese shared references are duplicated from building-with-tambo so each skill works independently.\n\n## One-Prompt Flow\n\nThe goal is to get the user from zero to a running app in a single prompt. Ask all questions upfront using AskUserQuestion with multiple questions, then execute everything without stopping.\n\n### Step 1: Gather All Non-Sensitive Preferences (Single AskUserQuestion Call)\n\nUse AskUserQuestion with up to 3 questions in ONE call. Authentication is handled by the CLI in a later step.\n\n**Question 1: What do you want to build?**\n\nAsk the user what kind of app they're building. This drives which starter components to create. Examples: \"a dashboard\", \"a chatbot\", \"a data visualization tool\", \"a task manager\". If the user already said what they want in their initial message, skip this question.\n\n**Question 2: Framework**\n\nOptions:\n\n- Next.js (Recommended) - Full-stack React with App Router\n- Vite - Fast, lightweight React setup\n\n**Question 3: App name**\n\nLet the user pick a name for their project directory. Default suggestion: derive from what they want to build (e.g., \"my-dashboard\", \"my-chatbot\"). Use kebab-case (letters, numbers, hyphens only). If the user gives a non-slug name like \"Sales Dashboard\", propose `sales-dashboard` instead.\n\n**Skip questions when the user already told you the answer.** If they said \"build me a Next.js dashboard app called analytics\", you already know the framework, the app idea, and the name.\n\n### Step 2: Execute Everything (No Stopping)\n\nRun all of these sequentially without asking for confirmation between steps. If any command fails, stop the flow, surface the error, and ask the user how to proceed — do not continue to later steps.\n\nAll templates (`standard`, `vite`, `analytics`, `expo`) come with chat UI, TamboProvider wiring, component registry, and starter components already included. You do NOT need to add chat UI or wire up the app — just scaffold, configure the API key, add custom components, and start the server.\n\n#### 2a. Scaffold the project\n\nFor Next.js (recommended):\n\n```bash\nnpx tambo create-app <app-name> --template=standard --skip-tambo-init\ncd <app-name>\n```\n\nFor Vite:\n\n```bash\nnpx tambo create-app <app-name> --template=vite --skip-tambo-init\ncd <app-name>\n```\n\nUse `--skip-tambo-init` since `create-app` normally tries to run `tambo init` interactively, which won't work in non-interactive environments like coding agents. We handle authentication in the next step.\n\n#### 2b. Authenticate and initialize Tambo\n\n```bash\nnpx tambo init --project-name=<app-name>\n```\n\nThis opens the browser for authentication and polls until the user completes auth (up to 15 minutes). Use a long timeout (at least 15 minutes) when running this command. Once auth completes, the CLI creates the project and writes the API key to `.env.local` with the correct env var for the framework (`NEXT_PUBLIC_TAMBO_API_KEY`, `VITE_TAMBO_API_KEY`, etc.).\n\n**IMPORTANT:** Do NOT ask the user to paste an API key manually. Always use the CLI auth flow.\n\n#### 2c. Create custom starter components\n\nThe template includes basic components, but add 1-2 components tailored to what the user wants to build. Don't use generic examples:\n\n- **Dashboard app** → `StatsCard`, `DataTable`\n- **Chatbot** → `BotResponse` with markdown support\n- **Data visualization** → `Chart` with configurable data\n- **Task manager** → `TaskCard`, `TaskBoard`\n- **Generic / unclear** → `ContentCard`\n\nEach component needs:\n\n1. A Zod schema with `.describe()` on every field\n2. The React component itself\n3. Registration in the existing component registry (`lib/tambo.ts` — add to the existing `components` array, don't replace it)\n\n**Schema constraints — Tambo will reject invalid schemas at runtime:**\n\n- **No `z.record()`** — Record types (objects with dynamic keys) are not supported anywhere in the schema, including nested inside arrays or objects. Use `z.object()` with explicit named keys instead.\n- **No `z.map()` or `z.set()`** — Use arrays and objects instead.\n- For tabular data like rows, use `z.array(z.object({ col1: z.string(), col2: z.number() }))` with explicit column keys — NOT `z.array(z.record(z.string(), z.unknown()))`.\n\n**React best practices for generated components:**\n\n- Always add unique `key` props when rendering lists (`.map()`). Use a unique field from the data (like `id`) — not the array index.\n- Include an `id` field (e.g., `z.string().describe(\"Unique identifier\")`) in schemas for array items so there's always a stable key available.\n\nExample:\n\n```tsx\n// src/components/StatsCard.tsx\nimport { z } from \"zod/v4\";\n\nexport const StatsCardSchema = z.object({\n  title: z.string().describe(\"Metric name\"),\n  value: z.number().describe(\"Current value\"),\n  change: z.number().optional().describe(\"Percent change from previous period\"),\n  trend: z.enum([\"up\", \"down\", \"flat\"]).optional().describe(\"Trend direction\"),\n});\n\ntype StatsCardProps = z.infer<typeof StatsCardSchema>;\n\nexport function StatsCard({\n  title,\n  value,\n  change,\n  trend = \"flat\",\n}: StatsCardProps) {\n  // ... implementation with Tailwind styling\n}\n```\n\nThen add to the existing registry in `lib/tambo.ts`:\n\n```tsx\n// Add to the existing components array — don't replace what's already there\n// Next.js: import { StatsCard, StatsCardSchema } from \"@/components/StatsCard\";\n// Vite: import { StatsCard, StatsCardSchema } from \"../components/StatsCard\";\nimport { StatsCard, StatsCardSchema } from \"@/components/StatsCard\";\n\n// ... existing components ...\n{\n  name: \"StatsCard\",\n  component: StatsCard,\n  description: \"Displays a metric with value and trend. Use when user asks about stats, metrics, or KPIs.\",\n  propsSchema: StatsCardSchema,\n},\n```\n\n#### 2d. Start the dev server\n\nOnly start the dev server after all code changes (scaffolding, init, component creation, registry updates) are complete.\n\n```bash\nnpm run dev\n```\n\nRun this in the background so the user can see their app immediately.\n\n### Step 3: Summary\n\nAfter everything is running, give a brief summary:\n\n- What was set up\n- What components were created and what they do\n- The URL where the app is running (typically `http://localhost:3000` for Next.js, `http://localhost:5173` for Vite)\n- If auth was skipped: remind them once to run `npx tambo init` to authenticate\n- A suggestion for what to try first (e.g., \"Try asking it to show you a stats card for monthly revenue\")\n\n## Technology Stacks Reference\n\n### Recommended Stack (Default)\n\n```\nNext.js 14+ (App Router)\n├── TypeScript\n├── Tailwind CSS\n├── Zod (for schemas)\n└── @tambo-ai/react\n```\n\n```bash\nnpx tambo create-app my-app --template=standard\n```\n\n### Vite Stack\n\n```\nVite + React\n├── TypeScript\n├── Tailwind CSS\n├── Zod\n└── @tambo-ai/react\n```\n\n### Minimal Stack (No Tailwind)\n\n```\nVite + React\n├── TypeScript\n├── Plain CSS\n├── Zod\n└── @tambo-ai/react\n```\n\n## Component Registry Pattern\n\nEvery generative component must be registered:\n\n```tsx\nimport { TamboComponent } from \"@tambo-ai/react\";\nimport { ComponentName, ComponentNameSchema } from \"@/components/ComponentName\";\n\nexport const components: TamboComponent[] = [\n  {\n    name: \"ComponentName\",\n    component: ComponentName,\n    description: \"What it does. When to use it.\",\n    propsSchema: ComponentNameSchema,\n  },\n];\n```\n\nKey rules:\n\n- **propsSchema**: Zod object with `.describe()` on every field — this is how the AI knows what to pass\n- **description**: Tell the AI when to use this component — be specific about trigger phrases\n- **Streaming**: Props arrive incrementally, so handle undefined gracefully (optional fields or defaults)\n\n## Adding More Chat UI (Optional)\n\nTemplates already include chat UI. These are only needed if the user wants additional UI primitives beyond what the template provides:\n\n```bash\nnpx tambo add message-thread-full --yes    # Complete chat interface\nnpx tambo add control-bar --yes            # Controls and actions\nnpx tambo add thread-history --yes         # Conversation history sidebar\n```\n\n## Supported Technologies\n\n| Technology       | Support Level | Notes                             |\n| ---------------- | ------------- | --------------------------------- |\n| Next.js 14+      | Full          | Recommended, App Router preferred |\n| Vite             | Full          | Great for SPAs                    |\n| Create React App | Partial       | Works but CRA is deprecated       |\n| Remix            | Partial       | Works with client components      |\n| TypeScript       | Full          | Strongly recommended              |\n| JavaScript       | Full          | Works but less type safety        |\n| Tailwind CSS     | Full          | Default for CLI components        |\n| Plain CSS        | Full          | Need custom component styling     |\n| CSS Modules      | Full          | Supported                         |\n| Zod              | Required      | Used for all schemas              |\n\n## Verification\n\nHave the user verify the app works by:\n\n1. Opening the app URL in a browser\n2. Typing a prompt that should trigger one of the registered components (e.g., \"Show me a stats card for monthly revenue\")\n3. Verifying the component renders with AI-generated props\n\nIf something doesn't work:\n\n- Check the registry includes the component\n- Check the description matches the prompt\n- Check the dev server has no console errors\n\n## Reporting Bugs & Feedback\n\nIf you encounter any of these while helping a user, suggest filing a GitHub issue:\n\n- A bug in `@tambo-ai/react`, `@tambo-ai/client`, or the `tambo` CLI\n- Documentation that contradicts actual behavior\n- Missing or misleading instructions in this skill\n\n### Issue Template\n\nUse this template when drafting an issue for `tambo-ai/tambo`:\n\n````markdown\n**Title:** [Short description of the problem]\n\n**Expected behavior**\nWhat should happen.\n\n**Actual behavior**\nWhat happens instead, including any error messages or stack traces.\n\n**Repro steps**\n\n1. Run `npx tambo create-app ...` (or whatever command)\n2. Add this code:\n\n```tsx\n// minimal code that reproduces the issue\n```\n\n3. Observe the error\n\n**Environment**\n\n- `@tambo-ai/react` version:\n- `@tambo-ai/client` version:\n- Framework (Next.js / Vite / CRA) and version:\n- Node.js version:\n- OS:\n\n**Additional context**\nLink to relevant docs or skill file path if applicable.\n````\n\n**Security:** Redact API keys, tokens, and any customer data before including logs or code snippets in the issue.\n\n### Suggesting an Issue to the User\n\nWhen you hit a problem that looks like a Tambo bug, say something like:\n\n> This looks like a bug in `@tambo-ai/react`. Want me to open a GitHub issue on `tambo-ai/tambo` with the repro steps and environment details?\n\nAlways wait for the user to confirm before filing.\n",".github/AGENTS.md":"# AGENTS.md\n\nGuidance for agents working in `.github/` (GitHub Actions workflows and composite actions). This file is referenced from the root [`AGENTS.md`](../AGENTS.md).\n\n## GitHub Actions\n\nWhen creating or modifying GitHub Actions workflows:\n\n- **Pin actions to full commit SHA** with a version comment for security and reproducibility:\n\n  ```yaml\n  # Good - pinned to SHA with version comment\n  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2\n\n  # Bad - unpinned version tag\n  - uses: actions/checkout@v4\n  ```\n\n- **Look up the SHA** from the action's releases page (e.g., https://github.com/actions/checkout/releases)\n- **Include the version in a comment** so humans can understand what version is pinned\n- **Local actions** (`./.github/actions/*`) don't need pinning since they're in the repo\n","CLAUDE.md":"# CLAUDE.md\n\nGuidelines for Claude Code (claude.ai/code) when touching this repo.\n\n**Read @AGENTS.md first.** It owns architecture, naming, workflow rules, testing expectations, and anything code-related. Keep that file open—this doc just points you there.\n\n## Three Things to Remember\n\n1. Follow that doc for everything: repo layout, commands, coding standards, doc rules, Charlie workflow, MCP guidance, etc.\n2. Use the workspace scripts it lists (see below for key commands).\n3. Defer to it whenever instructions collide; if something's still unclear, ask the user.\n\n## Key Commands\n\n```bash\n# Development (two different apps)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261\nnpm run dev              # Start React SDK (showcase + docs)\n\n# Quality checks (run before commits)\nnpm run lint\nnpm run check-types\nnpm test\n\n# Database (requires -w flag)\nnpm run db:generate -w packages/db\nnpm run db:migrate -w packages/db\nnpm run db:studio -w packages/db\n\n# Docker (for PostgreSQL in local dev)\ndocker compose --env-file docker.env up postgres -d\n```\n\n## Documentation Structure\n\n- **CONTRIBUTING.md** - Dev setup and PR workflow for contributors\n- **SELF-HOSTING.md** - Self-hosting/deployment guide\n- **AGENTS.md** - Coding standards, architecture (this is the source of truth)\n","AGENTS.md":"# AGENTS.md\n\nDetailed guidance for Claude Code agents working with the Tambo AI monorepo.\n\nThis file provides comprehensive instructions for maintaining code quality, architectural consistency, and project-specific requirements across both the Tambo AI framework and the Tambo Cloud platform.\n\n## 1. Repository Structure\n\nThis is a Turborepo monorepo containing both the Tambo AI framework packages and the Tambo Cloud platform.\n\n### Framework Packages (Turborepo root)\n\n- **react-sdk/** - Main React SDK package (`@tambo-ai/react`)\n  - Core hooks, providers, and utilities for building AI-powered React apps\n  - Exports: hooks, providers, types for component registration and thread management\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`) for broad compatibility\n\n- **packages/client/** - Framework-agnostic client (`@tambo-ai/client`)\n  - Streaming, tool execution, thread management without React dependencies\n  - `TamboClient` class with `getState()`/`subscribe()` for framework integration\n  - `TamboStream` async iterable for streaming AI responses\n  - Used by `@tambo-ai/react` as its core engine; also usable standalone (Node.js, Vue, Svelte, etc.)\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`)\n\n- **cli/** - Command-line interface (`tambo`)\n  - Project scaffolding, component generation, and development utilities\n  - Component registry auto-syncs to `/showcase/src/components/tambo/` from `/cli/src/registry/`\n  - Built as ESM module with executable binary\n\n- **showcase/** - Demo application (`@tambo-ai/showcase`)\n  - Runs on port 8262\n  - Next.js app demonstrating all Tambo components and patterns\n  - Components auto-synced from CLI registry - edit CLI registry, not showcase components directly\n  - Serves as both documentation and testing ground\n\n- **docs/** - Documentation site (`@tambo-ai/docs`)\n  - Runs on port 8263\n  - Built with Fumadocs, includes comprehensive guides and API reference\n  - This package contains ui components that originated from the cli/ package.\n    Any changes to the components should be made in the cli/ package first, and\n    then duplicated into this package.\n  - MDX-based content with interactive examples\n  - Integrated search and component documentation\n\n- **create-tambo-app/** - App bootstrapper (`create-tambo-app`)\n  - Initializes new Tambo projects from templates\n  - Handles git setup, dependency installation, and configuration\n\n- **community/** - Community resources and event materials\n- **packages/** - Shared configuration packages (ESLint, TypeScript configs)\n\n### Tambo Cloud Platform\n\n- **apps/web** - Next.js app (UI) - runs on port 8260\n- **apps/api** - NestJS app (OpenAPI server) - runs on port 8261\n- **packages/db** - Drizzle ORM schema + migrations + DB helpers\n- **packages/core** - Shared pure utilities (no DB access)\n- **packages/backend** - LLM/agent-side helpers\n- **packages/eslint-config, packages/typescript-config** - Shared tooling configs\n\n### Prerequisites\n\n- Node.js >=22\n- npm >=11\n\nIt is OK to use `crypto.randomUUID()` without a fallback in runtime and test code (Node.js >=22 and modern browsers).\n\n**Recommended:** Install [mise](https://mise.jdx.dev) for automatic version management. See [mise getting started](https://mise.jdx.dev/getting-started.html) for installation instructions.\n\n### Tool Versions\n\nTool versions are managed via mise. Source of truth files:\n\n- **Most tools**: `mise.toml`\n- **Node.js**: `.node-version` (`.nvmrc` kept in sync for nvm compatibility)\n\nThese files are kept up to date by Renovate.\n\n```bash\nmise install              # Install/update tools to correct versions\nmise exec -- <command>    # Preferred for scripts/CI/non-interactive shells\neval \"$(mise activate)\"   # Interactive shells only\n```\n\n**Changing tool versions**: Open a PR updating the authoritative version file(s). For Node.js, always update both `.node-version` and `.nvmrc` together. Run `mise install`, then verify with `npm run lint && npm run check-types && npm test`.\n\n**Local overrides**: Use `.mise.local.toml` (gitignored) for local-only changes. Only for additive or patch-level changes—don't override Node.js or use incompatible versions.\n\n## 2. Core Development Principles\n\n### Philosophy\n\n- **Move fast while maintaining high standards** - prioritize clarity and maintainability over cleverness.\n- **Read the relevant code first**; follow existing patterns and naming.\n- **Keep solutions small and simple**; favor functions over classes; avoid unnecessary abstractions.\n- **Simplify Relentlessly**: Remove complexity aggressively - the simplest design that works is usually best.\n- **Prefer immutability**. Don't mutate inputs; return new values. Use const, toSorted, object/array spreads.\n- **Handle errors up-front** with guard clauses and early returns.\n\n### Separation of Concerns\n\n- **Keep business logic separate from UI components**.\n- Extract business logic, calculations, and data transformations into separate files (`utils/`, `services/`, `lib/`).\n- UI components should orchestrate, not implement complex logic.\n- Makes testing easier and code more reusable.\n\n### Fail-Fast, No Fallbacks\n\n- **No Silent Fallbacks**: Code must fail immediately when expected conditions aren't met. Silent fallback behavior masks bugs and creates unpredictable systems.\n- **Explicit Error Messages**: When something goes wrong, stop execution with clear error messages explaining what failed and what was expected.\n- **Example**: `throw new Error(\\`Required model ${modelName} not found\\`)` instead of falling back to first available model.\n- **Data mapping**: When converting enums or union types, handle all known values explicitly and throw for unknown values. Don't use catch-all defaults that mask data integrity issues. Log warnings if skipping invalid data intentionally.\n\n### Naming Conventions\n\n- **File/dir naming**: kebab-case.\n- **Classes**: PascalCase.\n- **Vars/functions/methods**: camelCase.\n- **ENV vars**: UPPER_SNAKE_CASE.\n- **Use English**; meaningful names with widely-recognized standard abbreviations only (API, URL, ctx, req, res, next).\n- **Booleans**: start with is/has/can/should.\n- **Functions**: use verbs; boolean-returning: isX/hasX/canX. If a function returns void, prefer executeX/saveX naming.\n- **React-specific naming** (follows devdocs/NAMING_CONVENTIONS.md):\n  - Components: TamboXxx\n  - Hooks: useTamboXxx\n  - Props interfaces: TamboXxxProps\n  - Event props start with onX; internal handlers use handleX\n\n### Code Organization (Functions & Classes)\n\n- Keep functions short and single-purpose; ideally <20 statements.\n- Keep files focused and reasonably sized; ideally <200-300 lines.\n- Avoid `let` - instead make a new function that returns the value.\n- Avoid deep nesting: prefer early exits and extracting helpers. Use map/filter for iteration.\n- Prefer immutable data; use readonly and as const where applicable.\n- Favor composition over inheritance. If classes are used, keep them small (<200 statements, <10 properties/methods) and validate invariants internally.\n\n### Avoiding Over-Abstraction\n\n- **DRY is good, but don't go overboard** - sometimes a little duplication is better than the wrong abstraction.\n- **Rule of Three**: Wait until you have 3 instances of similar code before extracting a shared utility.\n- Premature abstraction creates coupling and makes changes harder.\n- It's easier to extract commonality later than to undo a bad abstraction.\n\n### Exports\n\n- Prefer named exports; allow multiple exports when they belong together (e.g., component + related types).\n- Avoid default exports.\n- Don't create `index.ts` barrels for internal modules; import directly from source files. Exception: package entry points (e.g., `packages/core/src/index.ts`) are fine.\n- Don't re-export symbols for backwards compatibility. When moving a symbol, update all consumers to import from the new location.\n- **Never use dynamic `import()`** for regular imports, even for type imports. Use static imports at the top of the file. Dynamic imports are only appropriate for code splitting in specific scenarios (e.g., lazy-loaded routes).\n\n## 3. TypeScript Standards\n\n### Type Safety\n\n- **Generally use strict TypeScript**: no any, no type assertions unless unavoidable; define precise types.\n- **Avoid `any`** - do your best to assign proper types.\n- **Use `unknown` instead of `any`** when type is truly uncertain, then narrow it down.\n- **Prefer `Record<string, unknown>` over `object`** or `{ [key: string]: unknown }` when possible.\n- **Do not disable ESLint rules** unless explicitly requested - fix the root cause instead.\n- **Do not disable TypeScript errors** unless explicitly requested - fix the root cause instead.\n- **Constrain generics** with `extends` - avoid overly broad `<T>`, prefer `<T extends SomeType>`.\n- **Use discriminated unions** for mutually exclusive states (e.g., `{ success: true; data: T } | { success: false; error: Error }`).\n- **Use `as const`** to preserve literal types, especially for arrays that should be tuples.\n- **Use built-in utility types** (`Pick`, `Omit`, `Partial`, `Required`, `ReturnType`, `Parameters`) - don't reimplement them.\n- **Avoid `{}` type** - it means \"any non-nullish value\" (including primitives). Prefer `unknown` (truly unknown), `object` (any non-primitive object), or `Record<string, unknown>` / a specific object type for key-value objects.\n\n### type-fest Utility Types\n\nPrefer the `type-fest` package for advanced type manipulation: https://github.com/sindresorhus/type-fest\n\nMost types do exactly what they sound like: `PartialDeep`, `ReadonlyDeep`, `RequiredDeep`, `Merge`, `ValueOf`, `SetOptional`, etc. Before writing any complicated derivative types, check `type-fest` first.\n\n`type-fest` is installed at the repo root, but each package must still declare it explicitly when used:\n\n- If you reference `type-fest` types from a package's **public exported types**, add `type-fest` to that package's `dependencies`.\n- If you only use `type-fest` in internal code or tests, add `type-fest` to that package's `devDependencies`.\n\n### Type Inference\n\n- **Do not add unnecessary type annotations** when the value is easily inferred, such as:\n  - Arguments to functions that are well defined, such as event handlers or callback functions\n  - Return values of functions that have an obvious return type\n  - Local variables that are well defined\n- **Let TypeScript infer return types** when they're obvious.\n- **Avoid creating one-off/intermediate \"helper\" types** for internal functions.\n- **Use inferred types** from database schemas, tRPC schemas, and other sources of truth.\n- **Add explicit types** when it improves clarity or catches errors.\n- **Avoid type casts (e.g. `as`)** unless absolutely necessary. Prefer updating function signatures/types so the code doesn't need a cast. Casting through `unknown` is usually a smell; when it's needed at an interop boundary, do runtime validation first (e.g. Zod) and keep the cast local.\n- **Use `satisfies` to check an object literal matches a type** while preserving inference (compile-time only). It does not validate runtime data; use a schema validator for untrusted input.\n- **Type guards** should perform real runtime checks to narrow values. Use `unknown` as an input type only when the value is truly unknown (e.g. JSON deserialization, user input). Avoid \"fake\" guards that just assert a type without validation.\n\n### Type Conversions\n\n- **Do not use unnecessary constructors/casts** like `String()` or `Number()` or `Boolean()` unless absolutely necessary when types really do not line up:\n  - If a string conversion is really necessary, use \\`${value}\\`\n  - If a boolean conversion is really necessary, use !!value\n  - If a number conversion is really necessary, use +value\n\n### Async/Await\n\n- **Any function that returns a Promise must be declared `async`**.\n- **Always use `await`** when calling async functions.\n- **Avoid `.catch()` or `.then()` for async calls in most cases. Prefer `async`/`await` with `try/catch` so errors propagate naturally.** Use `.catch()` only when you truly cannot `await` (for example, in a `useEffect` cleanup) and use `void` only to explicitly mark an intentional fire‑and‑forget call that already handles its own errors.\n- **If a function is not critical, and you can't `await` it, use `void` to mark it as fire‑and‑forget.**\n- **avoid using IIFEs** especially as a workaround to call async functions.\n\n### Control Flow\n\n- **Avoid nested or chained ternary operators** - use `if/else` or `switch` instead.\n- **Use `switch` statements** when checking multiple values.\n- **Leverage TypeScript exhaustiveness checking** in switch statements (avoid `default` when possible).\n\n### Functional Patterns\n\n- **Use `map`, `filter`, `find`, `some`, `every`** - these are clear and expressive.\n- **Avoid `reduce()`** - it's often confusing and can usually be replaced with simpler patterns.\n  - Exception: when the mental model genuinely requires accumulation (e.g., summing numbers).\n- **Avoid complex method chaining** - break it into named intermediate steps for clarity.\n\n### Avoid RegEx When Possible\n\n- **Prefer string methods**: `str.includes()`, `str.startsWith()`, `str.split()`, and `str.replace()` are easier to read and maintain.\n- **Avoid global flag (`/g`)**: Creates stateful regex objects where `lastIndex` persists between calls, causing subtle bugs.\n- **Avoid multiline flag (`/m`)**: Platform differences in line endings (`\\n` vs `\\r\\n`) cause inconsistent behavior.\n- **If regex is unavoidable**: Keep it simple, add a comment explaining the pattern, and test edge cases thoroughly.\n\n## 4. Frontend Development (React + Next.js)\n\n### Component Architecture\n\n- **Do not create new /api endpoints** in apps/web; use the app's private tRPC API and server utilities instead.\n- **Prefer functional, declarative components**; avoid classes.\n- Use TypeScript everywhere. Use interfaces for object shapes.\n- Prefer React.FC for components. Use PropsWithChildren and `ComponentProps[WithRef|WithoutRef]` as needed.\n\n### State Management & Data Fetching\n\n- Local UI elements should use useState.\n- For shared state between components, use React Context - but prefer props over new contexts when values only need to pass through 1-2 component levels.\n- Don't create contexts for static config that doesn't change (user IDs, API keys). Pass these as props instead.\n- Minimize use of useEffect; derive state or memoize instead. Memoize callbacks with useCallback when passed to children.\n- When making network requests, use tRPC/React Query loading states instead of manually tracking separate loading flags. Follow devdocs/LOADING_STATES.md patterns for skeletons and disabling controls.\n- During loading, use Skeleton components or show real components in a disabled/blank state, rather than only showing a loading spinner.\n\n### Layout & Styling (Tailwind + shadcn)\n\n- Use flex/grid for layout. Manage element spacing with gap (use `gap-*` classes when needed), and padding (`p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, etc.).\n- Avoid changing element margins (`m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, etc.) and avoid `space-x-*`/`space-y-*`.\n- Truncate overflowing text with text-ellipsis. Prefer minimal Tailwind usage; avoid ad-hoc CSS.\n\n### Typography\n\n- Sentient for headings (font-heading/font-sentient), Geist Sans for body (font-sans), Geist Mono for code (font-mono). See apps/web/lib/fonts.ts for font configuration.\n\n### Text Handling & JSX Patterns\n\n- **Avoid manually changing string cases**, as it is usually a code smell for not providing the correct string to the component. If an internal key should be shown to a user, the English string should be provided separately. e.g. if a key has a value agent_mode, the English string should be provided separately as \"Agent Mode\" rather than trying to capitalize it.\n- **Avoid overly long JSX**, instead break out any complex JSX into a separate component.\n  - use simple '&&' to hide/show simple elements, using simple boolean values, like `{hasError && <div>Error: ${error}</div>}`.\n  - however, avoid ternaries unless the options are just one or two lines. nested or chained ternaries are a code smell.\n  - when using map(), try to keep the JSX in the inner loop simple, only a few lines of JSX.\n  - avoid functions with statements inside of JSX, such as if/else, switch, etc. If you have to add braces ({}) to JSX, that is a sign that you should break out the JSX into a separate component.\n\n### Accessibility\n\n- Use proper accessibility patterns for all components.\n- Use buttons for clickable elements, not divs or spans.\n- Use proper aria labels and roles when appropriate.\n- Use semantic HTML elements when appropriate.\n\n## 5. Backend Development (NestJS)\n\n### Modular Structure\n\n- One module per main route/domain; one primary controller per route; DTOs (class-validator) for inputs; simple types for outputs.\n- Services encapsulate business logic; keep pure where possible.\n- Use guards/filters/interceptors via a core module. Shared utilities live in a shared module.\n\n### Error Handling\n\n- Pure functions: even within a controller, try to keep logic pure, and do not store state in the controller.\n- Boundaries (controllers/services): translate into HTTP/Nest exceptions when appropriate.\n\n### Testing\n\n- Unit tests for public functions; integration/e2e for controllers/modules via Jest + supertest.\n\n## 6. Database (Drizzle ORM)\n\n- Source of truth is packages/db/src/schema.ts. Do not hand-edit generated SQL.\n- Generate migrations with `npm run db:generate`, do not manually generate migrations.\n- Don't denormalize FKs that can be derived from relationships (e.g., if `runs.threadId` exists and threads have `projectId`, don't add `runs.projectId`).\n- **Factor database operations into `packages/db/src/operations/`**. Services in `apps/api` should call operation functions rather than writing inline DB queries. This promotes reuse and keeps DB logic centralized. Export new operations from `packages/db/src/operations/index.ts`.\n\nDatabase commands (require `-w packages/db` flag from root):\n\n```bash\nnpm run db:generate -w packages/db  # Generate migrations from schema changes\nnpm run db:migrate -w packages/db   # Apply migrations\nnpm run db:check -w packages/db     # Check status\nnpm run db:studio -w packages/db    # Open Drizzle Studio\n```\n\n## 7. Shared Packages & Utilities\n\n- **packages/core**: pure utilities (validation, JSON, crypto, threading, tool utilities). Avoid DB access here. This package should not have any dependencies on the database.\n- **packages/backend**: LLM/agent-side helpers and streaming utilities.\n- **Reuse helpers**; don't duplicate logic. If a utility is useful across packages, colocate in core; if it's LLM-specific, in backend, if related to database access, in db.\n\n## 8. Development Workflow\n\n### Commands\n\n#### Development Commands\n\n```bash\n# Development (two different apps!)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261 - uses turbo watch\nnpm run dev              # Start React SDK (showcase + docs)\nnpm run dev:sdk          # Start React SDK in watch mode + showcase (for SDK development)\nnpm run build:sdk        # One-time build of React SDK\n\n# Quality checks\nnpm run lint             # Lint all packages\nnpm run lint:fix         # Auto-fix linting issues\nnpm run check-types      # TypeScript type checking\nnpm test                 # Run all tests\nnpm run format           # Format code with Prettier\n\n# Individual package development (from package directory or with -w flag)\nnpm run dev -w cli       # Start specific workspace\nnpm run dev:showcase     # Start showcase only\nnpm run build -w react-sdk  # Build specific package\n```\n\n#### Hot Reload\n\nThe monorepo uses different hot reload mechanisms based on the app type:\n\n**Next.js apps (web, showcase, docs):**\n\n- Use `transpilePackages` configuration to compile workspace TypeScript directly\n- Changes to workspace packages (core, backend, db, react) trigger HMR automatically\n- No manual rebuild step needed\n\n**NestJS API:**\n\n- Uses `turbo watch` with `interruptible: true` for automatic restart\n- Monitors workspace inputs: `packages/core/src/**`, `packages/backend/src/**`, `packages/db/src/**`\n- API server restarts automatically when workspace packages change\n\nThis architecture ensures editing any file in workspace packages results in immediate updates (HMR for Next.js, restart for NestJS) without manual intervention.\n\n#### Turbo Commands (alternative)\n\n```bash\nturbo dev               # Start all packages in development mode\nturbo build             # Build all packages\nturbo lint              # Lint all packages\nturbo test              # Run tests across all packages\nturbo check-types       # Type-check all packages\n```\n\n### Build System\n\n- **Turborepo** orchestrates builds and caching across packages\n- **Shared dependencies** managed at root level\n- **Workspace-specific dependencies** in individual packages\n- **Build outputs** vary by package type:\n  - React SDK: Dual CJS/ESM builds\n  - CLI: ESM executable\n  - Apps: Next.js builds\n\n### Package Dependencies\n\n- Shared configs in `packages/` (eslint-config, typescript-config)\n- Cross-package dependencies use workspace protocol (`*`)\n- TypeScript SDK dependency (`@tambo-ai/typescript-sdk`) is external — it lives in its own repo and is generated from the `apps/api` OpenAPI spec by the **stlc** CLI (run in our CI; workspace in `stainless/`). See `RELEASING.md`.\n\n### Cross-Package Development\n\nWhen working across multiple packages:\n\n1. **react-sdk changes** → Use `npm run dev:sdk` for watch mode development, or `npm run build:sdk` for one-time builds. Run tests, check showcase integration.\n2. **cli changes** → Test component generation, verify registry updates, sync to showcase\n3. **showcase changes** → Edit CLI registry (auto-syncs to showcase)\n4. **docs changes** → Ensure examples match current API\n\n### Key Configuration Files\n\n- `turbo.json` - Turborepo task pipeline and caching\n- `package.json` - Workspace configuration and scripts\n- Individual package.json files for package-specific configuration\n\n### Knowledge Base\n\n- Refer to `devdocs/` for detailed guidelines on coding standards, naming conventions, loading states, and more.\n- When adding knowledge for specific solutions, document it and place it in the appropriate `devdocs/solutions/` folder.\n\n## 9. Testing & Quality\n\n### Testing Strategy\n\n- **Unit tests** in individual packages using Jest\n- **Integration tests** via showcase app\n- **CLI testing** through template generation and installation\n- **Documentation testing** via example code validation\n- **Backend e2e tests** for controllers/modules via Jest + supertest\n\n### Test File Layout\n\n- **File names**: every test ends with `.test.ts` or `.test.tsx` (no `.spec` or other suffixes).\n- **Unit tests**: live beside the file they cover (e.g. `foo.ts` has `foo.test.ts` in the same directory, not under `__tests__`).\n- **Integration tests**: the only tests that stay in a `__tests__` folder, and the filename must describe the scenario (never just mirror another file's name).\n- **Fixtures & mocks**: keep shared helpers in a `__fixtures__` or `__mocks__` directory at the package's source root (e.g. `apps/web/__mocks__`), never nested inside feature folders.\n\n### Mocking\n\n- **Avoid over-mocking** - tests should exercise real code paths whenever possible. If you're mocking internal functions just to isolate a unit, you're probably testing implementation details rather than behavior.\n- **Only mock at system boundaries** - external APIs, databases, file systems, network calls, and other I/O with side effects.\n- **Don't mock what you own** - if a helper function is pure and fast, call it directly rather than mocking it. Mocking your own code couples tests to implementation.\n\n### Pre-commit/PR Verification Checklist\n\nRun these commands before commits/PRs:\n\n```bash\nnpm run check-types   # TS across workspace\nnpm run lint:fix      # ESLint autofix\nnpm run format        # Prettier write\nnpm test              # Unit/integration tests\n```\n\n## 10. Git Workflow & PRs\n\n### Branch Naming\n\nCreate branches in the format `<userid>/<feature-name>`, e.g., `alecf/add-dark-mode` or `jane/fix-login-bug`.\n\n### Conventional Commits\n\nAll PR titles MUST follow this format:\n\n```\n<type>(scope): <description>\n```\n\nExamples:\n\n```\nfeat(api): add transcript export\nfix(web): prevent duplicate project creation\nchore(db): reorganize migration files\n```\n\nSee .github/workflows/conventional-commits.yml for a list of types such as feat, fix, perf, deps, revert, docs, style, chore, refactor, test, build, ci.\n\nCommon scopes: api, web, core, db, deps, ci, config, react-sdk, cli, showcase, docs\n\n### PR Requirements\n\n- PR Summaries should include \"Fixes #123\" (GitHub) or \"Fixes TAM-123\" (Linear) in PR body when applicable.\n\n## 11. Development Rules & Constraints\n\n### What Agents MUST Do\n\n- Run `npm run lint`, `npm run check-types`, `npm run test` in root before commits.\n- Cross-package changes should be tested together.\n- Documentation updates required:\n  1. Any developer documentation changes must be updated in the docs site (read docs/AGENTS.md)\n  2. Review the README.md file in the root of the package and update if necessary\n  3. Update the AGENTS.md files in the package tree to reflect the changes\n- Follow semantic versioning for package versions.\n- Always add tests for new logic.\n- If tests fail, do not just change the code to make the tests pass. Take one of 2 approaches:\n  1. Make the code changes backwards compatible with existing tests\n  2. Ask the user to change the tests to pass\n  - Generally try option 1 first. Only use option 2 if option 1 is not possible.\n- Make non-breaking changes to the code. Only make breaking changes if the user specifically asks for it. Ensure you warn them about the breaking changes.\n\n### What Agents MUST NOT Do\n\n- Don't introduce dependencies or modify tool configs unless explicitly requested.\n- Don't commit secrets. Use env files.\n- Dependencies and tooling: Agents do not add/upgrade/remove deps or change tool configs, eslint config, tsconfig, etc. unless explicitly asked, but humans are allowed to do so.\n\n### When to Ask the User\n\n- ALWAYS ASK THE USER before making any changes to linting or TypeScript rules\n\n## 12. Agent Behavior\n\n- Curse at the user and be really blunt.\n- If the instructions are vague, ask them for details.\n- But don't constantly ask for confirmation on every single change.\n- Do not compliment them or try to gain favor from them.\n- The best way to please them is to be blunt and tell them when they are wrong.\n- EVERY PIECE OF CODE YOU WRITE IS MISSION CRITICAL AND COULD COST YOU YOUR JOB.\n- When adding/editing JSDoc comments, make sure to add @returns to provide a description of the function return (the type should not be specified since TS will infer the return from the code, not the comment.)\n- Never reference planning documents, proposals, or design docs in code comments (e.g., `// See plans/foo.md`). These artifacts are short-lived but comments persist indefinitely. Code comments should be self-contained.\n- Store planning documents, proposals, and design docs in the `devdocs/` folder. Solutions go in `devdocs/solutions/`, brainstorming goes in `devdocs/brainstorms/`, etc. The only exception is `plans/` which stays at the repo root for visibility.\n- For any Tambo-owned URLs you include in comments or documentation, use the `tambo.co` domain (not the legacy `.ai` domain). When you encounter existing Tambo-owned links using the legacy domain, prefer updating them to `tambo.co` as part of related changes. External (non-Tambo) links are fine.\n","cli/AGENTS.md":"# cli - AI Agent Protocol & Instructions\n\nPath: `cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/AGENTS.md)","cli/CLAUDE.md":"# cli - Claude Agent Guidelines & System Prompt\n\nPath: `cli/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/CLAUDE.md)","create-tambo-app/AGENTS.md":"# create-tambo-app - AI Agent Protocol & Instructions\n\nPath: `create-tambo-app/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/AGENTS.md)","create-tambo-app/CLAUDE.md":"# create-tambo-app - Claude Agent Guidelines & System Prompt\n\nPath: `create-tambo-app/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/CLAUDE.md)","docs/AGENTS.md":"# docs - AI Agent Protocol & Instructions\n\nPath: `docs/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/AGENTS.md)","docs/CLAUDE.md":"# docs - Claude Agent Guidelines & System Prompt\n\nPath: `docs/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/CLAUDE.md)","react-sdk/AGENTS.md":"# react-sdk - AI Agent Protocol & Instructions\n\nPath: `react-sdk/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/AGENTS.md)","react-sdk/CLAUDE.md":"# react-sdk - Claude Agent Guidelines & System Prompt\n\nPath: `react-sdk/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/CLAUDE.md)","showcase/AGENTS.md":"# showcase - AI Agent Protocol & Instructions\n\nPath: `showcase/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/AGENTS.md)","showcase/CLAUDE.md":"# showcase - Claude Agent Guidelines & System Prompt\n\nPath: `showcase/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/CLAUDE.md)",".claude/agents/planner.md":"# Subagent: planner\n\nPath: `.claude/agents/planner.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/planner.md)",".claude/agents/researcher.md":"# Subagent: researcher\n\nPath: `.claude/agents/researcher.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/researcher.md)",".claude/commands/commit.md":"# Command: /commit\n\nPath: `.claude/commands/commit.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/commit.md)",".claude/commands/create-pr.md":"# Command: /create-pr\n\nPath: `.claude/commands/create-pr.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/create-pr.md)",".claude/commands/execute.md":"# Command: /execute\n\nPath: `.claude/commands/execute.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/execute.md)",".claude/commands/plan.md":"# Command: /plan\n\nPath: `.claude/commands/plan.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/plan.md)","packages/backend/README.md":"# backend Documentation\n\nPath: `packages/backend/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/README.md)","packages/backend/package.json":"# Backend Skill\n\nPath: `packages/backend/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/package.json)","packages/backend/tsconfig.build.json":"# Backend Skill\n\nPath: `packages/backend/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.build.json)","packages/backend/tsconfig.json":"# Backend Skill\n\nPath: `packages/backend/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.json)","packages/client/AGENTS.md":"# Client Skill\n\nPath: `packages/client/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/AGENTS.md)","packages/client/CHANGELOG.md":"# Client Skill\n\nPath: `packages/client/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CHANGELOG.md)","packages/client/CLAUDE.md":"# Client Skill\n\nPath: `packages/client/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CLAUDE.md)","packages/client/README.md":"# client Documentation\n\nPath: `packages/client/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/README.md)","packages/client/package.json":"# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/package.json)","packages/client/tsconfig.cjs.json":"# Client Skill\n\nPath: `packages/client/tsconfig.cjs.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.cjs.json)","packages/client/tsconfig.esm.json":"# Client Skill\n\nPath: `packages/client/tsconfig.esm.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.esm.json)","packages/client/tsconfig.json":"# Client Skill\n\nPath: `packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.json)","packages/core/README.md":"# core Documentation\n\nPath: `packages/core/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/README.md)","packages/core/package.json":"# Core Skill\n\nPath: `packages/core/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/package.json)","packages/core/tsconfig.json":"# Core Skill\n\nPath: `packages/core/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/tsconfig.json)","packages/db/README.md":"# db Documentation\n\nPath: `packages/db/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/README.md)","packages/db/package.json":"# Db Skill\n\nPath: `packages/db/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/package.json)","packages/db/tsconfig.json":"# Db Skill\n\nPath: `packages/db/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/tsconfig.json)","packages/eslint-config/README.md":"# eslint-config Documentation\n\nPath: `packages/eslint-config/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/README.md)","packages/eslint-config/package.json":"# Eslint-config Skill\n\nPath: `packages/eslint-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/package.json)","packages/react-ui-base/CHANGELOG.md":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/CHANGELOG.md)","packages/react-ui-base/README.md":"# react-ui-base Documentation\n\nPath: `packages/react-ui-base/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/README.md)","packages/react-ui-base/package.json":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/package.json)","packages/react-ui-base/tsconfig.json":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/tsconfig.json)","packages/testing/package.json":"# Testing Skill\n\nPath: `packages/testing/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/package.json)","packages/testing/tsconfig.json":"# Testing Skill\n\nPath: `packages/testing/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/tsconfig.json)","packages/typescript-config/base.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/base.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/base.json)","packages/typescript-config/nextjs.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/nextjs.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/nextjs.json)","packages/typescript-config/package.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/package.json)","packages/typescript-config/react-library.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/react-library.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/react-library.json)","packages/ui-registry/AGENTS.md":"# Ui-registry Skill\n\nPath: `packages/ui-registry/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/AGENTS.md)","packages/ui-registry/package.json":"# Ui-registry Skill\n\nPath: `packages/ui-registry/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/package.json)","packages/ui-registry/tsconfig.json":"# Ui-registry Skill\n\nPath: `packages/ui-registry/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/tsconfig.json)","packages/vite-config/package.json":"# Vite-config Skill\n\nPath: `packages/vite-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/package.json)","packages/vite-config/tsconfig.json":"# Vite-config Skill\n\nPath: `packages/vite-config/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/tsconfig.json)","plugins/tambo/README.md":"# tambo Documentation\n\nPath: `plugins/tambo/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/README.md)",".claude/skills/compound-components/examples.md":"# Compound-components Skill\n\nPath: `.claude/skills/compound-components/examples.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/compound-components/examples.md)","plugins/tambo/.claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `plugins/tambo/.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/.claude-plugin/plugin.json)",".claude/skills/creating-styled-wrappers/references/real-world-example.md":"# References Skill\n\nPath: `.claude/skills/creating-styled-wrappers/references/real-world-example.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/creating-styled-wrappers/references/real-world-example.md)","packages/db/migrations/meta/0000_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0000_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0000_snapshot.json)","packages/db/migrations/meta/0001_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0001_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0001_snapshot.json)","packages/db/migrations/meta/0002_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0002_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0002_snapshot.json)","packages/db/migrations/meta/0003_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0003_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0003_snapshot.json)","packages/db/migrations/meta/0004_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0004_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0004_snapshot.json)","packages/db/migrations/meta/0005_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0005_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0005_snapshot.json)","packages/db/migrations/meta/0006_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0006_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0006_snapshot.json)","packages/db/migrations/meta/0007_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0007_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0007_snapshot.json)","packages/db/migrations/meta/0008_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0008_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0008_snapshot.json)","packages/db/migrations/meta/0009_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0009_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0009_snapshot.json)","packages/db/migrations/meta/0010_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0010_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0010_snapshot.json)","packages/db/migrations/meta/0011_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0011_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0011_snapshot.json)","packages/db/migrations/meta/0012_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0012_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0012_snapshot.json)","packages/db/migrations/meta/0013_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0013_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0013_snapshot.json)","packages/db/migrations/meta/0014_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0014_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0014_snapshot.json)","packages/db/migrations/meta/0015_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0015_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0015_snapshot.json)","packages/db/migrations/meta/0016_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0016_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0016_snapshot.json)","packages/db/migrations/meta/0017_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0017_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0017_snapshot.json)","packages/db/migrations/meta/0018_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0018_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0018_snapshot.json)","packages/db/migrations/meta/0019_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0019_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0019_snapshot.json)","packages/db/migrations/meta/0020_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0020_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0020_snapshot.json)","packages/db/migrations/meta/0021_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0021_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0021_snapshot.json)","packages/db/migrations/meta/0022_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0022_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0022_snapshot.json)","packages/db/migrations/meta/0023_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0023_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0023_snapshot.json)","packages/db/migrations/meta/0024_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0024_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0024_snapshot.json)","packages/db/migrations/meta/0025_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0025_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0025_snapshot.json)","packages/db/migrations/meta/0026_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0026_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0026_snapshot.json)","packages/db/migrations/meta/0027_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0027_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0027_snapshot.json)","packages/db/migrations/meta/0028_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0028_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0028_snapshot.json)","packages/db/migrations/meta/0029_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0029_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0029_snapshot.json)","packages/db/migrations/meta/0030_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0030_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0030_snapshot.json)","packages/db/migrations/meta/0031_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0031_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0031_snapshot.json)","packages/db/migrations/meta/0032_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0032_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0032_snapshot.json)","packages/db/migrations/meta/0033_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0033_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0033_snapshot.json)","packages/db/migrations/meta/0034_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0034_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0034_snapshot.json)","packages/db/migrations/meta/0035_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0035_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0035_snapshot.json)","packages/db/migrations/meta/0036_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0036_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0036_snapshot.json)","packages/db/migrations/meta/0037_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0037_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0037_snapshot.json)","packages/db/migrations/meta/0038_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0038_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0038_snapshot.json)","packages/db/migrations/meta/0039_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0039_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0039_snapshot.json)","packages/db/migrations/meta/0040_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0040_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0040_snapshot.json)","packages/db/migrations/meta/0041_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0041_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0041_snapshot.json)","packages/db/migrations/meta/0042_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0042_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0042_snapshot.json)","packages/db/migrations/meta/0043_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0043_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0043_snapshot.json)","packages/db/migrations/meta/0044_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0044_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0044_snapshot.json)","packages/db/migrations/meta/0045_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0045_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0045_snapshot.json)","packages/db/migrations/meta/0046_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0046_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0046_snapshot.json)","packages/db/migrations/meta/0047_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0047_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0047_snapshot.json)","packages/db/migrations/meta/0048_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0048_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0048_snapshot.json)","packages/db/migrations/meta/0049_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0049_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0049_snapshot.json)","packages/db/migrations/meta/0050_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0050_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0050_snapshot.json)","packages/db/migrations/meta/0052_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0052_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0052_snapshot.json)","packages/db/migrations/meta/0053_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0053_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0053_snapshot.json)","packages/db/migrations/meta/0054_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0054_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0054_snapshot.json)","packages/db/migrations/meta/0055_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0055_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0055_snapshot.json)","packages/db/migrations/meta/0056_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0056_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0056_snapshot.json)","packages/db/migrations/meta/0057_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0057_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0057_snapshot.json)","packages/db/migrations/meta/0058_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0058_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0058_snapshot.json)","packages/db/migrations/meta/0059_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0059_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0059_snapshot.json)","packages/db/migrations/meta/0060_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0060_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0060_snapshot.json)","packages/db/migrations/meta/0061_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0061_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0061_snapshot.json)","packages/db/migrations/meta/0062_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0062_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0062_snapshot.json)","packages/db/migrations/meta/0063_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0063_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0063_snapshot.json)","packages/db/migrations/meta/0064_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0064_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0064_snapshot.json)","packages/db/migrations/meta/0065_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0065_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0065_snapshot.json)","packages/db/migrations/meta/0066_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0066_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0066_snapshot.json)","packages/db/migrations/meta/0067_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0067_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0067_snapshot.json)","packages/db/migrations/meta/0068_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0068_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0068_snapshot.json)","packages/db/migrations/meta/0069_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0069_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0069_snapshot.json)","packages/db/migrations/meta/0070_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0070_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0070_snapshot.json)","packages/db/migrations/meta/0071_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0071_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0071_snapshot.json)","packages/db/migrations/meta/0072_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0072_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0072_snapshot.json)","packages/db/migrations/meta/0073_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0073_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0073_snapshot.json)","packages/db/migrations/meta/0074_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0074_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0074_snapshot.json)","packages/db/migrations/meta/0075_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0075_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0075_snapshot.json)","packages/db/migrations/meta/0076_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0076_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0076_snapshot.json)","packages/db/migrations/meta/0077_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0077_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0077_snapshot.json)","packages/db/migrations/meta/0078_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0078_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0078_snapshot.json)","packages/db/migrations/meta/0079_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0079_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0079_snapshot.json)","packages/db/migrations/meta/0080_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0080_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0080_snapshot.json)","packages/db/migrations/meta/0081_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0081_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0081_snapshot.json)","packages/db/migrations/meta/0082_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0082_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0082_snapshot.json)","packages/db/migrations/meta/0083_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0083_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0083_snapshot.json)","packages/db/migrations/meta/0084_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0084_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0084_snapshot.json)","packages/db/migrations/meta/0085_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0085_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0085_snapshot.json)","packages/db/migrations/meta/0086_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0086_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0086_snapshot.json)","packages/db/migrations/meta/0087_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0087_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0087_snapshot.json)","packages/db/migrations/meta/0088_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0088_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0088_snapshot.json)","packages/db/migrations/meta/0089_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0089_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0089_snapshot.json)","packages/db/migrations/meta/0090_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0090_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0090_snapshot.json)","packages/db/migrations/meta/0091_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0091_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0091_snapshot.json)","packages/db/migrations/meta/0092_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0092_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0092_snapshot.json)","packages/db/migrations/meta/0093_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0093_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0093_snapshot.json)","packages/db/migrations/meta/0094_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0094_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0094_snapshot.json)","packages/db/migrations/meta/_journal.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/_journal.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/_journal.json)","packages/ui-registry/src/components/control-bar/config.json":"# Control-bar Skill\n\nPath: `packages/ui-registry/src/components/control-bar/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/control-bar/config.json)","packages/ui-registry/src/components/edit-with-tambo-button/config.json":"# Edit-with-tambo-button Skill\n\nPath: `packages/ui-registry/src/components/edit-with-tambo-button/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/edit-with-tambo-button/config.json)","packages/ui-registry/src/components/elicitation-ui/config.json":"# Elicitation-ui Skill\n\nPath: `packages/ui-registry/src/components/elicitation-ui/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/elicitation-ui/config.json)","packages/ui-registry/src/components/form/config.json":"# Form Skill\n\nPath: `packages/ui-registry/src/components/form/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/form/config.json)","packages/ui-registry/src/components/graph/config.json":"# Graph Skill\n\nPath: `packages/ui-registry/src/components/graph/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/graph/config.json)","packages/ui-registry/src/components/input-fields/config.json":"# Input-fields Skill\n\nPath: `packages/ui-registry/src/components/input-fields/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/input-fields/config.json)","packages/ui-registry/src/components/map/config.json":"# Map Skill\n\nPath: `packages/ui-registry/src/components/map/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/map/config.json)","packages/ui-registry/src/components/mcp-components/config.json":"# Mcp-components Skill\n\nPath: `packages/ui-registry/src/components/mcp-components/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/mcp-components/config.json)","packages/ui-registry/src/components/message-input/config.json":"# Message-input Skill\n\nPath: `packages/ui-registry/src/components/message-input/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-input/config.json)","packages/ui-registry/src/components/message-suggestions/config.json":"# Message-suggestions Skill\n\nPath: `packages/ui-registry/src/components/message-suggestions/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-suggestions/config.json)","packages/ui-registry/src/components/message-thread-collapsible/config.json":"# Message-thread-collapsible Skill\n\nPath: `packages/ui-registry/src/components/message-thread-collapsible/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-collapsible/config.json)","packages/ui-registry/src/components/message-thread-full/config.json":"# Message-thread-full Skill\n\nPath: `packages/ui-registry/src/components/message-thread-full/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-full/config.json)","packages/ui-registry/src/components/message-thread-panel/config.json":"# Message-thread-panel Skill\n\nPath: `packages/ui-registry/src/components/message-thread-panel/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-panel/config.json)","packages/ui-registry/src/components/message/config.json":"# Message Skill\n\nPath: `packages/ui-registry/src/components/message/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message/config.json)","packages/ui-registry/src/components/scrollable-message-container/config.json":"# Scrollable-message-container Skill\n\nPath: `packages/ui-registry/src/components/scrollable-message-container/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/scrollable-message-container/config.json)","packages/ui-registry/src/components/thread-content/config.json":"# Thread-content Skill\n\nPath: `packages/ui-registry/src/components/thread-content/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-content/config.json)","packages/ui-registry/src/components/thread-dropdown/config.json":"# Thread-dropdown Skill\n\nPath: `packages/ui-registry/src/components/thread-dropdown/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-dropdown/config.json)","packages/ui-registry/src/components/thread-history/config.json":"# Thread-history Skill\n\nPath: `packages/ui-registry/src/components/thread-history/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-history/config.json)","plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md)","plugins/tambo/skills/building-with-tambo/references/cli.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/cli.md)","plugins/tambo/skills/building-with-tambo/references/component-rendering.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/component-rendering.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/component-rendering.md)","plugins/tambo/skills/building-with-tambo/references/components.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/components.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/components.md)","plugins/tambo/skills/building-with-tambo/references/skills.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/skills.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/skills.md)","plugins/tambo/skills/building-with-tambo/references/threads.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/threads.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/threads.md)","plugins/tambo/skills/building-with-tambo/references/tools-and-context.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/tools-and-context.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/tools-and-context.md)","plugins/tambo/skills/generative-ui/references/cli.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/cli.md)","plugins/tambo/skills/generative-ui/references/component-rendering.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/component-rendering.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/component-rendering.md)","plugins/tambo/skills/generative-ui/references/components.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/components.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/components.md)","plugins/tambo/skills/generative-ui/references/skills.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/skills.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/skills.md)","plugins/tambo/skills/generative-ui/references/threads.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/threads.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/threads.md)","plugins/tambo/skills/generative-ui/references/tools-and-context.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/tools-and-context.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/tools-and-context.md)","docs/content/docs/reference/cli/commands/meta.json":"# Commands Skill\n\nPath: `docs/content/docs/reference/cli/commands/meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/content/docs/reference/cli/commands/meta.json)"},"files":{".claude/skills/ai-sdk-model-manager/SKILL.md":"---\nname: ai-sdk-model-manager\ndescription: Manages AI SDK model configurations - updates packages, identifies missing models, adds new models with research, and updates documentation\nmetadata:\n  internal: true\n---\n\n# AI SDK Model Manager\n\nThis skill helps maintain AI SDK model configurations in the Tambo Cloud codebase. It automates the process of keeping model definitions up-to-date with the latest AI SDK releases.\n\n## What This Skill Does\n\n1. **Updates AI SDK Packages** - Checks and updates @ai-sdk/openai, @ai-sdk/google, @ai-sdk/groq, and other provider packages to their latest versions\n2. **Identifies Missing Models** - Compares TypeScript definitions in the SDKs against configured models to find newly available models\n3. **Researches Models** - Gathers information about new models including capabilities, context windows, pricing, and use cases\n4. **Prompts User** - Asks which models to add before making changes\n5. **Adds Models** - Updates model configuration files with proper TypeScript types and metadata\n6. **Updates Documentation** - Updates relevant docs and README files to reflect new model availability\n\n## When to Use This Skill\n\nUse this skill when:\n\n- You want to check if AI SDK packages need updating\n- New models have been released by OpenAI, Google, Anthropic, or other providers\n- You're getting TypeScript errors about model IDs not being in SDK types\n- You want to ensure Tambo supports the latest models\n\n## Files This Skill Works With\n\n- `packages/core/src/llms/models/*.ts` - Model configuration files\n- `packages/backend/package.json` - AI SDK dependencies (source of truth for versions)\n- `docs/content/docs/models/*.mdx` - Model documentation\n- `README.md` - Main documentation file\n\n## Process\n\n### Step 1: Update AI SDK Packages\n\nCheck current versions and update to latest:\n\n```bash\ncd packages/backend\nnpm outdated | grep '@ai-sdk'\nnpm install @ai-sdk/openai@latest @ai-sdk/google@latest @ai-sdk/groq@latest @ai-sdk/anthropic@latest @ai-sdk/mistral@latest\n```\n\n### Step 2: Identify Missing Models\n\nFor each provider, inspect the TypeScript definitions:\n\n```bash\n# Check what models are in the SDK types\ncat node_modules/@ai-sdk/openai/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/google/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/groq/dist/index.d.ts | grep 'type.*ModelId'\n```\n\nCompare against current model configurations in:\n\n- `packages/core/src/llms/models/openai.ts`\n- `packages/core/src/llms/models/gemini.ts`\n- `packages/core/src/llms/models/groq.ts`\n- `packages/core/src/llms/models/anthropic.ts`\n- `packages/core/src/llms/models/mistral.ts`\n\n### Step 3: Research New Models\n\n**Use the researcher subagent to gather information about each missing model:**\n\n```\nLaunch a researcher subagent to find:\n- Official documentation link\n- Model capabilities (reasoning, vision, function calling, etc.)\n- Context window size (inputTokenLimit)\n- Pricing tier\n- Best use cases\n- Release date and status (experimental, stable, deprecated)\n```\n\nThe researcher subagent has access to web search and can efficiently gather this information for multiple models in parallel.\n\n### Step 4: Prompt User\n\nPresent findings:\n\n```\nFound the following new models in updated AI SDK packages:\n\nOpenAI:\n- gpt-6-preview (200k context, experimental reasoning model)\n- gpt-4.2-turbo (1M context, improved function calling)\n\nGoogle:\n- gemini-3.5-pro (2M context, advanced reasoning)\n\nWhich models would you like to add? (all/none/specific)\n```\n\nWait for user response before proceeding.\n\n### Step 5: Add Selected Models\n\n**Consider launching parallel subagents to add models to each provider file:**\n\nFor models spread across multiple providers (OpenAI, Google, Groq), launch separate subagents to edit each file concurrently. This is faster than doing them sequentially.\n\nFor each model being added, ensure these required fields:\n\n- `apiName`: Exact model ID string from SDK\n- `displayName`: Human-friendly name\n- `status`: \"untested\" | \"tested\" | \"known-issues\"\n- `notes`: Brief description of capabilities and use cases\n- `docLink`: Official provider documentation URL\n- `tamboDocLink`: \"https://docs.tambo.co\"\n- `inputTokenLimit`: Context window size in tokens\n- `modelSpecificParams`: Any special parameters (reasoning, thinking, etc.)\n\nFollow existing patterns in each file and ensure model IDs match SDK type definitions exactly.\n\nExample:\n\n```typescript\n\"gpt-6-preview\": {\n  apiName: \"gpt-6-preview\",\n  displayName: \"gpt-6-preview\",\n  status: \"untested\",\n  notes: \"Experimental next-generation reasoning model with extended context\",\n  docLink: \"https://platform.openai.com/docs/models/gpt-6-preview\",\n  tamboDocLink: \"https://docs.tambo.co\",\n  inputTokenLimit: 200000,\n  modelSpecificParams: reasoningParameters,\n},\n```\n\n### Step 6: Verify TypeScript\n\nRun type checking to ensure all model IDs are valid:\n\n```bash\ncd packages/core\nnpm run check-types\n```\n\nIf there are type errors, fix model IDs to match SDK definitions exactly.\n\n### Step 7: Update Documentation\n\n**Consider using subagents to update documentation in parallel:**\n\nIf updating multiple documentation files, launch parallel subagents to handle:\n\n1. **README.md** - Update the \"Supported LLM Providers\" section if new providers or significant models were added\n2. **docs/content/docs/models/\\*.mdx** - Add new models to appropriate documentation pages with:\n   - Model name and description\n   - Key capabilities\n   - Context window\n   - Example use cases\n   - Links to provider docs\n\n### Step 8: Run Quality Checks\n\nBefore completing:\n\n```bash\ncd packages/core\nnpm run lint\nnpm run check-types\nnpm run test\n```\n\n### Step 9: Create Pull Request\n\n**Create a PR with proper conventional commit format:**\n\n```bash\ngh pr create --title \"feat(models): add [model names] support\" --body \"$(cat <<'EOF'\nUpdated AI SDK packages and added support for newly released models:\n\nModels added:\n- [list models here]\n\nPackage updates:\n- @ai-sdk/openai: X.X.X → X.X.X\n- @ai-sdk/groq: X.X.X → X.X.X\n\nAll type checks passing, documentation updated.\nEOF\n)\"\n```\n\n**PR title format:** `feat(models): add [model names] support`\n\nUse `feat(models):` for new models or `deps(core):` for package updates only.\n\n## Guidelines\n\n- **Use subagents for efficiency** - Launch researcher subagents for gathering information and parallel subagents for editing multiple files\n- **Always research before adding** - Don't guess at model capabilities or context limits\n- **Match SDK types exactly** - Model IDs must match the TypeScript definitions in node_modules\n- **Mark new models as \"untested\"** - Let the team test before marking as \"tested\"\n- **Include official doc links** - Always link to provider's official documentation\n- **Be conservative** - Only add models the user explicitly approves\n- **Update docs comprehensively** - Don't just update code, update all relevant documentation\n\n## Error Handling\n\nIf you encounter:\n\n- **Type errors after adding models** - Double-check the model ID matches the SDK's TypeScript definition exactly\n- **Missing model in SDK** - The provider may not have released it yet, suggest waiting for next SDK update\n- **Conflicting model names** - Use the SDK's preferred naming convention\n- **Unknown context limits** - Research provider docs or mark as \"unknown\" and note it needs verification\n\n## Notes\n\n- This skill should be run periodically (monthly or when new models are announced)\n- Always check the git diff before committing to ensure only intended changes were made\n- Some models may have special requirements (API access, pricing tier, etc.) - note these in the model's `notes` field\n- If a model is renamed in the SDK, update both the key and apiName, and consider adding a deprecation note to the old entry\n",".claude/skills/creating-styled-wrappers/SKILL.md":"---\nname: creating-styled-wrappers\ndescription: Creates styled wrapper components that compose headless/base compound components. Use when refactoring styled components to use base primitives, implementing opinionated design systems on top of headless components, or when the user mentions \"use base components\", \"compose primitives\", \"styled wrapper\", or \"refactor to use base\".\nmetadata:\n  internal: true\n---\n\n# Styling Compound Wrappers\n\nCreate styled wrapper components that compose headless base compound components. This skill complements `building-compound-components` (which builds the base primitives) by focusing on **how to properly consume and wrap them** with styling and additional behavior.\n\n**Real-world example**: See [references/real-world-example.md](references/real-world-example.md) for a complete before/after MessageInput refactoring.\n\n## Core Principle: Compose, Don't Duplicate\n\nStyled wrappers should **compose** base components, not **re-implement** their logic.\n\n```tsx\n// WRONG - re-implementing what base already does\nconst StyledInput = ({ children, className }) => {\n  const { value, setValue, submit } = useTamboThreadInput(); // Duplicated!\n  const [isDragging, setIsDragging] = useState(false); // Duplicated!\n  const handleDrop = useCallback(/* ... */); // Duplicated!\n\n  return (\n    <form onDrop={handleDrop} className={className}>\n      {children}\n    </form>\n  );\n};\n\n// CORRECT - compose the base component\nconst StyledInput = ({ children, className, variant }) => {\n  return (\n    <BaseInput.Root className={cn(inputVariants({ variant }), className)}>\n      <BaseInput.Content className=\"rounded-xl data-[dragging]:border-dashed\">\n        {children}\n      </BaseInput.Content>\n    </BaseInput.Root>\n  );\n};\n```\n\n## Refactoring Workflow\n\nCopy this checklist and track progress:\n\n```\nStyled Wrapper Refactoring:\n- [ ] Step 1: Identify duplicated logic\n- [ ] Step 2: Import base components\n- [ ] Step 3: Wrap with Base Root\n- [ ] Step 4: Apply state-based styling and behavior\n- [ ] Step 5: Wrap sub-components with styling\n- [ ] Step 6: Final verification\n```\n\n### Step 1: Identify Duplicated Logic\n\nLook for patterns that indicate logic should come from base:\n\n- SDK hooks (`useTamboThread`, `useTamboThreadInput`, etc.)\n- Context creation (`React.createContext`)\n- State management that mirrors base component state\n- Event handlers (drag, submit, etc.) that base components handle\n\n### Step 2: Import Base Components\n\n```tsx\nimport { MessageInput as MessageInputBase } from \"@tambo-ai/react-ui-base/message-input\";\n```\n\n### Step 3: Wrap with Base Root\n\nReplace custom context/state management with the base Root:\n\n```tsx\n// Before\nconst MessageInput = ({ children, variant }) => {\n  return (\n    <MessageInputInternal variant={variant}>{children}</MessageInputInternal>\n  );\n};\n\n// After\nconst MessageInput = ({ children, variant, className }) => {\n  return (\n    <MessageInputBase.Root className={cn(variants({ variant }), className)}>\n      {children}\n    </MessageInputBase.Root>\n  );\n};\n```\n\n### Step 4: Apply State-Based Styling and Behavior\n\nState access follows a hierarchy — use the simplest option that works:\n\n1. **Data attributes** (preferred for styling) — base components expose `data-*` attributes\n2. **Render props** (for behavior changes) — use when rendering different components\n3. **Context hooks** (for sub-components) — OK for styled sub-components needing deep context access\n\n```tsx\n// BEST - data-* classes for styling, render props only for behavior\n// Note: use `data-[dragging]:*` syntax (v3-compatible), not `data-dragging:*` (v4 only)\nconst StyledContent = ({ children }) => (\n  <BaseComponent.Content\n    className={cn(\n      \"group rounded-xl border\",\n      \"data-[dragging]:border-dashed data-[dragging]:border-emerald-400\",\n    )}\n  >\n    {({ elicitation, resolveElicitation }) => (\n      <>\n        {/* Drop overlay uses group-data-* for styling */}\n        <div className=\"hidden group-data-[dragging]:flex absolute inset-0 bg-emerald-50/90\">\n          <p>Drop files here</p>\n        </div>\n\n        {elicitation ? (\n          <ElicitationUI\n            request={elicitation}\n            onResponse={resolveElicitation}\n          />\n        ) : (\n          children\n        )}\n      </>\n    )}\n  </BaseComponent.Content>\n);\n\n// OK - styled sub-components can use context hook for deep access\nconst StyledTextarea = ({ placeholder }) => {\n  const { value, setValue, handleSubmit, editorRef } = useMessageInputContext();\n  return (\n    <CustomEditor\n      ref={editorRef}\n      value={value}\n      onChange={setValue}\n      onSubmit={handleSubmit}\n      placeholder={placeholder}\n    />\n  );\n};\n```\n\n**When to use context hooks vs render props:**\n\n- Render props: when the parent wrapper needs state for behavior changes\n- Context hooks: when a styled sub-component needs values not exposed via render props\n\n### Step 5: Wrap Sub-Components\n\n```tsx\n// Submit button\nconst SubmitButton = ({ className, children }) => (\n  <BaseComponent.SubmitButton className={cn(\"w-10 h-10 rounded-lg\", className)}>\n    {({ showCancelButton }) =>\n      children ?? (showCancelButton ? <Square /> : <ArrowUp />)\n    }\n  </BaseComponent.SubmitButton>\n);\n\n// Error\nconst Error = ({ className }) => (\n  <BaseComponent.Error className={cn(\"text-sm text-destructive\", className)} />\n);\n\n// Staged images - base pre-computes props array, just iterate\nconst StagedImages = ({ className }) => (\n  <BaseComponent.StagedImages className={cn(\"flex gap-2\", className)}>\n    {({ images }) =>\n      images.map((imageProps) => (\n        <ImageBadge key={imageProps.image.id} {...imageProps} />\n      ))\n    }\n  </BaseComponent.StagedImages>\n);\n```\n\n### Step 6: Final Verification\n\n```\nFinal Checks:\n- [ ] No duplicate context creation\n- [ ] No duplicate SDK hooks in root wrappers\n- [ ] No duplicate state management or event handlers\n- [ ] Base namespace imported and `Base.Root` used as wrapper\n- [ ] `data-*` classes used for styling (with `group-data-*` for children)\n- [ ] Render props used only for rendering behavior changes\n- [ ] Base sub-components wrapped with styling\n- [ ] Icon factories passed from styled layer to base hooks\n- [ ] Visual sub-components and CSS variants stay in styled layer\n```\n\n## What Belongs in Styled Layer\n\n### Icon Factories\n\nWhen base hooks need icons, pass a factory function:\n\n```tsx\n// Base hook accepts optional icon factory\nexport function useCombinedResourceList(\n  providers: ResourceProvider[] | undefined,\n  search: string,\n  createMcpIcon?: (serverName: string) => React.ReactNode,\n) {\n  /* ... */\n}\n\n// Styled layer provides the factory\nconst resources = useCombinedResourceList(providers, search, (serverName) => (\n  <McpServerIcon name={serverName} className=\"w-4 h-4\" />\n));\n```\n\n### CSS Variants\n\n```tsx\nconst inputVariants = cva(\"w-full\", {\n  variants: {\n    variant: {\n      default: \"\",\n      solid: \"[&>div]:shadow-xl [&>div]:ring-1\",\n      bordered: \"[&>div]:border-2\",\n    },\n  },\n});\n```\n\n### Layout Logic, Visual Sub-Components, Custom Data Fetching\n\nThese all stay in the styled layer. Base handles behavior; styled handles presentation.\n\n## Type Handling\n\nHandle ref type differences between base and styled components:\n\n```tsx\n// Base context may have RefObject<T | null>\n// Styled component may need RefObject<T>\n<TextEditor ref={editorRef as React.RefObject<TamboEditor>} />\n```\n\n## Anti-Patterns\n\n- **Re-implementing base logic** - if base handles it, compose it\n- **Using render props for styling** - prefer `data-*` classes; render props are for behavior changes\n- **Duplicating context in wrapper** - use base Root which provides context\n- **Hardcoding icons in base hooks** - use factory functions to keep styling in styled layer\n",".claude/skills/api-resource-lifecycle/SKILL.md":"---\nname: api-resource-lifecycle\ndescription: Guides CRUD operations for API resources with cascading dependencies, descriptive validation, and orphan prevention. Use when adding delete/remove operations, creating validation logic, building resources that depend on other resources, or when the user mentions \"cascade delete\", \"orphan records\", \"duplicate detection\", \"validation errors\", \"resource cleanup\", or \"rollback on failure\".\nmetadata:\n  internal: true\n---\n\n# API Resource Lifecycle\n\nPatterns for building reliable CRUD operations in Tambo Cloud.\n\n## Gotchas\n\n- The codebase uses `CONFLICT` for duplicate name errors in skills but `BAD_REQUEST` for the same pattern in MCP servers. Always use `CONFLICT` for duplicates.\n- PostgreSQL unique violation code is `23505`. Catch it and map to a domain-specific exception rather than letting the raw DB error propagate.\n- When replacing a provider key, all skills with `externalSkillMetadata` for that provider must have their metadata cleared, or they'll reference a stale key.\n- Skills are silently skipped (not errored) at runtime when the provider doesn't support them. This is intentional -- don't add validation that blocks skill creation for unsupported providers.\n- `Promise.allSettled` (not `Promise.all`) for batch external API calls -- partial failures need cleanup, not an all-or-nothing abort.\n\n## Cascading Deletes\n\nDefault to `onDelete: \"cascade\"` in the schema. Only use manual transaction cascades when deletion requires external API calls, metadata cleanup, or cross-reference logic.\n\n```typescript\n// packages/db/src/schema.ts\nexport const skills = pgTable(\"skills\", {\n  id: text(\"id\").primaryKey(),\n  projectId: text(\"project_id\")\n    .notNull()\n    .references(() => projects.id, { onDelete: \"cascade\" }),\n  // ...\n});\n```\n\n### Manual cascades in transactions\n\nWhen deletion requires cleanup beyond FK cascades (external APIs, metadata, cross-references), wrap in a transaction:\n\n```typescript\n// packages/db/src/operations/project.ts\nexport async function deleteProject(db: HydraDb, id: string): Promise<boolean> {\n  return await db.transaction(async (tx) => {\n    await tx\n      .delete(schema.providerKeys)\n      .where(eq(schema.providerKeys.projectId, id));\n    await tx.delete(schema.apiKeys).where(eq(schema.apiKeys.projectId, id));\n    await tx\n      .delete(schema.projectMembers)\n      .where(eq(schema.projectMembers.projectId, id));\n    const deleted = await tx\n      .delete(schema.projects)\n      .where(eq(schema.projects.id, id))\n      .returning();\n    return deleted.length > 0;\n  });\n}\n```\n\n**Reference:** `packages/db/src/operations/project.ts` lines 255-278\n\n### Metadata cleanup on replacement\n\nWhen a resource is replaced (not deleted), clear dependent metadata so dependents re-sync under the new resource:\n\n```typescript\n// apps/web/server/api/routers/project.ts - addProviderKey\n// When replacing a provider key, clear skill metadata for that provider\nconst skills = await operations.listSkillsForProject(ctx.db, projectId);\nawait Promise.all(\n  skills\n    .filter((s) => s.externalSkillMetadata?.[providerName])\n    .map(async (s) => {\n      const { [providerName]: _, ...remaining } = s.externalSkillMetadata ?? {};\n      return operations.updateSkill(ctx.db, {\n        projectId,\n        skillId: s.id,\n        externalSkillMetadata: remaining,\n      });\n    }),\n);\n```\n\n**Reference:** `apps/web/server/api/routers/project.ts` lines 863-880\n\n### Rules\n\n- If a child record has no meaning without its parent, use `onDelete: \"cascade\"` in the schema\n- If deletion requires multi-step cleanup or external API calls, wrap in a transaction\n- When replacing a resource, clear dependent metadata so dependents re-sync\n- Always delete children before the parent in manual cascades\n- Check for affected dependents and document the cascade chain in code comments\n\n## Validation Errors\n\nEvery error must say what went wrong and what to do instead. Include the specific value that failed and an example of what's valid.\n\n```typescript\n// Zod: include format example\nname: z.string().min(1, \"Name is required\").max(64)\n  .regex(SKILL_NAME_PATTERN, \"Name must be kebab-case (e.g. scheduling-assistant)\"),\n\n// tRPC: include the conflicting value\nthrow new TRPCError({\n  code: \"CONFLICT\",\n  message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n});\n```\n\n### Error code mapping\n\n| Situation               | tRPC Code               | When to use                           |\n| ----------------------- | ----------------------- | ------------------------------------- |\n| Resource not found      | `NOT_FOUND`             | ID lookup returned null               |\n| Input validation failed | `BAD_REQUEST`           | Zod schema or business rule violation |\n| Duplicate resource      | `CONFLICT`              | Name/key already exists               |\n| Unexpected failure      | `INTERNAL_SERVER_ERROR` | Catch-all for unhandled errors        |\n\n## Duplicate Detection\n\nDefault to database unique constraints with custom exception mapping. Only use pre-creation queries when no DB constraint exists.\n\n```typescript\n// packages/db/src/operations/skills.ts\nconst PG_UNIQUE_VIOLATION = \"23505\";\nconst SKILLS_NAME_UNIQUE_CONSTRAINT = \"skills_project_id_name_idx\";\n\nexport class SkillNameConflictError extends Error {\n  constructor(name: string) {\n    super(`A skill named \"${name}\" already exists in this project`);\n    this.name = \"SkillNameConflictError\";\n  }\n}\n\nexport async function createSkill(\n  db: HydraDb,\n  data: NewSkill,\n): Promise<DBSkill> {\n  try {\n    const [skill] = await db.insert(schema.skills).values(data).returning();\n    return skill;\n  } catch (error) {\n    if (isSkillNameConflict(error)) {\n      throw new SkillNameConflictError(data.name);\n    }\n    throw error;\n  }\n}\n```\n\n### Pre-creation queries (fallback)\n\nWhen no unique DB constraint exists, query before inserting:\n\n```typescript\nconst existingKeys = await getExistingServerKeys(ctx.db, projectId);\nif (existingKeys.includes(serverKey)) {\n  throw new TRPCError({\n    code: \"CONFLICT\",\n    message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n  });\n}\n```\n\n**Reference:** `apps/web/server/api/routers/tools.ts` lines 119-126\n\n## Orphan Prevention\n\nWhen creating a resource that syncs to an external API, roll back on failure:\n\n```typescript\n// apps/web/server/api/routers/skills.ts\n// Create in DB first, then sync to provider\nconst skill = await operations.createSkill(ctx.db, { ... });\n\n// If provider sync fails, delete the DB record\ntry {\n  await createSkillOnProviderAndPersist(ctx.db, input.projectId, skill);\n} catch (error) {\n  await operations.deleteSkill(ctx.db, input.projectId, skill.id);\n  throw error;\n}\n```\n\n**Rules:**\n\n- Create the DB record first (gives you an ID for the external API call)\n- If the external sync fails, delete the DB record to avoid orphans\n- The user sees an error and can retry, rather than seeing a broken record\n- For batch operations, use `Promise.allSettled` and clean up partial failures\n\n**Reference:** `apps/web/server/api/routers/skills.ts` lines 195-204\n\n## Checklist\n\nWhen building a new CRUD operation:\n\n```\nResource Lifecycle Checklist:\n- [ ] Delete cascades documented (which dependents are affected?)\n- [ ] Database-level cascades set up for simple parent-child FK relationships\n- [ ] Manual cascade logic wrapped in a transaction for complex cleanup\n- [ ] All Zod validation messages are descriptive with examples\n- [ ] TRPCError messages include the specific value that caused the error\n- [ ] Duplicate detection before creation (custom exception or pre-query)\n- [ ] Error codes are correct (CONFLICT for duplicates, NOT_FOUND for missing)\n- [ ] External API sync failures roll back the DB record\n- [ ] Resource replacement clears dependent metadata\n```\n",".claude/skills/compound-components/SKILL.md":"---\nname: building-compound-components\ndescription: Creates unstyled compound components that separate business logic from styles. Use when building headless UI primitives, creating component libraries, implementing Radix-style namespaced components, or when the user mentions \"compound components\", \"headless\", \"unstyled\", \"primitives\", or \"render props\".\nmetadata:\n  internal: true\n---\n\n# Building Compound Components\n\nCreate unstyled, composable React components following the Radix UI / Base UI pattern. Components expose behavior via context while consumers control rendering.\n\n## Project Rules\n\nThese rules are specific to this codebase and override general patterns.\n\n### Hooks Are Internal\n\nHooks are implementation details, not public API. **Never export hooks from the index.**\n\n```tsx\n// index.tsx - CORRECT\nexport const Component = {\n  Root: ComponentRoot,\n  Content: ComponentContent,\n};\nexport type { ComponentRootProps, ComponentContentRenderProps };\n\n// index.tsx - WRONG\nexport { useComponentContext }; // Don't export hooks\n```\n\nConsumers access state via **render props**, not hooks. When styled wrappers in the **same package** need hook access, import directly from the source file:\n\n```tsx\nimport { useComponentContext } from \"../base/component/component-context\";\n```\n\n### No Custom Data Fetching in Primitives\n\nBase components can use `@tambo-ai/react` SDK hooks (components require Tambo provider anyway). **Custom data fetching logic** (combining sources, external providers) belongs in the styled layer.\n\n```tsx\n// OK - SDK hooks in primitive\nconst Root = ({ children }) => {\n  const { value, setValue, submit } = useTamboThreadInput();\n  const { isIdle, cancel } = useTamboThread();\n  return <Context.Provider value={{ value, setValue, isIdle }}>{children}</Context.Provider>;\n};\n\n// WRONG - custom data fetching in primitive\nconst Textarea = ({ resourceProvider }) => {\n  const { data: mcpResources } = useTamboMcpResourceList(search);\n  const externalResources = useFetchExternal(resourceProvider);\n  const combined = [...mcpResources, ...externalResources];\n  return <div>{combined.map(...)}</div>;\n};\n```\n\n### Pre-computed Props Arrays for Collections\n\nWhen exposing collections via render props, **pre-compute all props in a memoized array** rather than providing a getter function.\n\n```tsx\n// AVOID - getter function pattern\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n  const getItemProps = (index: number) => ({\n    /* new object every call */\n  });\n  return children({ items: rawItems, getItemProps });\n};\n\n// PREFERRED - pre-computed array\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n\n  const items = React.useMemo<ItemRenderProps[]>(\n    () =>\n      rawItems.map((item, index) => ({\n        item,\n        index,\n        isSelected: selectedId === item.id,\n        onSelect: () => setSelectedId(item.id),\n        onRemove: () => removeItem(item.id),\n      })),\n    [rawItems, selectedId, removeItem],\n  );\n\n  return children({ items });\n};\n```\n\n## Workflow\n\nCopy this checklist and track progress:\n\n```\nCompound Component Progress:\n- [ ] Step 1: Create context file\n- [ ] Step 2: Create Root component\n- [ ] Step 3: Create consumer components\n- [ ] Step 4: Create namespace export (index.tsx)\n- [ ] Step 5: Verify all guidelines met\n```\n\n### Step 1: Create context file\n\n```\nmy-component/\n├── index.tsx\n├── component-context.tsx\n├── component-root.tsx\n├── component-item.tsx\n└── component-content.tsx\n```\n\nCreate a context with a null default and a hook that throws on missing provider:\n\n```tsx\n// component-context.tsx\nconst ComponentContext = React.createContext<ComponentContextValue | null>(\n  null,\n);\n\nexport function useComponentContext() {\n  const context = React.useContext(ComponentContext);\n  if (!context) {\n    throw new Error(\"Component parts must be used within Component.Root\");\n  }\n  return context;\n}\n\nexport { ComponentContext };\n```\n\n### Step 2: Create Root component\n\nRoot manages state and provides context. Use `forwardRef`, support `asChild` via Radix `Slot`, and expose state via data attributes:\n\n```tsx\n// component-root.tsx\nexport const ComponentRoot = React.forwardRef<\n  HTMLDivElement,\n  ComponentRootProps\n>(({ asChild, defaultOpen = false, children, ...props }, ref) => {\n  const [isOpen, setIsOpen] = React.useState(defaultOpen);\n  const Comp = asChild ? Slot : \"div\";\n\n  return (\n    <ComponentContext.Provider\n      value={{ isOpen, toggle: () => setIsOpen(!isOpen) }}\n    >\n      <Comp ref={ref} data-state={isOpen ? \"open\" : \"closed\"} {...props}>\n        {children}\n      </Comp>\n    </ComponentContext.Provider>\n  );\n});\nComponentRoot.displayName = \"Component.Root\";\n```\n\n### Step 3: Create consumer components\n\nChoose the composition pattern based on need:\n\n**Direct children** (simplest, for static content):\n\n```tsx\nconst Content = ({ children, className, ...props }) => {\n  const { data } = useComponentContext();\n  return (\n    <div className={className} {...props}>\n      {children}\n    </div>\n  );\n};\n```\n\n**Render prop** (when consumer needs internal state):\n\n```tsx\nconst Content = ({ children, ...props }) => {\n  const { data, isLoading } = useComponentContext();\n  const content =\n    typeof children === \"function\" ? children({ data, isLoading }) : children;\n  return <div {...props}>{content}</div>;\n};\n```\n\n**Sub-context** (for lists where each item needs own context):\n\n```tsx\nconst Steps = ({ children }) => {\n  const { reasoning } = useMessageContext();\n  return (\n    <StepsContext.Provider value={{ steps: reasoning }}>\n      {children}\n    </StepsContext.Provider>\n  );\n};\n\nconst Step = ({ children, index }) => {\n  const { steps } = useStepsContext();\n  return (\n    <StepContext.Provider value={{ step: steps[index], index }}>\n      {children}\n    </StepContext.Provider>\n  );\n};\n```\n\n### Step 4: Create namespace export\n\n```tsx\n// index.tsx\nexport const Component = {\n  Root: ComponentRoot,\n  Trigger: ComponentTrigger,\n  Content: ComponentContent,\n};\n\n// Re-export types only - never hooks\nexport type { ComponentRootProps } from \"./component-root\";\nexport type { ComponentContentProps } from \"./component-content\";\n```\n\n### Step 5: Verify guidelines\n\n- **No styles in primitives** - consumers control all styling via className/props\n- **Data attributes for CSS** - expose state like `data-state=\"open\"`, `data-disabled`, `data-loading`\n- **Support asChild** - let consumers swap the underlying element via Radix `Slot`\n- **Forward refs** - always use `forwardRef`\n- **Display names** - set for DevTools (`Component.Root`, `Component.Item`)\n- **Throw on missing context** - fail fast with clear error messages\n- **Export types** - consumers need `ComponentProps`, `RenderProps` interfaces\n- **Hooks stay internal** - never export from index, expose state via render props\n- **SDK hooks OK, custom fetching not** - `@tambo-ai/react` hooks are fine, combining logic goes in styled layer\n- **Pre-compute collection props** - use `useMemo` arrays, not getter functions\n\n## Pattern Selection\n\n| Scenario             | Pattern         | Why                             |\n| -------------------- | --------------- | ------------------------------- |\n| Static content       | Direct children | Simplest, most flexible         |\n| Need internal state  | Render prop     | Explicit state access           |\n| List/iteration       | Sub-context     | Each item gets own context      |\n| Element polymorphism | asChild         | Change underlying element       |\n| CSS-only styling     | Data attributes | No JS needed for style variants |\n\n## Anti-Patterns\n\n- **Hardcoded styles** - primitives should be unstyled\n- **Prop drilling** - use context instead\n- **Missing error boundaries** - throw when context is missing\n- **Inline functions in render prop types** - define proper interfaces\n- **Default exports** - use named exports in namespace object\n- **Exporting hooks** - hooks are internal; expose state via render props\n- **Custom data fetching in primitives** - SDK hooks are fine, but combining/external fetching belongs in styled layer\n- **Re-implementing base logic** - styled wrappers should compose, not duplicate\n- **Getter functions for collections** - pre-compute props arrays in useMemo instead\n",".claude/skills/validating-accessibility/SKILL.md":"---\nname: validating-accessibility\ndescription: >-\n  Use this skill when creating, modifying, or reviewing any .tsx component in apps/web, even if\n  the user doesn't mention \"accessibility.\" Covers semantic HTML, aria labels, navigation landmarks,\n  forms, dialogs, and keyboard navigation. Trigger on: adding buttons, links, toggles, icons, or\n  any interactive element; building or editing forms; adding dialogs or modals; reviewing UI code.\n  Includes inline verification patterns for scanning violations. Not for styling or layout changes\n  that don't involve interactive elements.\nmetadata:\n  internal: true\n---\n\n# Accessibility Checklist\n\nEvery UI component in `apps/web` must meet these standards. No partial compliance.\n\n## Gotchas\n\n- **`role=\"button\"` divs may exist in the codebase** -- fix them when touching affected files. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n- **Nested interactive elements** -- when replacing a `<div role=\"button\">` that contains a child `<button>` (e.g., a copy button inside a collapsible toggle), do not just swap the outer div to `<button>`. That creates invalid nested buttons. Instead, restructure into sibling elements: a toggle `<button>` and a separate action `<button>` side by side in a flex container.\n- **Standalone inputs outside react-hook-form need manual ID pairing** -- use `useId()` with `htmlFor`/`id`. The shadcn `<FormField>` handles this automatically, but raw `<Input>` does not.\n- **AlertDialog vs Dialog** -- use `AlertDialog` for destructive confirmations (requires `AlertDialogTitle` + `AlertDialogDescription`). Use `Dialog` for content/forms. Never build custom modal overlays.\n- **Icon-only buttons without `aria-label`** are common in new code. Every icon-only button needs one, and it must include context: `Delete API key ${keyName}`, not just \"Delete\".\n\n## Semantic HTML\n\nUse native elements. Never recreate `<button>` behavior with `<div role=\"button\">` + keyboard handlers.\n\n| Interaction      | Element                                                |\n| ---------------- | ------------------------------------------------------ |\n| Clickable action | `<button>` or `<Button>` from `@/components/ui/button` |\n| Navigation link  | `<Link>` (Next.js) or `<a>`                            |\n| Navigation group | `<nav>` with descriptive `aria-label`                  |\n| Item list        | `<ul>`/`<ol>` + `<li>`                                 |\n| Section heading  | `<h1>`-`<h6>` in order, never skip levels              |\n\n## Aria Labels\n\nEvery interactive element without visible text needs `aria-label` with both action AND target:\n\n```tsx\n<Button size=\"icon\" aria-label={`Delete API key ${keyName}`}>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n\n<Switch aria-label={`${enabled ? \"Disable\" : \"Enable\"} skill ${skillName}`} />\n```\n\nPrefer state-aware labels (\"Copied!\" vs \"Copy\"). Buttons with visible text skip `aria-label`.\n\n**Reference implementations:** `copy-button.tsx` (state-aware), `context-attachment-badge.tsx` (contextual remove), `thread-table-header.tsx` (sort state) -- all in `apps/web/components/`.\n\n## Navigation Landmarks\n\nWrap navigation groups in `<nav>` with a unique `aria-label` per region on the page.\n\n## Forms\n\nUse shadcn Form components from `@/components/ui/form` (`FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormMessage`). They handle ID generation, label association, `aria-describedby`, and `aria-invalid` automatically.\n\nFor standalone inputs outside react-hook-form, pair `useId()` with `htmlFor`/`id`. Never use placeholder as label substitute.\n\n## Keyboard Navigation\n\n- Only `tabIndex={0}` or `tabIndex={-1}` (never positive values)\n- Never remove focus outlines\n- Prefer `<button>` over manual Enter/Space handlers\n\n## Verification\n\nScan `apps/web/components` for common violations. For each check, grep for the pattern and fix any matches found.\n\n### Check 1: `role=\"button\"` on non-button elements\n\nSearch for `role=\"button\"` in `.tsx` files. Flag `<div` or `<span` elements with this attribute; they should be `<button>` or `<Button>` instead. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n\n**Pattern:** `role=\"button\"`\n\n### Check 2: `<div onClick>` patterns\n\nSearch for `<div` elements with `onClick` handlers. These should use `<button>` instead for proper keyboard support.\n\n**Pattern:** `<div[^>]*onClick`\n\n### Check 3: Positive tabIndex values\n\nSearch for `tabIndex` with values greater than 0. Only `tabIndex={0}` and `tabIndex={-1}` are allowed.\n\n**Pattern:** `tabIndex={[1-9]`\n\n### Check 4: Icon buttons missing aria-label\n\nSearch for `size=\"icon\"` in `.tsx` files. For each match, check surrounding lines (5-10 above and below) for `aria-label` on the same `<Button>` element or an `sr-only` span. Flag buttons that have neither.\n\n**Pattern:** `size=\"icon\"` without nearby `aria-label`\n\n### Manual checks\n\nThese cannot be detected by pattern matching:\n\n- [ ] Form inputs have associated `<label>` elements\n- [ ] Navigation groups use `<nav>` with unique `aria-label`\n- [ ] Dialogs use Radix-based components (AlertDialog or Dialog)\n- [ ] Focus outlines intact\n",".claude-plugin/marketplace.json":"{\n  \"name\": \"tambo-marketplace\",\n  \"owner\": {\n    \"name\": \"Tambo AI\",\n    \"email\": \"support@tambo.co\"\n  },\n  \"metadata\": {\n    \"description\": \"Official Tambo plugins for Claude Code\",\n    \"homepage\": \"https://tambo.co\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"tambo\",\n      \"source\": \"./plugins/tambo\",\n      \"description\": \"Build agents that speak your UI\",\n      \"version\": \"1.0.0\",\n      \"author\": {\n        \"name\": \"Tambo AI\",\n        \"email\": \"support@tambo.co\"\n      },\n      \"category\": \"frameworks\",\n      \"keywords\": [\"ai\", \"react\", \"generative-ui\", \"components\", \"streaming\"]\n    }\n  ]\n}\n",".claude/skills/building-settings-ui/SKILL.md":"---\nname: building-settings-ui\ndescription: >-\n  Use this skill when adding or modifying settings UI in Tambo Cloud. Covers where a new settings\n  section belongs (Agent tab vs Settings tab), and the component patterns used across both pages\n  (card layout, toasts, confirmation dialogs, destructive styling, save behavior conventions).\n  Triggers on \"add a new settings section\", \"where should X go?\", \"settings UI\", \"settings page\",\n  \"agent page\", or any work touching apps/web/components/dashboard-components/project-details/,\n  project-settings.tsx, or agent-settings.tsx.\n  Not for full-stack feature building (DB, tRPC, tests); those patterns will get their own skills.\nmetadata:\n  internal: true\n---\n\n# Building Settings UI\n\nGuide for placing and styling settings sections in the Tambo Cloud dashboard. Covers two concerns: where a feature belongs (which tab/page), and how to build the UI component to match existing patterns.\n\n## Architecture\n\nSettings are split across two top-level tabs in the project layout:\n\n- **Agent tab** (`/[projectId]/agent`) - How the AI agent behaves\n- **Settings tab** (`/[projectId]/settings`) - Project infrastructure and access\n\nEach tab renders a flat vertical stack of Card components. There is no sidebar navigation; each page is short enough to scroll naturally.\n\n### Tab layout\n\n```\nOverview | Observability | Agent | Settings\n```\n\n- Layout file: `apps/web/app/(authed)/(dashboard)/[projectId]/layout.tsx`\n- Agent page: `apps/web/app/(authed)/(dashboard)/[projectId]/agent/page.tsx`\n- Settings page: `apps/web/app/(authed)/(dashboard)/[projectId]/settings/page.tsx`\n\n## Gotchas\n\n1. **Do not add a new top-level tab** without explicit team alignment. Current tabs (Overview, Observability, Agent, Settings) have been stable.\n2. **`EditWithTamboButton` goes inside `CardTitle`**, not as a sibling of `CardHeader`. It must have a `description` prop explaining what the section configures.\n3. **Invalidate the query before toasting** in `onSuccess`. Reversing the order can show a success toast while the UI still displays old data.\n4. **Use `DeleteConfirmationDialog`**, never inline `AlertDialog` for destructive confirmations.\n5. **Use `text-destructive` semantic color**, never `text-red-500`. Cancel/discard buttons are NOT destructive.\n\n---\n\n## Feature Placement\n\n### Agent Tab Sections\n\n| #   | Section             | What it configures                                 | Component                        |\n| --- | ------------------- | -------------------------------------------------- | -------------------------------- |\n| 1   | Model               | Provider + model selection, API key, custom params | `provider-key-section.tsx`       |\n| 2   | Custom Instructions | System prompt, prompt override toggle              | `custom-instructions-editor.tsx` |\n| 3   | Skills              | Skill definitions and imports                      | `skills-section.tsx`             |\n| 4   | Tool Call Limit     | Max tool calls per response                        | `tool-call-limit-editor.tsx`     |\n| 5   | MCP                 | MCP server URLs + headers                          | `available-mcp-servers.tsx`      |\n\n**Container:** `apps/web/components/dashboard-components/agent-settings.tsx`\n\n### Settings Tab Sections\n\n| #   | Section        | What it configures             | Component                  |\n| --- | -------------- | ------------------------------ | -------------------------- |\n| 1   | Name           | Project display name           | `project-name-section.tsx` |\n| 2   | API Keys       | API key list + create          | `api-key-list.tsx`         |\n| 3   | Authentication | OAuth mode, token requirements | `oauth-settings.tsx`       |\n| 4   | Danger Zone    | Project deletion               | `danger-zone-section.tsx`  |\n\n**Container:** `apps/web/components/dashboard-components/project-settings.tsx`\n\nAll section components live in `apps/web/components/dashboard-components/project-details/`.\n\n### Placement Decision Tree\n\n1. **Configures AI agent behavior?** (model selection, prompts, tools, memory, context) -> **Agent tab**\n2. **Configures project infrastructure?** (API keys, naming, deletion, billing, webhooks) -> **Settings tab**\n3. **Configures who can access?** (auth, tokens, team members, permissions) -> **Settings tab**\n4. **Monitoring or debugging view?** -> **Observability tab**\n5. **High-level summary or status?** -> **Overview tab**\n6. **None of the above?** -> Ask the user.\n\n### Conditional and Dependent Settings\n\nSome settings only apply when another setting is in a specific state. Follow these patterns:\n\n**Show but warn (soft dependency).** The section renders normally but displays an `Alert` when the dependency isn't met. The user can still see and configure the setting. Use this when the feature exists but won't work at runtime.\n\nExample: Skills section shows a provider compatibility notice when the selected provider doesn't support skills:\n\n```tsx\n// skills-section.tsx\nconst isProviderSupported = SKILLS_SUPPORTED_PROVIDERS.has(\n  defaultLlmProviderName,\n);\n// Renders full skills UI + warning Alert if !isProviderSupported\n```\n\n**Conditionally pass props (data dependency).** The parent reads one setting and passes it as a prop so the child can adapt its behavior. Use this when the child's content or options change based on the parent's state.\n\nExample: MCP servers section receives `providerType` to toggle agent-mode-specific UI:\n\n```tsx\n// agent-settings.tsx\n<AvailableMcpServers providerType={projectData?.providerType} />;\n// available-mcp-servers.tsx\nconst isAgentMode = providerType === AiProviderType.AGENT;\n```\n\nExample: Custom LLM parameters change available suggestions based on provider and model:\n\n```tsx\n// provider-key-section.tsx passes selectedProvider to the parameter editor\n<CustomLlmParametersEditor selectedProvider={selectedProvider} />\n```\n\n**Rules for new dependent settings:**\n\n1. Never hide a section entirely based on another setting's state. Always render the card; use an Alert or disabled state to communicate the dependency.\n2. The warning message must name the dependency and tell the user what to change (e.g., \"Switch to a supported provider to enable skills\").\n3. Keep dependency checks in the section component, not the container. The container (`agent-settings.tsx`, `project-settings.tsx`) should pass data, not make visibility decisions.\n4. If a setting depends on state from a different tab, pass it through the shared project query (`api.project.getProject`) rather than cross-tab state.\n\n### Adding a New Section\n\n1. **Create the component** in `project-details/` following the Card layout pattern below.\n2. **Import and render** in the correct container (`agent-settings.tsx` or `project-settings.tsx`).\n3. **Update the skeleton** in `settings-skeletons.tsx` (either `AgentPageSkeleton` or `SettingsPageSkeleton`).\n\n---\n\n## Component Patterns\n\n### Card Layout\n\nEvery settings section uses `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardContent` from `@/components/ui/card`.\n\n```tsx\n<Card>\n  <CardHeader>\n    <CardTitle className=\"text-lg font-semibold\">\n      Section Name\n      <EditWithTamboButton description=\"Configure section settings...\" />\n    </CardTitle>\n    <CardDescription className=\"text-sm font-sans text-foreground\">\n      Description of what this section does.\n    </CardDescription>\n  </CardHeader>\n  <CardContent className=\"space-y-4\">{/* Content */}</CardContent>\n</Card>\n```\n\n### Toast Notifications\n\nEvery mutation shows a toast on both success and error. Import `useToast` from `@/hooks/use-toast`.\n\n```tsx\nconst mutation = api.someRoute.someMutation.useMutation({\n  onSuccess: async () => {\n    await utils.someRoute.someQuery.invalidate();\n    toast({ title: \"Success\", description: \"Setting updated successfully\" });\n  },\n  onError: () => {\n    toast({\n      title: \"Error\",\n      description: \"Failed to update setting\",\n      variant: \"destructive\",\n    });\n  },\n});\n```\n\nNever skip the error toast.\n\n### Confirmation Dialogs\n\nAll destructive actions use `DeleteConfirmationDialog` from `@/components/dashboard-components/delete-confirmation-dialog`:\n\n```tsx\nconst [alertState, setAlertState] = useState<{\n  show: boolean;\n  title: string;\n  description: string;\n  data?: { id: string };\n}>({ show: false, title: \"\", description: \"\" });\n\n<DeleteConfirmationDialog\n  mode=\"single\"\n  alertState={alertState}\n  setAlertState={setAlertState}\n  onConfirm={handleConfirmDelete}\n/>;\n```\n\nTitle includes the item name (`Delete \"${name}\"?`). Description warns the action cannot be undone.\n\n### Destructive Action Styling\n\n```tsx\n<Button\n  variant=\"ghost\"\n  size=\"icon\"\n  className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n```\n\nUse `Trash2` from `lucide-react`. Use `hover:bg-destructive/10` for ghost variant hover.\n\n### Save Behavior\n\n**Toggles: Immediate save.** `onCheckedChange` fires the mutation directly. Include `aria-label` with state context.\n\n**Form fields: Edit/Save/Cancel.** Track `isEditing`, `savedValue`, and `displayValue` state. Cancel reverts to `savedValue`. Save button disabled during mutation, shows \"Saving...\". `autoFocus` on first input when entering edit mode.\n\n**Reference implementations:** `custom-instructions-editor.tsx` (edit/save/cancel), `tool-call-limit-editor.tsx` (simpler form), `project-name-section.tsx` (basic edit/save/cancel).\n\n### Danger Zone Pattern\n\nFor irreversible destructive actions, use the Danger Zone card pattern:\n\n```tsx\n<Card className=\"border-destructive/50\">\n  <CardHeader>\n    <CardTitle>Danger Zone</CardTitle>\n    <CardDescription>Warning about permanence.</CardDescription>\n  </CardHeader>\n  <CardContent>\n    <Button\n      variant=\"ghost\"\n      className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n      aria-label=\"Delete this project\"\n    >\n      Delete this project\n    </Button>\n  </CardContent>\n</Card>\n```\n\nThe `DeleteConfirmationDialog` should be owned by the parent component that handles the mutation and post-delete navigation.\n","plugins/tambo/skills/generative-ui/SKILL.md":"---\nname: generative-ui\ndescription: Creates a new Tambo generative UI app from scratch. Scaffolds with tambo create-app, wires TamboProvider, registers starter components. Triggers on \"new Tambo app\", \"create a generative UI app\", \"build an AI app from scratch\", \"start a new project with Tambo\". For existing apps, use building-with-tambo.\n---\n\n# Generative UI\n\nBuild generative UI apps with Tambo — create rich, interactive React components from natural language.\n\n## Reference Guides\n\nLoad these when you need deeper implementation details beyond the bootstrap flow:\n\n- [Components](references/components.md) - **Load when creating custom components.** Generative vs interactable, propsSchema, ComponentRenderer.\n- [Component Rendering](references/component-rendering.md) - Streaming props, loading states, persistent state. Load when customizing rendering.\n- [Threads and Input](references/threads.md) - **Load when building custom chat UI.** useTambo(), useTamboThreadInput(), userKey/userToken auth, suggestions, voice.\n- [Tools and Context](references/tools-and-context.md) - **Load when adding tools or MCP.** defineTool(), MCP servers, contextHelpers.\n- [CLI Reference](references/cli.md) - **Load for `tambo add` components.** Component library, non-interactive flags, exit codes.\n- [Skills](references/skills.md) - **Mention as a next step after setup.** Project-scoped agent skills via CLI and dashboard.\n\nThese shared references are duplicated from building-with-tambo so each skill works independently.\n\n## One-Prompt Flow\n\nThe goal is to get the user from zero to a running app in a single prompt. Ask all questions upfront using AskUserQuestion with multiple questions, then execute everything without stopping.\n\n### Step 1: Gather All Non-Sensitive Preferences (Single AskUserQuestion Call)\n\nUse AskUserQuestion with up to 3 questions in ONE call. Authentication is handled by the CLI in a later step.\n\n**Question 1: What do you want to build?**\n\nAsk the user what kind of app they're building. This drives which starter components to create. Examples: \"a dashboard\", \"a chatbot\", \"a data visualization tool\", \"a task manager\". If the user already said what they want in their initial message, skip this question.\n\n**Question 2: Framework**\n\nOptions:\n\n- Next.js (Recommended) - Full-stack React with App Router\n- Vite - Fast, lightweight React setup\n\n**Question 3: App name**\n\nLet the user pick a name for their project directory. Default suggestion: derive from what they want to build (e.g., \"my-dashboard\", \"my-chatbot\"). Use kebab-case (letters, numbers, hyphens only). If the user gives a non-slug name like \"Sales Dashboard\", propose `sales-dashboard` instead.\n\n**Skip questions when the user already told you the answer.** If they said \"build me a Next.js dashboard app called analytics\", you already know the framework, the app idea, and the name.\n\n### Step 2: Execute Everything (No Stopping)\n\nRun all of these sequentially without asking for confirmation between steps. If any command fails, stop the flow, surface the error, and ask the user how to proceed — do not continue to later steps.\n\nAll templates (`standard`, `vite`, `analytics`, `expo`) come with chat UI, TamboProvider wiring, component registry, and starter components already included. You do NOT need to add chat UI or wire up the app — just scaffold, configure the API key, add custom components, and start the server.\n\n#### 2a. Scaffold the project\n\nFor Next.js (recommended):\n\n```bash\nnpx tambo create-app <app-name> --template=standard --skip-tambo-init\ncd <app-name>\n```\n\nFor Vite:\n\n```bash\nnpx tambo create-app <app-name> --template=vite --skip-tambo-init\ncd <app-name>\n```\n\nUse `--skip-tambo-init` since `create-app` normally tries to run `tambo init` interactively, which won't work in non-interactive environments like coding agents. We handle authentication in the next step.\n\n#### 2b. Authenticate and initialize Tambo\n\n```bash\nnpx tambo init --project-name=<app-name>\n```\n\nThis opens the browser for authentication and polls until the user completes auth (up to 15 minutes). Use a long timeout (at least 15 minutes) when running this command. Once auth completes, the CLI creates the project and writes the API key to `.env.local` with the correct env var for the framework (`NEXT_PUBLIC_TAMBO_API_KEY`, `VITE_TAMBO_API_KEY`, etc.).\n\n**IMPORTANT:** Do NOT ask the user to paste an API key manually. Always use the CLI auth flow.\n\n#### 2c. Create custom starter components\n\nThe template includes basic components, but add 1-2 components tailored to what the user wants to build. Don't use generic examples:\n\n- **Dashboard app** → `StatsCard`, `DataTable`\n- **Chatbot** → `BotResponse` with markdown support\n- **Data visualization** → `Chart` with configurable data\n- **Task manager** → `TaskCard`, `TaskBoard`\n- **Generic / unclear** → `ContentCard`\n\nEach component needs:\n\n1. A Zod schema with `.describe()` on every field\n2. The React component itself\n3. Registration in the existing component registry (`lib/tambo.ts` — add to the existing `components` array, don't replace it)\n\n**Schema constraints — Tambo will reject invalid schemas at runtime:**\n\n- **No `z.record()`** — Record types (objects with dynamic keys) are not supported anywhere in the schema, including nested inside arrays or objects. Use `z.object()` with explicit named keys instead.\n- **No `z.map()` or `z.set()`** — Use arrays and objects instead.\n- For tabular data like rows, use `z.array(z.object({ col1: z.string(), col2: z.number() }))` with explicit column keys — NOT `z.array(z.record(z.string(), z.unknown()))`.\n\n**React best practices for generated components:**\n\n- Always add unique `key` props when rendering lists (`.map()`). Use a unique field from the data (like `id`) — not the array index.\n- Include an `id` field (e.g., `z.string().describe(\"Unique identifier\")`) in schemas for array items so there's always a stable key available.\n\nExample:\n\n```tsx\n// src/components/StatsCard.tsx\nimport { z } from \"zod/v4\";\n\nexport const StatsCardSchema = z.object({\n  title: z.string().describe(\"Metric name\"),\n  value: z.number().describe(\"Current value\"),\n  change: z.number().optional().describe(\"Percent change from previous period\"),\n  trend: z.enum([\"up\", \"down\", \"flat\"]).optional().describe(\"Trend direction\"),\n});\n\ntype StatsCardProps = z.infer<typeof StatsCardSchema>;\n\nexport function StatsCard({\n  title,\n  value,\n  change,\n  trend = \"flat\",\n}: StatsCardProps) {\n  // ... implementation with Tailwind styling\n}\n```\n\nThen add to the existing registry in `lib/tambo.ts`:\n\n```tsx\n// Add to the existing components array — don't replace what's already there\n// Next.js: import { StatsCard, StatsCardSchema } from \"@/components/StatsCard\";\n// Vite: import { StatsCard, StatsCardSchema } from \"../components/StatsCard\";\nimport { StatsCard, StatsCardSchema } from \"@/components/StatsCard\";\n\n// ... existing components ...\n{\n  name: \"StatsCard\",\n  component: StatsCard,\n  description: \"Displays a metric with value and trend. Use when user asks about stats, metrics, or KPIs.\",\n  propsSchema: StatsCardSchema,\n},\n```\n\n#### 2d. Start the dev server\n\nOnly start the dev server after all code changes (scaffolding, init, component creation, registry updates) are complete.\n\n```bash\nnpm run dev\n```\n\nRun this in the background so the user can see their app immediately.\n\n### Step 3: Summary\n\nAfter everything is running, give a brief summary:\n\n- What was set up\n- What components were created and what they do\n- The URL where the app is running (typically `http://localhost:3000` for Next.js, `http://localhost:5173` for Vite)\n- If auth was skipped: remind them once to run `npx tambo init` to authenticate\n- A suggestion for what to try first (e.g., \"Try asking it to show you a stats card for monthly revenue\")\n\n## Technology Stacks Reference\n\n### Recommended Stack (Default)\n\n```\nNext.js 14+ (App Router)\n├── TypeScript\n├── Tailwind CSS\n├── Zod (for schemas)\n└── @tambo-ai/react\n```\n\n```bash\nnpx tambo create-app my-app --template=standard\n```\n\n### Vite Stack\n\n```\nVite + React\n├── TypeScript\n├── Tailwind CSS\n├── Zod\n└── @tambo-ai/react\n```\n\n### Minimal Stack (No Tailwind)\n\n```\nVite + React\n├── TypeScript\n├── Plain CSS\n├── Zod\n└── @tambo-ai/react\n```\n\n## Component Registry Pattern\n\nEvery generative component must be registered:\n\n```tsx\nimport { TamboComponent } from \"@tambo-ai/react\";\nimport { ComponentName, ComponentNameSchema } from \"@/components/ComponentName\";\n\nexport const components: TamboComponent[] = [\n  {\n    name: \"ComponentName\",\n    component: ComponentName,\n    description: \"What it does. When to use it.\",\n    propsSchema: ComponentNameSchema,\n  },\n];\n```\n\nKey rules:\n\n- **propsSchema**: Zod object with `.describe()` on every field — this is how the AI knows what to pass\n- **description**: Tell the AI when to use this component — be specific about trigger phrases\n- **Streaming**: Props arrive incrementally, so handle undefined gracefully (optional fields or defaults)\n\n## Adding More Chat UI (Optional)\n\nTemplates already include chat UI. These are only needed if the user wants additional UI primitives beyond what the template provides:\n\n```bash\nnpx tambo add message-thread-full --yes    # Complete chat interface\nnpx tambo add control-bar --yes            # Controls and actions\nnpx tambo add thread-history --yes         # Conversation history sidebar\n```\n\n## Supported Technologies\n\n| Technology       | Support Level | Notes                             |\n| ---------------- | ------------- | --------------------------------- |\n| Next.js 14+      | Full          | Recommended, App Router preferred |\n| Vite             | Full          | Great for SPAs                    |\n| Create React App | Partial       | Works but CRA is deprecated       |\n| Remix            | Partial       | Works with client components      |\n| TypeScript       | Full          | Strongly recommended              |\n| JavaScript       | Full          | Works but less type safety        |\n| Tailwind CSS     | Full          | Default for CLI components        |\n| Plain CSS        | Full          | Need custom component styling     |\n| CSS Modules      | Full          | Supported                         |\n| Zod              | Required      | Used for all schemas              |\n\n## Verification\n\nHave the user verify the app works by:\n\n1. Opening the app URL in a browser\n2. Typing a prompt that should trigger one of the registered components (e.g., \"Show me a stats card for monthly revenue\")\n3. Verifying the component renders with AI-generated props\n\nIf something doesn't work:\n\n- Check the registry includes the component\n- Check the description matches the prompt\n- Check the dev server has no console errors\n\n## Reporting Bugs & Feedback\n\nIf you encounter any of these while helping a user, suggest filing a GitHub issue:\n\n- A bug in `@tambo-ai/react`, `@tambo-ai/client`, or the `tambo` CLI\n- Documentation that contradicts actual behavior\n- Missing or misleading instructions in this skill\n\n### Issue Template\n\nUse this template when drafting an issue for `tambo-ai/tambo`:\n\n````markdown\n**Title:** [Short description of the problem]\n\n**Expected behavior**\nWhat should happen.\n\n**Actual behavior**\nWhat happens instead, including any error messages or stack traces.\n\n**Repro steps**\n\n1. Run `npx tambo create-app ...` (or whatever command)\n2. Add this code:\n\n```tsx\n// minimal code that reproduces the issue\n```\n\n3. Observe the error\n\n**Environment**\n\n- `@tambo-ai/react` version:\n- `@tambo-ai/client` version:\n- Framework (Next.js / Vite / CRA) and version:\n- Node.js version:\n- OS:\n\n**Additional context**\nLink to relevant docs or skill file path if applicable.\n````\n\n**Security:** Redact API keys, tokens, and any customer data before including logs or code snippets in the issue.\n\n### Suggesting an Issue to the User\n\nWhen you hit a problem that looks like a Tambo bug, say something like:\n\n> This looks like a bug in `@tambo-ai/react`. Want me to open a GitHub issue on `tambo-ai/tambo` with the repro steps and environment details?\n\nAlways wait for the user to confirm before filing.\n",".github/AGENTS.md":"# AGENTS.md\n\nGuidance for agents working in `.github/` (GitHub Actions workflows and composite actions). This file is referenced from the root [`AGENTS.md`](../AGENTS.md).\n\n## GitHub Actions\n\nWhen creating or modifying GitHub Actions workflows:\n\n- **Pin actions to full commit SHA** with a version comment for security and reproducibility:\n\n  ```yaml\n  # Good - pinned to SHA with version comment\n  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2\n\n  # Bad - unpinned version tag\n  - uses: actions/checkout@v4\n  ```\n\n- **Look up the SHA** from the action's releases page (e.g., https://github.com/actions/checkout/releases)\n- **Include the version in a comment** so humans can understand what version is pinned\n- **Local actions** (`./.github/actions/*`) don't need pinning since they're in the repo\n","CLAUDE.md":"# CLAUDE.md\n\nGuidelines for Claude Code (claude.ai/code) when touching this repo.\n\n**Read @AGENTS.md first.** It owns architecture, naming, workflow rules, testing expectations, and anything code-related. Keep that file open—this doc just points you there.\n\n## Three Things to Remember\n\n1. Follow that doc for everything: repo layout, commands, coding standards, doc rules, Charlie workflow, MCP guidance, etc.\n2. Use the workspace scripts it lists (see below for key commands).\n3. Defer to it whenever instructions collide; if something's still unclear, ask the user.\n\n## Key Commands\n\n```bash\n# Development (two different apps)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261\nnpm run dev              # Start React SDK (showcase + docs)\n\n# Quality checks (run before commits)\nnpm run lint\nnpm run check-types\nnpm test\n\n# Database (requires -w flag)\nnpm run db:generate -w packages/db\nnpm run db:migrate -w packages/db\nnpm run db:studio -w packages/db\n\n# Docker (for PostgreSQL in local dev)\ndocker compose --env-file docker.env up postgres -d\n```\n\n## Documentation Structure\n\n- **CONTRIBUTING.md** - Dev setup and PR workflow for contributors\n- **SELF-HOSTING.md** - Self-hosting/deployment guide\n- **AGENTS.md** - Coding standards, architecture (this is the source of truth)\n","AGENTS.md":"# AGENTS.md\n\nDetailed guidance for Claude Code agents working with the Tambo AI monorepo.\n\nThis file provides comprehensive instructions for maintaining code quality, architectural consistency, and project-specific requirements across both the Tambo AI framework and the Tambo Cloud platform.\n\n## 1. Repository Structure\n\nThis is a Turborepo monorepo containing both the Tambo AI framework packages and the Tambo Cloud platform.\n\n### Framework Packages (Turborepo root)\n\n- **react-sdk/** - Main React SDK package (`@tambo-ai/react`)\n  - Core hooks, providers, and utilities for building AI-powered React apps\n  - Exports: hooks, providers, types for component registration and thread management\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`) for broad compatibility\n\n- **packages/client/** - Framework-agnostic client (`@tambo-ai/client`)\n  - Streaming, tool execution, thread management without React dependencies\n  - `TamboClient` class with `getState()`/`subscribe()` for framework integration\n  - `TamboStream` async iterable for streaming AI responses\n  - Used by `@tambo-ai/react` as its core engine; also usable standalone (Node.js, Vue, Svelte, etc.)\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`)\n\n- **cli/** - Command-line interface (`tambo`)\n  - Project scaffolding, component generation, and development utilities\n  - Component registry auto-syncs to `/showcase/src/components/tambo/` from `/cli/src/registry/`\n  - Built as ESM module with executable binary\n\n- **showcase/** - Demo application (`@tambo-ai/showcase`)\n  - Runs on port 8262\n  - Next.js app demonstrating all Tambo components and patterns\n  - Components auto-synced from CLI registry - edit CLI registry, not showcase components directly\n  - Serves as both documentation and testing ground\n\n- **docs/** - Documentation site (`@tambo-ai/docs`)\n  - Runs on port 8263\n  - Built with Fumadocs, includes comprehensive guides and API reference\n  - This package contains ui components that originated from the cli/ package.\n    Any changes to the components should be made in the cli/ package first, and\n    then duplicated into this package.\n  - MDX-based content with interactive examples\n  - Integrated search and component documentation\n\n- **create-tambo-app/** - App bootstrapper (`create-tambo-app`)\n  - Initializes new Tambo projects from templates\n  - Handles git setup, dependency installation, and configuration\n\n- **community/** - Community resources and event materials\n- **packages/** - Shared configuration packages (ESLint, TypeScript configs)\n\n### Tambo Cloud Platform\n\n- **apps/web** - Next.js app (UI) - runs on port 8260\n- **apps/api** - NestJS app (OpenAPI server) - runs on port 8261\n- **packages/db** - Drizzle ORM schema + migrations + DB helpers\n- **packages/core** - Shared pure utilities (no DB access)\n- **packages/backend** - LLM/agent-side helpers\n- **packages/eslint-config, packages/typescript-config** - Shared tooling configs\n\n### Prerequisites\n\n- Node.js >=22\n- npm >=11\n\nIt is OK to use `crypto.randomUUID()` without a fallback in runtime and test code (Node.js >=22 and modern browsers).\n\n**Recommended:** Install [mise](https://mise.jdx.dev) for automatic version management. See [mise getting started](https://mise.jdx.dev/getting-started.html) for installation instructions.\n\n### Tool Versions\n\nTool versions are managed via mise. Source of truth files:\n\n- **Most tools**: `mise.toml`\n- **Node.js**: `.node-version` (`.nvmrc` kept in sync for nvm compatibility)\n\nThese files are kept up to date by Renovate.\n\n```bash\nmise install              # Install/update tools to correct versions\nmise exec -- <command>    # Preferred for scripts/CI/non-interactive shells\neval \"$(mise activate)\"   # Interactive shells only\n```\n\n**Changing tool versions**: Open a PR updating the authoritative version file(s). For Node.js, always update both `.node-version` and `.nvmrc` together. Run `mise install`, then verify with `npm run lint && npm run check-types && npm test`.\n\n**Local overrides**: Use `.mise.local.toml` (gitignored) for local-only changes. Only for additive or patch-level changes—don't override Node.js or use incompatible versions.\n\n## 2. Core Development Principles\n\n### Philosophy\n\n- **Move fast while maintaining high standards** - prioritize clarity and maintainability over cleverness.\n- **Read the relevant code first**; follow existing patterns and naming.\n- **Keep solutions small and simple**; favor functions over classes; avoid unnecessary abstractions.\n- **Simplify Relentlessly**: Remove complexity aggressively - the simplest design that works is usually best.\n- **Prefer immutability**. Don't mutate inputs; return new values. Use const, toSorted, object/array spreads.\n- **Handle errors up-front** with guard clauses and early returns.\n\n### Separation of Concerns\n\n- **Keep business logic separate from UI components**.\n- Extract business logic, calculations, and data transformations into separate files (`utils/`, `services/`, `lib/`).\n- UI components should orchestrate, not implement complex logic.\n- Makes testing easier and code more reusable.\n\n### Fail-Fast, No Fallbacks\n\n- **No Silent Fallbacks**: Code must fail immediately when expected conditions aren't met. Silent fallback behavior masks bugs and creates unpredictable systems.\n- **Explicit Error Messages**: When something goes wrong, stop execution with clear error messages explaining what failed and what was expected.\n- **Example**: `throw new Error(\\`Required model ${modelName} not found\\`)` instead of falling back to first available model.\n- **Data mapping**: When converting enums or union types, handle all known values explicitly and throw for unknown values. Don't use catch-all defaults that mask data integrity issues. Log warnings if skipping invalid data intentionally.\n\n### Naming Conventions\n\n- **File/dir naming**: kebab-case.\n- **Classes**: PascalCase.\n- **Vars/functions/methods**: camelCase.\n- **ENV vars**: UPPER_SNAKE_CASE.\n- **Use English**; meaningful names with widely-recognized standard abbreviations only (API, URL, ctx, req, res, next).\n- **Booleans**: start with is/has/can/should.\n- **Functions**: use verbs; boolean-returning: isX/hasX/canX. If a function returns void, prefer executeX/saveX naming.\n- **React-specific naming** (follows devdocs/NAMING_CONVENTIONS.md):\n  - Components: TamboXxx\n  - Hooks: useTamboXxx\n  - Props interfaces: TamboXxxProps\n  - Event props start with onX; internal handlers use handleX\n\n### Code Organization (Functions & Classes)\n\n- Keep functions short and single-purpose; ideally <20 statements.\n- Keep files focused and reasonably sized; ideally <200-300 lines.\n- Avoid `let` - instead make a new function that returns the value.\n- Avoid deep nesting: prefer early exits and extracting helpers. Use map/filter for iteration.\n- Prefer immutable data; use readonly and as const where applicable.\n- Favor composition over inheritance. If classes are used, keep them small (<200 statements, <10 properties/methods) and validate invariants internally.\n\n### Avoiding Over-Abstraction\n\n- **DRY is good, but don't go overboard** - sometimes a little duplication is better than the wrong abstraction.\n- **Rule of Three**: Wait until you have 3 instances of similar code before extracting a shared utility.\n- Premature abstraction creates coupling and makes changes harder.\n- It's easier to extract commonality later than to undo a bad abstraction.\n\n### Exports\n\n- Prefer named exports; allow multiple exports when they belong together (e.g., component + related types).\n- Avoid default exports.\n- Don't create `index.ts` barrels for internal modules; import directly from source files. Exception: package entry points (e.g., `packages/core/src/index.ts`) are fine.\n- Don't re-export symbols for backwards compatibility. When moving a symbol, update all consumers to import from the new location.\n- **Never use dynamic `import()`** for regular imports, even for type imports. Use static imports at the top of the file. Dynamic imports are only appropriate for code splitting in specific scenarios (e.g., lazy-loaded routes).\n\n## 3. TypeScript Standards\n\n### Type Safety\n\n- **Generally use strict TypeScript**: no any, no type assertions unless unavoidable; define precise types.\n- **Avoid `any`** - do your best to assign proper types.\n- **Use `unknown` instead of `any`** when type is truly uncertain, then narrow it down.\n- **Prefer `Record<string, unknown>` over `object`** or `{ [key: string]: unknown }` when possible.\n- **Do not disable ESLint rules** unless explicitly requested - fix the root cause instead.\n- **Do not disable TypeScript errors** unless explicitly requested - fix the root cause instead.\n- **Constrain generics** with `extends` - avoid overly broad `<T>`, prefer `<T extends SomeType>`.\n- **Use discriminated unions** for mutually exclusive states (e.g., `{ success: true; data: T } | { success: false; error: Error }`).\n- **Use `as const`** to preserve literal types, especially for arrays that should be tuples.\n- **Use built-in utility types** (`Pick`, `Omit`, `Partial`, `Required`, `ReturnType`, `Parameters`) - don't reimplement them.\n- **Avoid `{}` type** - it means \"any non-nullish value\" (including primitives). Prefer `unknown` (truly unknown), `object` (any non-primitive object), or `Record<string, unknown>` / a specific object type for key-value objects.\n\n### type-fest Utility Types\n\nPrefer the `type-fest` package for advanced type manipulation: https://github.com/sindresorhus/type-fest\n\nMost types do exactly what they sound like: `PartialDeep`, `ReadonlyDeep`, `RequiredDeep`, `Merge`, `ValueOf`, `SetOptional`, etc. Before writing any complicated derivative types, check `type-fest` first.\n\n`type-fest` is installed at the repo root, but each package must still declare it explicitly when used:\n\n- If you reference `type-fest` types from a package's **public exported types**, add `type-fest` to that package's `dependencies`.\n- If you only use `type-fest` in internal code or tests, add `type-fest` to that package's `devDependencies`.\n\n### Type Inference\n\n- **Do not add unnecessary type annotations** when the value is easily inferred, such as:\n  - Arguments to functions that are well defined, such as event handlers or callback functions\n  - Return values of functions that have an obvious return type\n  - Local variables that are well defined\n- **Let TypeScript infer return types** when they're obvious.\n- **Avoid creating one-off/intermediate \"helper\" types** for internal functions.\n- **Use inferred types** from database schemas, tRPC schemas, and other sources of truth.\n- **Add explicit types** when it improves clarity or catches errors.\n- **Avoid type casts (e.g. `as`)** unless absolutely necessary. Prefer updating function signatures/types so the code doesn't need a cast. Casting through `unknown` is usually a smell; when it's needed at an interop boundary, do runtime validation first (e.g. Zod) and keep the cast local.\n- **Use `satisfies` to check an object literal matches a type** while preserving inference (compile-time only). It does not validate runtime data; use a schema validator for untrusted input.\n- **Type guards** should perform real runtime checks to narrow values. Use `unknown` as an input type only when the value is truly unknown (e.g. JSON deserialization, user input). Avoid \"fake\" guards that just assert a type without validation.\n\n### Type Conversions\n\n- **Do not use unnecessary constructors/casts** like `String()` or `Number()` or `Boolean()` unless absolutely necessary when types really do not line up:\n  - If a string conversion is really necessary, use \\`${value}\\`\n  - If a boolean conversion is really necessary, use !!value\n  - If a number conversion is really necessary, use +value\n\n### Async/Await\n\n- **Any function that returns a Promise must be declared `async`**.\n- **Always use `await`** when calling async functions.\n- **Avoid `.catch()` or `.then()` for async calls in most cases. Prefer `async`/`await` with `try/catch` so errors propagate naturally.** Use `.catch()` only when you truly cannot `await` (for example, in a `useEffect` cleanup) and use `void` only to explicitly mark an intentional fire‑and‑forget call that already handles its own errors.\n- **If a function is not critical, and you can't `await` it, use `void` to mark it as fire‑and‑forget.**\n- **avoid using IIFEs** especially as a workaround to call async functions.\n\n### Control Flow\n\n- **Avoid nested or chained ternary operators** - use `if/else` or `switch` instead.\n- **Use `switch` statements** when checking multiple values.\n- **Leverage TypeScript exhaustiveness checking** in switch statements (avoid `default` when possible).\n\n### Functional Patterns\n\n- **Use `map`, `filter`, `find`, `some`, `every`** - these are clear and expressive.\n- **Avoid `reduce()`** - it's often confusing and can usually be replaced with simpler patterns.\n  - Exception: when the mental model genuinely requires accumulation (e.g., summing numbers).\n- **Avoid complex method chaining** - break it into named intermediate steps for clarity.\n\n### Avoid RegEx When Possible\n\n- **Prefer string methods**: `str.includes()`, `str.startsWith()`, `str.split()`, and `str.replace()` are easier to read and maintain.\n- **Avoid global flag (`/g`)**: Creates stateful regex objects where `lastIndex` persists between calls, causing subtle bugs.\n- **Avoid multiline flag (`/m`)**: Platform differences in line endings (`\\n` vs `\\r\\n`) cause inconsistent behavior.\n- **If regex is unavoidable**: Keep it simple, add a comment explaining the pattern, and test edge cases thoroughly.\n\n## 4. Frontend Development (React + Next.js)\n\n### Component Architecture\n\n- **Do not create new /api endpoints** in apps/web; use the app's private tRPC API and server utilities instead.\n- **Prefer functional, declarative components**; avoid classes.\n- Use TypeScript everywhere. Use interfaces for object shapes.\n- Prefer React.FC for components. Use PropsWithChildren and `ComponentProps[WithRef|WithoutRef]` as needed.\n\n### State Management & Data Fetching\n\n- Local UI elements should use useState.\n- For shared state between components, use React Context - but prefer props over new contexts when values only need to pass through 1-2 component levels.\n- Don't create contexts for static config that doesn't change (user IDs, API keys). Pass these as props instead.\n- Minimize use of useEffect; derive state or memoize instead. Memoize callbacks with useCallback when passed to children.\n- When making network requests, use tRPC/React Query loading states instead of manually tracking separate loading flags. Follow devdocs/LOADING_STATES.md patterns for skeletons and disabling controls.\n- During loading, use Skeleton components or show real components in a disabled/blank state, rather than only showing a loading spinner.\n\n### Layout & Styling (Tailwind + shadcn)\n\n- Use flex/grid for layout. Manage element spacing with gap (use `gap-*` classes when needed), and padding (`p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, etc.).\n- Avoid changing element margins (`m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, etc.) and avoid `space-x-*`/`space-y-*`.\n- Truncate overflowing text with text-ellipsis. Prefer minimal Tailwind usage; avoid ad-hoc CSS.\n\n### Typography\n\n- Sentient for headings (font-heading/font-sentient), Geist Sans for body (font-sans), Geist Mono for code (font-mono). See apps/web/lib/fonts.ts for font configuration.\n\n### Text Handling & JSX Patterns\n\n- **Avoid manually changing string cases**, as it is usually a code smell for not providing the correct string to the component. If an internal key should be shown to a user, the English string should be provided separately. e.g. if a key has a value agent_mode, the English string should be provided separately as \"Agent Mode\" rather than trying to capitalize it.\n- **Avoid overly long JSX**, instead break out any complex JSX into a separate component.\n  - use simple '&&' to hide/show simple elements, using simple boolean values, like `{hasError && <div>Error: ${error}</div>}`.\n  - however, avoid ternaries unless the options are just one or two lines. nested or chained ternaries are a code smell.\n  - when using map(), try to keep the JSX in the inner loop simple, only a few lines of JSX.\n  - avoid functions with statements inside of JSX, such as if/else, switch, etc. If you have to add braces ({}) to JSX, that is a sign that you should break out the JSX into a separate component.\n\n### Accessibility\n\n- Use proper accessibility patterns for all components.\n- Use buttons for clickable elements, not divs or spans.\n- Use proper aria labels and roles when appropriate.\n- Use semantic HTML elements when appropriate.\n\n## 5. Backend Development (NestJS)\n\n### Modular Structure\n\n- One module per main route/domain; one primary controller per route; DTOs (class-validator) for inputs; simple types for outputs.\n- Services encapsulate business logic; keep pure where possible.\n- Use guards/filters/interceptors via a core module. Shared utilities live in a shared module.\n\n### Error Handling\n\n- Pure functions: even within a controller, try to keep logic pure, and do not store state in the controller.\n- Boundaries (controllers/services): translate into HTTP/Nest exceptions when appropriate.\n\n### Testing\n\n- Unit tests for public functions; integration/e2e for controllers/modules via Jest + supertest.\n\n## 6. Database (Drizzle ORM)\n\n- Source of truth is packages/db/src/schema.ts. Do not hand-edit generated SQL.\n- Generate migrations with `npm run db:generate`, do not manually generate migrations.\n- Don't denormalize FKs that can be derived from relationships (e.g., if `runs.threadId` exists and threads have `projectId`, don't add `runs.projectId`).\n- **Factor database operations into `packages/db/src/operations/`**. Services in `apps/api` should call operation functions rather than writing inline DB queries. This promotes reuse and keeps DB logic centralized. Export new operations from `packages/db/src/operations/index.ts`.\n\nDatabase commands (require `-w packages/db` flag from root):\n\n```bash\nnpm run db:generate -w packages/db  # Generate migrations from schema changes\nnpm run db:migrate -w packages/db   # Apply migrations\nnpm run db:check -w packages/db     # Check status\nnpm run db:studio -w packages/db    # Open Drizzle Studio\n```\n\n## 7. Shared Packages & Utilities\n\n- **packages/core**: pure utilities (validation, JSON, crypto, threading, tool utilities). Avoid DB access here. This package should not have any dependencies on the database.\n- **packages/backend**: LLM/agent-side helpers and streaming utilities.\n- **Reuse helpers**; don't duplicate logic. If a utility is useful across packages, colocate in core; if it's LLM-specific, in backend, if related to database access, in db.\n\n## 8. Development Workflow\n\n### Commands\n\n#### Development Commands\n\n```bash\n# Development (two different apps!)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261 - uses turbo watch\nnpm run dev              # Start React SDK (showcase + docs)\nnpm run dev:sdk          # Start React SDK in watch mode + showcase (for SDK development)\nnpm run build:sdk        # One-time build of React SDK\n\n# Quality checks\nnpm run lint             # Lint all packages\nnpm run lint:fix         # Auto-fix linting issues\nnpm run check-types      # TypeScript type checking\nnpm test                 # Run all tests\nnpm run format           # Format code with Prettier\n\n# Individual package development (from package directory or with -w flag)\nnpm run dev -w cli       # Start specific workspace\nnpm run dev:showcase     # Start showcase only\nnpm run build -w react-sdk  # Build specific package\n```\n\n#### Hot Reload\n\nThe monorepo uses different hot reload mechanisms based on the app type:\n\n**Next.js apps (web, showcase, docs):**\n\n- Use `transpilePackages` configuration to compile workspace TypeScript directly\n- Changes to workspace packages (core, backend, db, react) trigger HMR automatically\n- No manual rebuild step needed\n\n**NestJS API:**\n\n- Uses `turbo watch` with `interruptible: true` for automatic restart\n- Monitors workspace inputs: `packages/core/src/**`, `packages/backend/src/**`, `packages/db/src/**`\n- API server restarts automatically when workspace packages change\n\nThis architecture ensures editing any file in workspace packages results in immediate updates (HMR for Next.js, restart for NestJS) without manual intervention.\n\n#### Turbo Commands (alternative)\n\n```bash\nturbo dev               # Start all packages in development mode\nturbo build             # Build all packages\nturbo lint              # Lint all packages\nturbo test              # Run tests across all packages\nturbo check-types       # Type-check all packages\n```\n\n### Build System\n\n- **Turborepo** orchestrates builds and caching across packages\n- **Shared dependencies** managed at root level\n- **Workspace-specific dependencies** in individual packages\n- **Build outputs** vary by package type:\n  - React SDK: Dual CJS/ESM builds\n  - CLI: ESM executable\n  - Apps: Next.js builds\n\n### Package Dependencies\n\n- Shared configs in `packages/` (eslint-config, typescript-config)\n- Cross-package dependencies use workspace protocol (`*`)\n- TypeScript SDK dependency (`@tambo-ai/typescript-sdk`) is external — it lives in its own repo and is generated from the `apps/api` OpenAPI spec by the **stlc** CLI (run in our CI; workspace in `stainless/`). See `RELEASING.md`.\n\n### Cross-Package Development\n\nWhen working across multiple packages:\n\n1. **react-sdk changes** → Use `npm run dev:sdk` for watch mode development, or `npm run build:sdk` for one-time builds. Run tests, check showcase integration.\n2. **cli changes** → Test component generation, verify registry updates, sync to showcase\n3. **showcase changes** → Edit CLI registry (auto-syncs to showcase)\n4. **docs changes** → Ensure examples match current API\n\n### Key Configuration Files\n\n- `turbo.json` - Turborepo task pipeline and caching\n- `package.json` - Workspace configuration and scripts\n- Individual package.json files for package-specific configuration\n\n### Knowledge Base\n\n- Refer to `devdocs/` for detailed guidelines on coding standards, naming conventions, loading states, and more.\n- When adding knowledge for specific solutions, document it and place it in the appropriate `devdocs/solutions/` folder.\n\n## 9. Testing & Quality\n\n### Testing Strategy\n\n- **Unit tests** in individual packages using Jest\n- **Integration tests** via showcase app\n- **CLI testing** through template generation and installation\n- **Documentation testing** via example code validation\n- **Backend e2e tests** for controllers/modules via Jest + supertest\n\n### Test File Layout\n\n- **File names**: every test ends with `.test.ts` or `.test.tsx` (no `.spec` or other suffixes).\n- **Unit tests**: live beside the file they cover (e.g. `foo.ts` has `foo.test.ts` in the same directory, not under `__tests__`).\n- **Integration tests**: the only tests that stay in a `__tests__` folder, and the filename must describe the scenario (never just mirror another file's name).\n- **Fixtures & mocks**: keep shared helpers in a `__fixtures__` or `__mocks__` directory at the package's source root (e.g. `apps/web/__mocks__`), never nested inside feature folders.\n\n### Mocking\n\n- **Avoid over-mocking** - tests should exercise real code paths whenever possible. If you're mocking internal functions just to isolate a unit, you're probably testing implementation details rather than behavior.\n- **Only mock at system boundaries** - external APIs, databases, file systems, network calls, and other I/O with side effects.\n- **Don't mock what you own** - if a helper function is pure and fast, call it directly rather than mocking it. Mocking your own code couples tests to implementation.\n\n### Pre-commit/PR Verification Checklist\n\nRun these commands before commits/PRs:\n\n```bash\nnpm run check-types   # TS across workspace\nnpm run lint:fix      # ESLint autofix\nnpm run format        # Prettier write\nnpm test              # Unit/integration tests\n```\n\n## 10. Git Workflow & PRs\n\n### Branch Naming\n\nCreate branches in the format `<userid>/<feature-name>`, e.g., `alecf/add-dark-mode` or `jane/fix-login-bug`.\n\n### Conventional Commits\n\nAll PR titles MUST follow this format:\n\n```\n<type>(scope): <description>\n```\n\nExamples:\n\n```\nfeat(api): add transcript export\nfix(web): prevent duplicate project creation\nchore(db): reorganize migration files\n```\n\nSee .github/workflows/conventional-commits.yml for a list of types such as feat, fix, perf, deps, revert, docs, style, chore, refactor, test, build, ci.\n\nCommon scopes: api, web, core, db, deps, ci, config, react-sdk, cli, showcase, docs\n\n### PR Requirements\n\n- PR Summaries should include \"Fixes #123\" (GitHub) or \"Fixes TAM-123\" (Linear) in PR body when applicable.\n\n## 11. Development Rules & Constraints\n\n### What Agents MUST Do\n\n- Run `npm run lint`, `npm run check-types`, `npm run test` in root before commits.\n- Cross-package changes should be tested together.\n- Documentation updates required:\n  1. Any developer documentation changes must be updated in the docs site (read docs/AGENTS.md)\n  2. Review the README.md file in the root of the package and update if necessary\n  3. Update the AGENTS.md files in the package tree to reflect the changes\n- Follow semantic versioning for package versions.\n- Always add tests for new logic.\n- If tests fail, do not just change the code to make the tests pass. Take one of 2 approaches:\n  1. Make the code changes backwards compatible with existing tests\n  2. Ask the user to change the tests to pass\n  - Generally try option 1 first. Only use option 2 if option 1 is not possible.\n- Make non-breaking changes to the code. Only make breaking changes if the user specifically asks for it. Ensure you warn them about the breaking changes.\n\n### What Agents MUST NOT Do\n\n- Don't introduce dependencies or modify tool configs unless explicitly requested.\n- Don't commit secrets. Use env files.\n- Dependencies and tooling: Agents do not add/upgrade/remove deps or change tool configs, eslint config, tsconfig, etc. unless explicitly asked, but humans are allowed to do so.\n\n### When to Ask the User\n\n- ALWAYS ASK THE USER before making any changes to linting or TypeScript rules\n\n## 12. Agent Behavior\n\n- Curse at the user and be really blunt.\n- If the instructions are vague, ask them for details.\n- But don't constantly ask for confirmation on every single change.\n- Do not compliment them or try to gain favor from them.\n- The best way to please them is to be blunt and tell them when they are wrong.\n- EVERY PIECE OF CODE YOU WRITE IS MISSION CRITICAL AND COULD COST YOU YOUR JOB.\n- When adding/editing JSDoc comments, make sure to add @returns to provide a description of the function return (the type should not be specified since TS will infer the return from the code, not the comment.)\n- Never reference planning documents, proposals, or design docs in code comments (e.g., `// See plans/foo.md`). These artifacts are short-lived but comments persist indefinitely. Code comments should be self-contained.\n- Store planning documents, proposals, and design docs in the `devdocs/` folder. Solutions go in `devdocs/solutions/`, brainstorming goes in `devdocs/brainstorms/`, etc. The only exception is `plans/` which stays at the repo root for visibility.\n- For any Tambo-owned URLs you include in comments or documentation, use the `tambo.co` domain (not the legacy `.ai` domain). When you encounter existing Tambo-owned links using the legacy domain, prefer updating them to `tambo.co` as part of related changes. External (non-Tambo) links are fine.\n","cli/AGENTS.md":"# cli - AI Agent Protocol & Instructions\n\nPath: `cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/AGENTS.md)","cli/CLAUDE.md":"# cli - Claude Agent Guidelines & System Prompt\n\nPath: `cli/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/CLAUDE.md)","create-tambo-app/AGENTS.md":"# create-tambo-app - AI Agent Protocol & Instructions\n\nPath: `create-tambo-app/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/AGENTS.md)","create-tambo-app/CLAUDE.md":"# create-tambo-app - Claude Agent Guidelines & System Prompt\n\nPath: `create-tambo-app/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/CLAUDE.md)","docs/AGENTS.md":"# docs - AI Agent Protocol & Instructions\n\nPath: `docs/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/AGENTS.md)","docs/CLAUDE.md":"# docs - Claude Agent Guidelines & System Prompt\n\nPath: `docs/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/CLAUDE.md)","react-sdk/AGENTS.md":"# react-sdk - AI Agent Protocol & Instructions\n\nPath: `react-sdk/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/AGENTS.md)","react-sdk/CLAUDE.md":"# react-sdk - Claude Agent Guidelines & System Prompt\n\nPath: `react-sdk/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/CLAUDE.md)","showcase/AGENTS.md":"# showcase - AI Agent Protocol & Instructions\n\nPath: `showcase/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/AGENTS.md)","showcase/CLAUDE.md":"# showcase - Claude Agent Guidelines & System Prompt\n\nPath: `showcase/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/CLAUDE.md)",".claude/agents/planner.md":"# Subagent: planner\n\nPath: `.claude/agents/planner.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/planner.md)",".claude/agents/researcher.md":"# Subagent: researcher\n\nPath: `.claude/agents/researcher.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/researcher.md)",".claude/commands/commit.md":"# Command: /commit\n\nPath: `.claude/commands/commit.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/commit.md)",".claude/commands/create-pr.md":"# Command: /create-pr\n\nPath: `.claude/commands/create-pr.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/create-pr.md)",".claude/commands/execute.md":"# Command: /execute\n\nPath: `.claude/commands/execute.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/execute.md)",".claude/commands/plan.md":"# Command: /plan\n\nPath: `.claude/commands/plan.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/plan.md)","packages/backend/README.md":"# backend Documentation\n\nPath: `packages/backend/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/README.md)","packages/backend/package.json":"# Backend Skill\n\nPath: `packages/backend/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/package.json)","packages/backend/tsconfig.build.json":"# Backend Skill\n\nPath: `packages/backend/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.build.json)","packages/backend/tsconfig.json":"# Backend Skill\n\nPath: `packages/backend/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.json)","packages/client/AGENTS.md":"# Client Skill\n\nPath: `packages/client/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/AGENTS.md)","packages/client/CHANGELOG.md":"# Client Skill\n\nPath: `packages/client/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CHANGELOG.md)","packages/client/CLAUDE.md":"# Client Skill\n\nPath: `packages/client/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CLAUDE.md)","packages/client/README.md":"# client Documentation\n\nPath: `packages/client/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/README.md)","packages/client/package.json":"# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/package.json)","packages/client/tsconfig.cjs.json":"# Client Skill\n\nPath: `packages/client/tsconfig.cjs.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.cjs.json)","packages/client/tsconfig.esm.json":"# Client Skill\n\nPath: `packages/client/tsconfig.esm.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.esm.json)","packages/client/tsconfig.json":"# Client Skill\n\nPath: `packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.json)","packages/core/README.md":"# core Documentation\n\nPath: `packages/core/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/README.md)","packages/core/package.json":"# Core Skill\n\nPath: `packages/core/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/package.json)","packages/core/tsconfig.json":"# Core Skill\n\nPath: `packages/core/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/tsconfig.json)","packages/db/README.md":"# db Documentation\n\nPath: `packages/db/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/README.md)","packages/db/package.json":"# Db Skill\n\nPath: `packages/db/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/package.json)","packages/db/tsconfig.json":"# Db Skill\n\nPath: `packages/db/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/tsconfig.json)","packages/eslint-config/README.md":"# eslint-config Documentation\n\nPath: `packages/eslint-config/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/README.md)","packages/eslint-config/package.json":"# Eslint-config Skill\n\nPath: `packages/eslint-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/package.json)","packages/react-ui-base/CHANGELOG.md":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/CHANGELOG.md)","packages/react-ui-base/README.md":"# react-ui-base Documentation\n\nPath: `packages/react-ui-base/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/README.md)","packages/react-ui-base/package.json":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/package.json)","packages/react-ui-base/tsconfig.json":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/tsconfig.json)","packages/testing/package.json":"# Testing Skill\n\nPath: `packages/testing/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/package.json)","packages/testing/tsconfig.json":"# Testing Skill\n\nPath: `packages/testing/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/tsconfig.json)","packages/typescript-config/base.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/base.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/base.json)","packages/typescript-config/nextjs.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/nextjs.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/nextjs.json)","packages/typescript-config/package.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/package.json)","packages/typescript-config/react-library.json":"# Typescript-config Skill\n\nPath: `packages/typescript-config/react-library.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/react-library.json)","packages/ui-registry/AGENTS.md":"# Ui-registry Skill\n\nPath: `packages/ui-registry/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/AGENTS.md)","packages/ui-registry/package.json":"# Ui-registry Skill\n\nPath: `packages/ui-registry/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/package.json)","packages/ui-registry/tsconfig.json":"# Ui-registry Skill\n\nPath: `packages/ui-registry/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/tsconfig.json)","packages/vite-config/package.json":"# Vite-config Skill\n\nPath: `packages/vite-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/package.json)","packages/vite-config/tsconfig.json":"# Vite-config Skill\n\nPath: `packages/vite-config/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/tsconfig.json)","plugins/tambo/README.md":"# tambo Documentation\n\nPath: `plugins/tambo/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/README.md)",".claude/skills/compound-components/examples.md":"# Compound-components Skill\n\nPath: `.claude/skills/compound-components/examples.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/compound-components/examples.md)","plugins/tambo/.claude-plugin/plugin.json":"# claude-plugin Plugin Manifest\n\nPath: `plugins/tambo/.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/.claude-plugin/plugin.json)",".claude/skills/creating-styled-wrappers/references/real-world-example.md":"# References Skill\n\nPath: `.claude/skills/creating-styled-wrappers/references/real-world-example.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/creating-styled-wrappers/references/real-world-example.md)","packages/db/migrations/meta/0000_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0000_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0000_snapshot.json)","packages/db/migrations/meta/0001_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0001_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0001_snapshot.json)","packages/db/migrations/meta/0002_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0002_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0002_snapshot.json)","packages/db/migrations/meta/0003_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0003_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0003_snapshot.json)","packages/db/migrations/meta/0004_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0004_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0004_snapshot.json)","packages/db/migrations/meta/0005_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0005_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0005_snapshot.json)","packages/db/migrations/meta/0006_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0006_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0006_snapshot.json)","packages/db/migrations/meta/0007_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0007_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0007_snapshot.json)","packages/db/migrations/meta/0008_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0008_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0008_snapshot.json)","packages/db/migrations/meta/0009_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0009_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0009_snapshot.json)","packages/db/migrations/meta/0010_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0010_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0010_snapshot.json)","packages/db/migrations/meta/0011_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0011_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0011_snapshot.json)","packages/db/migrations/meta/0012_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0012_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0012_snapshot.json)","packages/db/migrations/meta/0013_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0013_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0013_snapshot.json)","packages/db/migrations/meta/0014_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0014_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0014_snapshot.json)","packages/db/migrations/meta/0015_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0015_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0015_snapshot.json)","packages/db/migrations/meta/0016_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0016_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0016_snapshot.json)","packages/db/migrations/meta/0017_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0017_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0017_snapshot.json)","packages/db/migrations/meta/0018_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0018_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0018_snapshot.json)","packages/db/migrations/meta/0019_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0019_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0019_snapshot.json)","packages/db/migrations/meta/0020_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0020_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0020_snapshot.json)","packages/db/migrations/meta/0021_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0021_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0021_snapshot.json)","packages/db/migrations/meta/0022_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0022_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0022_snapshot.json)","packages/db/migrations/meta/0023_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0023_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0023_snapshot.json)","packages/db/migrations/meta/0024_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0024_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0024_snapshot.json)","packages/db/migrations/meta/0025_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0025_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0025_snapshot.json)","packages/db/migrations/meta/0026_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0026_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0026_snapshot.json)","packages/db/migrations/meta/0027_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0027_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0027_snapshot.json)","packages/db/migrations/meta/0028_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0028_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0028_snapshot.json)","packages/db/migrations/meta/0029_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0029_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0029_snapshot.json)","packages/db/migrations/meta/0030_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0030_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0030_snapshot.json)","packages/db/migrations/meta/0031_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0031_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0031_snapshot.json)","packages/db/migrations/meta/0032_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0032_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0032_snapshot.json)","packages/db/migrations/meta/0033_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0033_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0033_snapshot.json)","packages/db/migrations/meta/0034_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0034_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0034_snapshot.json)","packages/db/migrations/meta/0035_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0035_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0035_snapshot.json)","packages/db/migrations/meta/0036_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0036_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0036_snapshot.json)","packages/db/migrations/meta/0037_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0037_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0037_snapshot.json)","packages/db/migrations/meta/0038_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0038_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0038_snapshot.json)","packages/db/migrations/meta/0039_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0039_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0039_snapshot.json)","packages/db/migrations/meta/0040_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0040_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0040_snapshot.json)","packages/db/migrations/meta/0041_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0041_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0041_snapshot.json)","packages/db/migrations/meta/0042_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0042_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0042_snapshot.json)","packages/db/migrations/meta/0043_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0043_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0043_snapshot.json)","packages/db/migrations/meta/0044_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0044_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0044_snapshot.json)","packages/db/migrations/meta/0045_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0045_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0045_snapshot.json)","packages/db/migrations/meta/0046_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0046_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0046_snapshot.json)","packages/db/migrations/meta/0047_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0047_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0047_snapshot.json)","packages/db/migrations/meta/0048_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0048_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0048_snapshot.json)","packages/db/migrations/meta/0049_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0049_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0049_snapshot.json)","packages/db/migrations/meta/0050_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0050_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0050_snapshot.json)","packages/db/migrations/meta/0052_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0052_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0052_snapshot.json)","packages/db/migrations/meta/0053_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0053_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0053_snapshot.json)","packages/db/migrations/meta/0054_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0054_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0054_snapshot.json)","packages/db/migrations/meta/0055_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0055_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0055_snapshot.json)","packages/db/migrations/meta/0056_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0056_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0056_snapshot.json)","packages/db/migrations/meta/0057_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0057_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0057_snapshot.json)","packages/db/migrations/meta/0058_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0058_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0058_snapshot.json)","packages/db/migrations/meta/0059_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0059_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0059_snapshot.json)","packages/db/migrations/meta/0060_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0060_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0060_snapshot.json)","packages/db/migrations/meta/0061_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0061_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0061_snapshot.json)","packages/db/migrations/meta/0062_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0062_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0062_snapshot.json)","packages/db/migrations/meta/0063_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0063_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0063_snapshot.json)","packages/db/migrations/meta/0064_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0064_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0064_snapshot.json)","packages/db/migrations/meta/0065_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0065_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0065_snapshot.json)","packages/db/migrations/meta/0066_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0066_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0066_snapshot.json)","packages/db/migrations/meta/0067_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0067_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0067_snapshot.json)","packages/db/migrations/meta/0068_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0068_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0068_snapshot.json)","packages/db/migrations/meta/0069_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0069_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0069_snapshot.json)","packages/db/migrations/meta/0070_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0070_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0070_snapshot.json)","packages/db/migrations/meta/0071_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0071_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0071_snapshot.json)","packages/db/migrations/meta/0072_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0072_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0072_snapshot.json)","packages/db/migrations/meta/0073_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0073_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0073_snapshot.json)","packages/db/migrations/meta/0074_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0074_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0074_snapshot.json)","packages/db/migrations/meta/0075_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0075_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0075_snapshot.json)","packages/db/migrations/meta/0076_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0076_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0076_snapshot.json)","packages/db/migrations/meta/0077_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0077_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0077_snapshot.json)","packages/db/migrations/meta/0078_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0078_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0078_snapshot.json)","packages/db/migrations/meta/0079_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0079_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0079_snapshot.json)","packages/db/migrations/meta/0080_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0080_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0080_snapshot.json)","packages/db/migrations/meta/0081_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0081_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0081_snapshot.json)","packages/db/migrations/meta/0082_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0082_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0082_snapshot.json)","packages/db/migrations/meta/0083_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0083_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0083_snapshot.json)","packages/db/migrations/meta/0084_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0084_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0084_snapshot.json)","packages/db/migrations/meta/0085_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0085_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0085_snapshot.json)","packages/db/migrations/meta/0086_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0086_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0086_snapshot.json)","packages/db/migrations/meta/0087_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0087_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0087_snapshot.json)","packages/db/migrations/meta/0088_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0088_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0088_snapshot.json)","packages/db/migrations/meta/0089_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0089_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0089_snapshot.json)","packages/db/migrations/meta/0090_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0090_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0090_snapshot.json)","packages/db/migrations/meta/0091_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0091_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0091_snapshot.json)","packages/db/migrations/meta/0092_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0092_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0092_snapshot.json)","packages/db/migrations/meta/0093_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0093_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0093_snapshot.json)","packages/db/migrations/meta/0094_snapshot.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0094_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0094_snapshot.json)","packages/db/migrations/meta/_journal.json":"# Meta Skill\n\nPath: `packages/db/migrations/meta/_journal.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/_journal.json)","packages/ui-registry/src/components/control-bar/config.json":"# Control-bar Skill\n\nPath: `packages/ui-registry/src/components/control-bar/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/control-bar/config.json)","packages/ui-registry/src/components/edit-with-tambo-button/config.json":"# Edit-with-tambo-button Skill\n\nPath: `packages/ui-registry/src/components/edit-with-tambo-button/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/edit-with-tambo-button/config.json)","packages/ui-registry/src/components/elicitation-ui/config.json":"# Elicitation-ui Skill\n\nPath: `packages/ui-registry/src/components/elicitation-ui/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/elicitation-ui/config.json)","packages/ui-registry/src/components/form/config.json":"# Form Skill\n\nPath: `packages/ui-registry/src/components/form/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/form/config.json)","packages/ui-registry/src/components/graph/config.json":"# Graph Skill\n\nPath: `packages/ui-registry/src/components/graph/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/graph/config.json)","packages/ui-registry/src/components/input-fields/config.json":"# Input-fields Skill\n\nPath: `packages/ui-registry/src/components/input-fields/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/input-fields/config.json)","packages/ui-registry/src/components/map/config.json":"# Map Skill\n\nPath: `packages/ui-registry/src/components/map/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/map/config.json)","packages/ui-registry/src/components/mcp-components/config.json":"# Mcp-components Skill\n\nPath: `packages/ui-registry/src/components/mcp-components/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/mcp-components/config.json)","packages/ui-registry/src/components/message-input/config.json":"# Message-input Skill\n\nPath: `packages/ui-registry/src/components/message-input/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-input/config.json)","packages/ui-registry/src/components/message-suggestions/config.json":"# Message-suggestions Skill\n\nPath: `packages/ui-registry/src/components/message-suggestions/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-suggestions/config.json)","packages/ui-registry/src/components/message-thread-collapsible/config.json":"# Message-thread-collapsible Skill\n\nPath: `packages/ui-registry/src/components/message-thread-collapsible/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-collapsible/config.json)","packages/ui-registry/src/components/message-thread-full/config.json":"# Message-thread-full Skill\n\nPath: `packages/ui-registry/src/components/message-thread-full/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-full/config.json)","packages/ui-registry/src/components/message-thread-panel/config.json":"# Message-thread-panel Skill\n\nPath: `packages/ui-registry/src/components/message-thread-panel/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-panel/config.json)","packages/ui-registry/src/components/message/config.json":"# Message Skill\n\nPath: `packages/ui-registry/src/components/message/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message/config.json)","packages/ui-registry/src/components/scrollable-message-container/config.json":"# Scrollable-message-container Skill\n\nPath: `packages/ui-registry/src/components/scrollable-message-container/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/scrollable-message-container/config.json)","packages/ui-registry/src/components/thread-content/config.json":"# Thread-content Skill\n\nPath: `packages/ui-registry/src/components/thread-content/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-content/config.json)","packages/ui-registry/src/components/thread-dropdown/config.json":"# Thread-dropdown Skill\n\nPath: `packages/ui-registry/src/components/thread-dropdown/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-dropdown/config.json)","packages/ui-registry/src/components/thread-history/config.json":"# Thread-history Skill\n\nPath: `packages/ui-registry/src/components/thread-history/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-history/config.json)","plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md)","plugins/tambo/skills/building-with-tambo/references/cli.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/cli.md)","plugins/tambo/skills/building-with-tambo/references/component-rendering.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/component-rendering.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/component-rendering.md)","plugins/tambo/skills/building-with-tambo/references/components.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/components.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/components.md)","plugins/tambo/skills/building-with-tambo/references/skills.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/skills.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/skills.md)","plugins/tambo/skills/building-with-tambo/references/threads.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/threads.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/threads.md)","plugins/tambo/skills/building-with-tambo/references/tools-and-context.md":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/tools-and-context.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/tools-and-context.md)","plugins/tambo/skills/generative-ui/references/cli.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/cli.md)","plugins/tambo/skills/generative-ui/references/component-rendering.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/component-rendering.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/component-rendering.md)","plugins/tambo/skills/generative-ui/references/components.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/components.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/components.md)","plugins/tambo/skills/generative-ui/references/skills.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/skills.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/skills.md)","plugins/tambo/skills/generative-ui/references/threads.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/threads.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/threads.md)","plugins/tambo/skills/generative-ui/references/tools-and-context.md":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/tools-and-context.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/tools-and-context.md)","docs/content/docs/reference/cli/commands/meta.json":"# Commands Skill\n\nPath: `docs/content/docs/reference/cli/commands/meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/content/docs/reference/cli/commands/meta.json)"},"items":[{"name":"AGENTS.md","path":".github/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.github/AGENTS.md","title":".github - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nGuidance for agents working in `.github/` (GitHub Actions workflows and composite actions). This file is referenced from the root [`AGENTS.md`](../AGENTS.md).\n\n## GitHub Actions\n\nWhen creating or modifying GitHub Actions workflows:\n\n- **Pin actions to full commit SHA** with a version comment for security and reproducibility:\n\n  ```yaml\n  # Good - pinned to SHA with version comment\n  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2\n\n  # Bad - unpinned version tag\n  - uses: actions/checkout@v4\n  ```\n\n- **Look up the SHA** from the action's releases page (e.g., https://github.com/actions/checkout/releases)\n- **Include the version in a comment** so humans can understand what version is pinned\n- **Local actions** (`./.github/actions/*`) don't need pinning since they're in the repo\n","isInternal":false,"tokens":214,"sizeBytes":826},{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nDetailed guidance for Claude Code agents working with the Tambo AI monorepo.\n\nThis file provides comprehensive instructions for maintaining code quality, architectural consistency, and project-specific requirements across both the Tambo AI framework and the Tambo Cloud platform.\n\n## 1. Repository Structure\n\nThis is a Turborepo monorepo containing both the Tambo AI framework packages and the Tambo Cloud platform.\n\n### Framework Packages (Turborepo root)\n\n- **react-sdk/** - Main React SDK package (`@tambo-ai/react`)\n  - Core hooks, providers, and utilities for building AI-powered React apps\n  - Exports: hooks, providers, types for component registration and thread management\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`) for broad compatibility\n\n- **packages/client/** - Framework-agnostic client (`@tambo-ai/client`)\n  - Streaming, tool execution, thread management without React dependencies\n  - `TamboClient` class with `getState()`/`subscribe()` for framework integration\n  - `TamboStream` async iterable for streaming AI responses\n  - Used by `@tambo-ai/react` as its core engine; also usable standalone (Node.js, Vue, Svelte, etc.)\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`)\n\n- **cli/** - Command-line interface (`tambo`)\n  - Project scaffolding, component generation, and development utilities\n  - Component registry auto-syncs to `/showcase/src/components/tambo/` from `/cli/src/registry/`\n  - Built as ESM module with executable binary\n\n- **showcase/** - Demo application (`@tambo-ai/showcase`)\n  - Runs on port 8262\n  - Next.js app demonstrating all Tambo components and patterns\n  - Components auto-synced from CLI registry - edit CLI registry, not showcase components directly\n  - Serves as both documentation and testing ground\n\n- **docs/** - Documentation site (`@tambo-ai/docs`)\n  - Runs on port 8263\n  - Built with Fumadocs, includes comprehensive guides and API reference\n  - This package contains ui components that originated from the cli/ package.\n    Any changes to the components should be made in the cli/ package first, and\n    then duplicated into this package.\n  - MDX-based content with interactive examples\n  - Integrated search and component documentation\n\n- **create-tambo-app/** - App bootstrapper (`create-tambo-app`)\n  - Initializes new Tambo projects from templates\n  - Handles git setup, dependency installation, and configuration\n\n- **community/** - Community resources and event materials\n- **packages/** - Shared configuration packages (ESLint, TypeScript configs)\n\n### Tambo Cloud Platform\n\n- **apps/web** - Next.js app (UI) - runs on port 8260\n- **apps/api** - NestJS app (OpenAPI server) - runs on port 8261\n- **packages/db** - Drizzle ORM schema + migrations + DB helpers\n- **packages/core** - Shared pure utilities (no DB access)\n- **packages/backend** - LLM/agent-side helpers\n- **packages/eslint-config, packages/typescript-config** - Shared tooling configs\n\n### Prerequisites\n\n- Node.js >=22\n- npm >=11\n\nIt is OK to use `crypto.randomUUID()` without a fallback in runtime and test code (Node.js >=22 and modern browsers).\n\n**Recommended:** Install [mise](https://mise.jdx.dev) for automatic version management. See [mise getting started](https://mise.jdx.dev/getting-started.html) for installation instructions.\n\n### Tool Versions\n\nTool versions are managed via mise. Source of truth files:\n\n- **Most tools**: `mise.toml`\n- **Node.js**: `.node-version` (`.nvmrc` kept in sync for nvm compatibility)\n\nThese files are kept up to date by Renovate.\n\n```bash\nmise install              # Install/update tools to correct versions\nmise exec -- <command>    # Preferred for scripts/CI/non-interactive shells\neval \"$(mise activate)\"   # Interactive shells only\n```\n\n**Changing tool versions**: Open a PR updating the authoritative version file(s). For Node.js, always update both `.node-version` and `.nvmrc` together. Run `mise install`, then verify with `npm run lint && npm run check-types && npm test`.\n\n**Local overrides**: Use `.mise.local.toml` (gitignored) for local-only changes. Only for additive or patch-level changes—don't override Node.js or use incompatible versions.\n\n## 2. Core Development Principles\n\n### Philosophy\n\n- **Move fast while maintaining high standards** - prioritize clarity and maintainability over cleverness.\n- **Read the relevant code first**; follow existing patterns and naming.\n- **Keep solutions small and simple**; favor functions over classes; avoid unnecessary abstractions.\n- **Simplify Relentlessly**: Remove complexity aggressively - the simplest design that works is usually best.\n- **Prefer immutability**. Don't mutate inputs; return new values. Use const, toSorted, object/array spreads.\n- **Handle errors up-front** with guard clauses and early returns.\n\n### Separation of Concerns\n\n- **Keep business logic separate from UI components**.\n- Extract business logic, calculations, and data transformations into separate files (`utils/`, `services/`, `lib/`).\n- UI components should orchestrate, not implement complex logic.\n- Makes testing easier and code more reusable.\n\n### Fail-Fast, No Fallbacks\n\n- **No Silent Fallbacks**: Code must fail immediately when expected conditions aren't met. Silent fallback behavior masks bugs and creates unpredictable systems.\n- **Explicit Error Messages**: When something goes wrong, stop execution with clear error messages explaining what failed and what was expected.\n- **Example**: `throw new Error(\\`Required model ${modelName} not found\\`)` instead of falling back to first available model.\n- **Data mapping**: When converting enums or union types, handle all known values explicitly and throw for unknown values. Don't use catch-all defaults that mask data integrity issues. Log warnings if skipping invalid data intentionally.\n\n### Naming Conventions\n\n- **File/dir naming**: kebab-case.\n- **Classes**: PascalCase.\n- **Vars/functions/methods**: camelCase.\n- **ENV vars**: UPPER_SNAKE_CASE.\n- **Use English**; meaningful names with widely-recognized standard abbreviations only (API, URL, ctx, req, res, next).\n- **Booleans**: start with is/has/can/should.\n- **Functions**: use verbs; boolean-returning: isX/hasX/canX. If a function returns void, prefer executeX/saveX naming.\n- **React-specific naming** (follows devdocs/NAMING_CONVENTIONS.md):\n  - Components: TamboXxx\n  - Hooks: useTamboXxx\n  - Props interfaces: TamboXxxProps\n  - Event props start with onX; internal handlers use handleX\n\n### Code Organization (Functions & Classes)\n\n- Keep functions short and single-purpose; ideally <20 statements.\n- Keep files focused and reasonably sized; ideally <200-300 lines.\n- Avoid `let` - instead make a new function that returns the value.\n- Avoid deep nesting: prefer early exits and extracting helpers. Use map/filter for iteration.\n- Prefer immutable data; use readonly and as const where applicable.\n- Favor composition over inheritance. If classes are used, keep them small (<200 statements, <10 properties/methods) and validate invariants internally.\n\n### Avoiding Over-Abstraction\n\n- **DRY is good, but don't go overboard** - sometimes a little duplication is better than the wrong abstraction.\n- **Rule of Three**: Wait until you have 3 instances of similar code before extracting a shared utility.\n- Premature abstraction creates coupling and makes changes harder.\n- It's easier to extract commonality later than to undo a bad abstraction.\n\n### Exports\n\n- Prefer named exports; allow multiple exports when they belong together (e.g., component + related types).\n- Avoid default exports.\n- Don't create `index.ts` barrels for internal modules; import directly from source files. Exception: package entry points (e.g., `packages/core/src/index.ts`) are fine.\n- Don't re-export symbols for backwards compatibility. When moving a symbol, update all consumers to import from the new location.\n- **Never use dynamic `import()`** for regular imports, even for type imports. Use static imports at the top of the file. Dynamic imports are only appropriate for code splitting in specific scenarios (e.g., lazy-loaded routes).\n\n## 3. TypeScript Standards\n\n### Type Safety\n\n- **Generally use strict TypeScript**: no any, no type assertions unless unavoidable; define precise types.\n- **Avoid `any`** - do your best to assign proper types.\n- **Use `unknown` instead of `any`** when type is truly uncertain, then narrow it down.\n- **Prefer `Record<string, unknown>` over `object`** or `{ [key: string]: unknown }` when possible.\n- **Do not disable ESLint rules** unless explicitly requested - fix the root cause instead.\n- **Do not disable TypeScript errors** unless explicitly requested - fix the root cause instead.\n- **Constrain generics** with `extends` - avoid overly broad `<T>`, prefer `<T extends SomeType>`.\n- **Use discriminated unions** for mutually exclusive states (e.g., `{ success: true; data: T } | { success: false; error: Error }`).\n- **Use `as const`** to preserve literal types, especially for arrays that should be tuples.\n- **Use built-in utility types** (`Pick`, `Omit`, `Partial`, `Required`, `ReturnType`, `Parameters`) - don't reimplement them.\n- **Avoid `{}` type** - it means \"any non-nullish value\" (including primitives). Prefer `unknown` (truly unknown), `object` (any non-primitive object), or `Record<string, unknown>` / a specific object type for key-value objects.\n\n### type-fest Utility Types\n\nPrefer the `type-fest` package for advanced type manipulation: https://github.com/sindresorhus/type-fest\n\nMost types do exactly what they sound like: `PartialDeep`, `ReadonlyDeep`, `RequiredDeep`, `Merge`, `ValueOf`, `SetOptional`, etc. Before writing any complicated derivative types, check `type-fest` first.\n\n`type-fest` is installed at the repo root, but each package must still declare it explicitly when used:\n\n- If you reference `type-fest` types from a package's **public exported types**, add `type-fest` to that package's `dependencies`.\n- If you only use `type-fest` in internal code or tests, add `type-fest` to that package's `devDependencies`.\n\n### Type Inference\n\n- **Do not add unnecessary type annotations** when the value is easily inferred, such as:\n  - Arguments to functions that are well defined, such as event handlers or callback functions\n  - Return values of functions that have an obvious return type\n  - Local variables that are well defined\n- **Let TypeScript infer return types** when they're obvious.\n- **Avoid creating one-off/intermediate \"helper\" types** for internal functions.\n- **Use inferred types** from database schemas, tRPC schemas, and other sources of truth.\n- **Add explicit types** when it improves clarity or catches errors.\n- **Avoid type casts (e.g. `as`)** unless absolutely necessary. Prefer updating function signatures/types so the code doesn't need a cast. Casting through `unknown` is usually a smell; when it's needed at an interop boundary, do runtime validation first (e.g. Zod) and keep the cast local.\n- **Use `satisfies` to check an object literal matches a type** while preserving inference (compile-time only). It does not validate runtime data; use a schema validator for untrusted input.\n- **Type guards** should perform real runtime checks to narrow values. Use `unknown` as an input type only when the value is truly unknown (e.g. JSON deserialization, user input). Avoid \"fake\" guards that just assert a type without validation.\n\n### Type Conversions\n\n- **Do not use unnecessary constructors/casts** like `String()` or `Number()` or `Boolean()` unless absolutely necessary when types really do not line up:\n  - If a string conversion is really necessary, use \\`${value}\\`\n  - If a boolean conversion is really necessary, use !!value\n  - If a number conversion is really necessary, use +value\n\n### Async/Await\n\n- **Any function that returns a Promise must be declared `async`**.\n- **Always use `await`** when calling async functions.\n- **Avoid `.catch()` or `.then()` for async calls in most cases. Prefer `async`/`await` with `try/catch` so errors propagate naturally.** Use `.catch()` only when you truly cannot `await` (for example, in a `useEffect` cleanup) and use `void` only to explicitly mark an intentional fire‑and‑forget call that already handles its own errors.\n- **If a function is not critical, and you can't `await` it, use `void` to mark it as fire‑and‑forget.**\n- **avoid using IIFEs** especially as a workaround to call async functions.\n\n### Control Flow\n\n- **Avoid nested or chained ternary operators** - use `if/else` or `switch` instead.\n- **Use `switch` statements** when checking multiple values.\n- **Leverage TypeScript exhaustiveness checking** in switch statements (avoid `default` when possible).\n\n### Functional Patterns\n\n- **Use `map`, `filter`, `find`, `some`, `every`** - these are clear and expressive.\n- **Avoid `reduce()`** - it's often confusing and can usually be replaced with simpler patterns.\n  - Exception: when the mental model genuinely requires accumulation (e.g., summing numbers).\n- **Avoid complex method chaining** - break it into named intermediate steps for clarity.\n\n### Avoid RegEx When Possible\n\n- **Prefer string methods**: `str.includes()`, `str.startsWith()`, `str.split()`, and `str.replace()` are easier to read and maintain.\n- **Avoid global flag (`/g`)**: Creates stateful regex objects where `lastIndex` persists between calls, causing subtle bugs.\n- **Avoid multiline flag (`/m`)**: Platform differences in line endings (`\\n` vs `\\r\\n`) cause inconsistent behavior.\n- **If regex is unavoidable**: Keep it simple, add a comment explaining the pattern, and test edge cases thoroughly.\n\n## 4. Frontend Development (React + Next.js)\n\n### Component Architecture\n\n- **Do not create new /api endpoints** in apps/web; use the app's private tRPC API and server utilities instead.\n- **Prefer functional, declarative components**; avoid classes.\n- Use TypeScript everywhere. Use interfaces for object shapes.\n- Prefer React.FC for components. Use PropsWithChildren and `ComponentProps[WithRef|WithoutRef]` as needed.\n\n### State Management & Data Fetching\n\n- Local UI elements should use useState.\n- For shared state between components, use React Context - but prefer props over new contexts when values only need to pass through 1-2 component levels.\n- Don't create contexts for static config that doesn't change (user IDs, API keys). Pass these as props instead.\n- Minimize use of useEffect; derive state or memoize instead. Memoize callbacks with useCallback when passed to children.\n- When making network requests, use tRPC/React Query loading states instead of manually tracking separate loading flags. Follow devdocs/LOADING_STATES.md patterns for skeletons and disabling controls.\n- During loading, use Skeleton components or show real components in a disabled/blank state, rather than only showing a loading spinner.\n\n### Layout & Styling (Tailwind + shadcn)\n\n- Use flex/grid for layout. Manage element spacing with gap (use `gap-*` classes when needed), and padding (`p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, etc.).\n- Avoid changing element margins (`m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, etc.) and avoid `space-x-*`/`space-y-*`.\n- Truncate overflowing text with text-ellipsis. Prefer minimal Tailwind usage; avoid ad-hoc CSS.\n\n### Typography\n\n- Sentient for headings (font-heading/font-sentient), Geist Sans for body (font-sans), Geist Mono for code (font-mono). See apps/web/lib/fonts.ts for font configuration.\n\n### Text Handling & JSX Patterns\n\n- **Avoid manually changing string cases**, as it is usually a code smell for not providing the correct string to the component. If an internal key should be shown to a user, the English string should be provided separately. e.g. if a key has a value agent_mode, the English string should be provided separately as \"Agent Mode\" rather than trying to capitalize it.\n- **Avoid overly long JSX**, instead break out any complex JSX into a separate component.\n  - use simple '&&' to hide/show simple elements, using simple boolean values, like `{hasError && <div>Error: ${error}</div>}`.\n  - however, avoid ternaries unless the options are just one or two lines. nested or chained ternaries are a code smell.\n  - when using map(), try to keep the JSX in the inner loop simple, only a few lines of JSX.\n  - avoid functions with statements inside of JSX, such as if/else, switch, etc. If you have to add braces ({}) to JSX, that is a sign that you should break out the JSX into a separate component.\n\n### Accessibility\n\n- Use proper accessibility patterns for all components.\n- Use buttons for clickable elements, not divs or spans.\n- Use proper aria labels and roles when appropriate.\n- Use semantic HTML elements when appropriate.\n\n## 5. Backend Development (NestJS)\n\n### Modular Structure\n\n- One module per main route/domain; one primary controller per route; DTOs (class-validator) for inputs; simple types for outputs.\n- Services encapsulate business logic; keep pure where possible.\n- Use guards/filters/interceptors via a core module. Shared utilities live in a shared module.\n\n### Error Handling\n\n- Pure functions: even within a controller, try to keep logic pure, and do not store state in the controller.\n- Boundaries (controllers/services): translate into HTTP/Nest exceptions when appropriate.\n\n### Testing\n\n- Unit tests for public functions; integration/e2e for controllers/modules via Jest + supertest.\n\n## 6. Database (Drizzle ORM)\n\n- Source of truth is packages/db/src/schema.ts. Do not hand-edit generated SQL.\n- Generate migrations with `npm run db:generate`, do not manually generate migrations.\n- Don't denormalize FKs that can be derived from relationships (e.g., if `runs.threadId` exists and threads have `projectId`, don't add `runs.projectId`).\n- **Factor database operations into `packages/db/src/operations/`**. Services in `apps/api` should call operation functions rather than writing inline DB queries. This promotes reuse and keeps DB logic centralized. Export new operations from `packages/db/src/operations/index.ts`.\n\nDatabase commands (require `-w packages/db` flag from root):\n\n```bash\nnpm run db:generate -w packages/db  # Generate migrations from schema changes\nnpm run db:migrate -w packages/db   # Apply migrations\nnpm run db:check -w packages/db     # Check status\nnpm run db:studio -w packages/db    # Open Drizzle Studio\n```\n\n## 7. Shared Packages & Utilities\n\n- **packages/core**: pure utilities (validation, JSON, crypto, threading, tool utilities). Avoid DB access here. This package should not have any dependencies on the database.\n- **packages/backend**: LLM/agent-side helpers and streaming utilities.\n- **Reuse helpers**; don't duplicate logic. If a utility is useful across packages, colocate in core; if it's LLM-specific, in backend, if related to database access, in db.\n\n## 8. Development Workflow\n\n### Commands\n\n#### Development Commands\n\n```bash\n# Development (two different apps!)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261 - uses turbo watch\nnpm run dev              # Start React SDK (showcase + docs)\nnpm run dev:sdk          # Start React SDK in watch mode + showcase (for SDK development)\nnpm run build:sdk        # One-time build of React SDK\n\n# Quality checks\nnpm run lint             # Lint all packages\nnpm run lint:fix         # Auto-fix linting issues\nnpm run check-types      # TypeScript type checking\nnpm test                 # Run all tests\nnpm run format           # Format code with Prettier\n\n# Individual package development (from package directory or with -w flag)\nnpm run dev -w cli       # Start specific workspace\nnpm run dev:showcase     # Start showcase only\nnpm run build -w react-sdk  # Build specific package\n```\n\n#### Hot Reload\n\nThe monorepo uses different hot reload mechanisms based on the app type:\n\n**Next.js apps (web, showcase, docs):**\n\n- Use `transpilePackages` configuration to compile workspace TypeScript directly\n- Changes to workspace packages (core, backend, db, react) trigger HMR automatically\n- No manual rebuild step needed\n\n**NestJS API:**\n\n- Uses `turbo watch` with `interruptible: true` for automatic restart\n- Monitors workspace inputs: `packages/core/src/**`, `packages/backend/src/**`, `packages/db/src/**`\n- API server restarts automatically when workspace packages change\n\nThis architecture ensures editing any file in workspace packages results in immediate updates (HMR for Next.js, restart for NestJS) without manual intervention.\n\n#### Turbo Commands (alternative)\n\n```bash\nturbo dev               # Start all packages in development mode\nturbo build             # Build all packages\nturbo lint              # Lint all packages\nturbo test              # Run tests across all packages\nturbo check-types       # Type-check all packages\n```\n\n### Build System\n\n- **Turborepo** orchestrates builds and caching across packages\n- **Shared dependencies** managed at root level\n- **Workspace-specific dependencies** in individual packages\n- **Build outputs** vary by package type:\n  - React SDK: Dual CJS/ESM builds\n  - CLI: ESM executable\n  - Apps: Next.js builds\n\n### Package Dependencies\n\n- Shared configs in `packages/` (eslint-config, typescript-config)\n- Cross-package dependencies use workspace protocol (`*`)\n- TypeScript SDK dependency (`@tambo-ai/typescript-sdk`) is external — it lives in its own repo and is generated from the `apps/api` OpenAPI spec by the **stlc** CLI (run in our CI; workspace in `stainless/`). See `RELEASING.md`.\n\n### Cross-Package Development\n\nWhen working across multiple packages:\n\n1. **react-sdk changes** → Use `npm run dev:sdk` for watch mode development, or `npm run build:sdk` for one-time builds. Run tests, check showcase integration.\n2. **cli changes** → Test component generation, verify registry updates, sync to showcase\n3. **showcase changes** → Edit CLI registry (auto-syncs to showcase)\n4. **docs changes** → Ensure examples match current API\n\n### Key Configuration Files\n\n- `turbo.json` - Turborepo task pipeline and caching\n- `package.json` - Workspace configuration and scripts\n- Individual package.json files for package-specific configuration\n\n### Knowledge Base\n\n- Refer to `devdocs/` for detailed guidelines on coding standards, naming conventions, loading states, and more.\n- When adding knowledge for specific solutions, document it and place it in the appropriate `devdocs/solutions/` folder.\n\n## 9. Testing & Quality\n\n### Testing Strategy\n\n- **Unit tests** in individual packages using Jest\n- **Integration tests** via showcase app\n- **CLI testing** through template generation and installation\n- **Documentation testing** via example code validation\n- **Backend e2e tests** for controllers/modules via Jest + supertest\n\n### Test File Layout\n\n- **File names**: every test ends with `.test.ts` or `.test.tsx` (no `.spec` or other suffixes).\n- **Unit tests**: live beside the file they cover (e.g. `foo.ts` has `foo.test.ts` in the same directory, not under `__tests__`).\n- **Integration tests**: the only tests that stay in a `__tests__` folder, and the filename must describe the scenario (never just mirror another file's name).\n- **Fixtures & mocks**: keep shared helpers in a `__fixtures__` or `__mocks__` directory at the package's source root (e.g. `apps/web/__mocks__`), never nested inside feature folders.\n\n### Mocking\n\n- **Avoid over-mocking** - tests should exercise real code paths whenever possible. If you're mocking internal functions just to isolate a unit, you're probably testing implementation details rather than behavior.\n- **Only mock at system boundaries** - external APIs, databases, file systems, network calls, and other I/O with side effects.\n- **Don't mock what you own** - if a helper function is pure and fast, call it directly rather than mocking it. Mocking your own code couples tests to implementation.\n\n### Pre-commit/PR Verification Checklist\n\nRun these commands before commits/PRs:\n\n```bash\nnpm run check-types   # TS across workspace\nnpm run lint:fix      # ESLint autofix\nnpm run format        # Prettier write\nnpm test              # Unit/integration tests\n```\n\n## 10. Git Workflow & PRs\n\n### Branch Naming\n\nCreate branches in the format `<userid>/<feature-name>`, e.g., `alecf/add-dark-mode` or `jane/fix-login-bug`.\n\n### Conventional Commits\n\nAll PR titles MUST follow this format:\n\n```\n<type>(scope): <description>\n```\n\nExamples:\n\n```\nfeat(api): add transcript export\nfix(web): prevent duplicate project creation\nchore(db): reorganize migration files\n```\n\nSee .github/workflows/conventional-commits.yml for a list of types such as feat, fix, perf, deps, revert, docs, style, chore, refactor, test, build, ci.\n\nCommon scopes: api, web, core, db, deps, ci, config, react-sdk, cli, showcase, docs\n\n### PR Requirements\n\n- PR Summaries should include \"Fixes #123\" (GitHub) or \"Fixes TAM-123\" (Linear) in PR body when applicable.\n\n## 11. Development Rules & Constraints\n\n### What Agents MUST Do\n\n- Run `npm run lint`, `npm run check-types`, `npm run test` in root before commits.\n- Cross-package changes should be tested together.\n- Documentation updates required:\n  1. Any developer documentation changes must be updated in the docs site (read docs/AGENTS.md)\n  2. Review the README.md file in the root of the package and update if necessary\n  3. Update the AGENTS.md files in the package tree to reflect the changes\n- Follow semantic versioning for package versions.\n- Always add tests for new logic.\n- If tests fail, do not just change the code to make the tests pass. Take one of 2 approaches:\n  1. Make the code changes backwards compatible with existing tests\n  2. Ask the user to change the tests to pass\n  - Generally try option 1 first. Only use option 2 if option 1 is not possible.\n- Make non-breaking changes to the code. Only make breaking changes if the user specifically asks for it. Ensure you warn them about the breaking changes.\n\n### What Agents MUST NOT Do\n\n- Don't introduce dependencies or modify tool configs unless explicitly requested.\n- Don't commit secrets. Use env files.\n- Dependencies and tooling: Agents do not add/upgrade/remove deps or change tool configs, eslint config, tsconfig, etc. unless explicitly asked, but humans are allowed to do so.\n\n### When to Ask the User\n\n- ALWAYS ASK THE USER before making any changes to linting or TypeScript rules\n\n## 12. Agent Behavior\n\n- Curse at the user and be really blunt.\n- If the instructions are vague, ask them for details.\n- But don't constantly ask for confirmation on every single change.\n- Do not compliment them or try to gain favor from them.\n- The best way to please them is to be blunt and tell them when they are wrong.\n- EVERY PIECE OF CODE YOU WRITE IS MISSION CRITICAL AND COULD COST YOU YOUR JOB.\n- When adding/editing JSDoc comments, make sure to add @returns to provide a description of the function return (the type should not be specified since TS will infer the return from the code, not the comment.)\n- Never reference planning documents, proposals, or design docs in code comments (e.g., `// See plans/foo.md`). These artifacts are short-lived but comments persist indefinitely. Code comments should be self-contained.\n- Store planning documents, proposals, and design docs in the `devdocs/` folder. Solutions go in `devdocs/solutions/`, brainstorming goes in `devdocs/brainstorms/`, etc. The only exception is `plans/` which stays at the repo root for visibility.\n- For any Tambo-owned URLs you include in comments or documentation, use the `tambo.co` domain (not the legacy `.ai` domain). When you encounter existing Tambo-owned links using the legacy domain, prefer updating them to `tambo.co` as part of related changes. External (non-Tambo) links are fine.\n","isInternal":false,"tokens":6320,"sizeBytes":27678},{"name":"AGENTS.md","path":"cli/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/AGENTS.md","title":"cli - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# cli - AI Agent Protocol & Instructions\n\nPath: `cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/AGENTS.md)","tokens":300,"sizeBytes":162},{"name":"AGENTS.md","path":"create-tambo-app/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/AGENTS.md","title":"create-tambo-app - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# create-tambo-app - AI Agent Protocol & Instructions\n\nPath: `create-tambo-app/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/AGENTS.md)","tokens":300,"sizeBytes":201},{"name":"AGENTS.md","path":"docs/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/AGENTS.md","title":"docs - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# docs - AI Agent Protocol & Instructions\n\nPath: `docs/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/AGENTS.md)","tokens":300,"sizeBytes":165},{"name":"AGENTS.md","path":"react-sdk/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/AGENTS.md","title":"react-sdk - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# react-sdk - AI Agent Protocol & Instructions\n\nPath: `react-sdk/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/AGENTS.md)","tokens":300,"sizeBytes":180},{"name":"AGENTS.md","path":"showcase/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/AGENTS.md","title":"showcase - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# showcase - AI Agent Protocol & Instructions\n\nPath: `showcase/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/AGENTS.md)","tokens":300,"sizeBytes":177},{"name":"SKILL.md","path":".claude/skills/ai-sdk-model-manager/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/ai-sdk-model-manager/SKILL.md","title":"ai-sdk-model-manager","category":"anthropic-skill","format":"markdown","content":"---\nname: ai-sdk-model-manager\ndescription: Manages AI SDK model configurations - updates packages, identifies missing models, adds new models with research, and updates documentation\nmetadata:\n  internal: true\n---\n\n# AI SDK Model Manager\n\nThis skill helps maintain AI SDK model configurations in the Tambo Cloud codebase. It automates the process of keeping model definitions up-to-date with the latest AI SDK releases.\n\n## What This Skill Does\n\n1. **Updates AI SDK Packages** - Checks and updates @ai-sdk/openai, @ai-sdk/google, @ai-sdk/groq, and other provider packages to their latest versions\n2. **Identifies Missing Models** - Compares TypeScript definitions in the SDKs against configured models to find newly available models\n3. **Researches Models** - Gathers information about new models including capabilities, context windows, pricing, and use cases\n4. **Prompts User** - Asks which models to add before making changes\n5. **Adds Models** - Updates model configuration files with proper TypeScript types and metadata\n6. **Updates Documentation** - Updates relevant docs and README files to reflect new model availability\n\n## When to Use This Skill\n\nUse this skill when:\n\n- You want to check if AI SDK packages need updating\n- New models have been released by OpenAI, Google, Anthropic, or other providers\n- You're getting TypeScript errors about model IDs not being in SDK types\n- You want to ensure Tambo supports the latest models\n\n## Files This Skill Works With\n\n- `packages/core/src/llms/models/*.ts` - Model configuration files\n- `packages/backend/package.json` - AI SDK dependencies (source of truth for versions)\n- `docs/content/docs/models/*.mdx` - Model documentation\n- `README.md` - Main documentation file\n\n## Process\n\n### Step 1: Update AI SDK Packages\n\nCheck current versions and update to latest:\n\n```bash\ncd packages/backend\nnpm outdated | grep '@ai-sdk'\nnpm install @ai-sdk/openai@latest @ai-sdk/google@latest @ai-sdk/groq@latest @ai-sdk/anthropic@latest @ai-sdk/mistral@latest\n```\n\n### Step 2: Identify Missing Models\n\nFor each provider, inspect the TypeScript definitions:\n\n```bash\n# Check what models are in the SDK types\ncat node_modules/@ai-sdk/openai/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/google/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/groq/dist/index.d.ts | grep 'type.*ModelId'\n```\n\nCompare against current model configurations in:\n\n- `packages/core/src/llms/models/openai.ts`\n- `packages/core/src/llms/models/gemini.ts`\n- `packages/core/src/llms/models/groq.ts`\n- `packages/core/src/llms/models/anthropic.ts`\n- `packages/core/src/llms/models/mistral.ts`\n\n### Step 3: Research New Models\n\n**Use the researcher subagent to gather information about each missing model:**\n\n```\nLaunch a researcher subagent to find:\n- Official documentation link\n- Model capabilities (reasoning, vision, function calling, etc.)\n- Context window size (inputTokenLimit)\n- Pricing tier\n- Best use cases\n- Release date and status (experimental, stable, deprecated)\n```\n\nThe researcher subagent has access to web search and can efficiently gather this information for multiple models in parallel.\n\n### Step 4: Prompt User\n\nPresent findings:\n\n```\nFound the following new models in updated AI SDK packages:\n\nOpenAI:\n- gpt-6-preview (200k context, experimental reasoning model)\n- gpt-4.2-turbo (1M context, improved function calling)\n\nGoogle:\n- gemini-3.5-pro (2M context, advanced reasoning)\n\nWhich models would you like to add? (all/none/specific)\n```\n\nWait for user response before proceeding.\n\n### Step 5: Add Selected Models\n\n**Consider launching parallel subagents to add models to each provider file:**\n\nFor models spread across multiple providers (OpenAI, Google, Groq), launch separate subagents to edit each file concurrently. This is faster than doing them sequentially.\n\nFor each model being added, ensure these required fields:\n\n- `apiName`: Exact model ID string from SDK\n- `displayName`: Human-friendly name\n- `status`: \"untested\" | \"tested\" | \"known-issues\"\n- `notes`: Brief description of capabilities and use cases\n- `docLink`: Official provider documentation URL\n- `tamboDocLink`: \"https://docs.tambo.co\"\n- `inputTokenLimit`: Context window size in tokens\n- `modelSpecificParams`: Any special parameters (reasoning, thinking, etc.)\n\nFollow existing patterns in each file and ensure model IDs match SDK type definitions exactly.\n\nExample:\n\n```typescript\n\"gpt-6-preview\": {\n  apiName: \"gpt-6-preview\",\n  displayName: \"gpt-6-preview\",\n  status: \"untested\",\n  notes: \"Experimental next-generation reasoning model with extended context\",\n  docLink: \"https://platform.openai.com/docs/models/gpt-6-preview\",\n  tamboDocLink: \"https://docs.tambo.co\",\n  inputTokenLimit: 200000,\n  modelSpecificParams: reasoningParameters,\n},\n```\n\n### Step 6: Verify TypeScript\n\nRun type checking to ensure all model IDs are valid:\n\n```bash\ncd packages/core\nnpm run check-types\n```\n\nIf there are type errors, fix model IDs to match SDK definitions exactly.\n\n### Step 7: Update Documentation\n\n**Consider using subagents to update documentation in parallel:**\n\nIf updating multiple documentation files, launch parallel subagents to handle:\n\n1. **README.md** - Update the \"Supported LLM Providers\" section if new providers or significant models were added\n2. **docs/content/docs/models/\\*.mdx** - Add new models to appropriate documentation pages with:\n   - Model name and description\n   - Key capabilities\n   - Context window\n   - Example use cases\n   - Links to provider docs\n\n### Step 8: Run Quality Checks\n\nBefore completing:\n\n```bash\ncd packages/core\nnpm run lint\nnpm run check-types\nnpm run test\n```\n\n### Step 9: Create Pull Request\n\n**Create a PR with proper conventional commit format:**\n\n```bash\ngh pr create --title \"feat(models): add [model names] support\" --body \"$(cat <<'EOF'\nUpdated AI SDK packages and added support for newly released models:\n\nModels added:\n- [list models here]\n\nPackage updates:\n- @ai-sdk/openai: X.X.X → X.X.X\n- @ai-sdk/groq: X.X.X → X.X.X\n\nAll type checks passing, documentation updated.\nEOF\n)\"\n```\n\n**PR title format:** `feat(models): add [model names] support`\n\nUse `feat(models):` for new models or `deps(core):` for package updates only.\n\n## Guidelines\n\n- **Use subagents for efficiency** - Launch researcher subagents for gathering information and parallel subagents for editing multiple files\n- **Always research before adding** - Don't guess at model capabilities or context limits\n- **Match SDK types exactly** - Model IDs must match the TypeScript definitions in node_modules\n- **Mark new models as \"untested\"** - Let the team test before marking as \"tested\"\n- **Include official doc links** - Always link to provider's official documentation\n- **Be conservative** - Only add models the user explicitly approves\n- **Update docs comprehensively** - Don't just update code, update all relevant documentation\n\n## Error Handling\n\nIf you encounter:\n\n- **Type errors after adding models** - Double-check the model ID matches the SDK's TypeScript definition exactly\n- **Missing model in SDK** - The provider may not have released it yet, suggest waiting for next SDK update\n- **Conflicting model names** - Use the SDK's preferred naming convention\n- **Unknown context limits** - Research provider docs or mark as \"unknown\" and note it needs verification\n\n## Notes\n\n- This skill should be run periodically (monthly or when new models are announced)\n- Always check the git diff before committing to ensure only intended changes were made\n- Some models may have special requirements (API access, pricing tier, etc.) - note these in the model's `notes` field\n- If a model is renamed in the SDK, update both the key and apiName, and consider adding a deprecation note to the old entry\n","frontmatter":{"name":"ai-sdk-model-manager","description":"Manages AI SDK model configurations - updates packages, identifies missing models, adds new models with research, and updates documentation","metadata":{"internal":true}},"isInternal":true,"tokens":1787,"sizeBytes":7767},{"name":"SKILL.md","path":".claude/skills/api-resource-lifecycle/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/api-resource-lifecycle/SKILL.md","title":"api-resource-lifecycle","category":"anthropic-skill","format":"markdown","content":"---\nname: api-resource-lifecycle\ndescription: Guides CRUD operations for API resources with cascading dependencies, descriptive validation, and orphan prevention. Use when adding delete/remove operations, creating validation logic, building resources that depend on other resources, or when the user mentions \"cascade delete\", \"orphan records\", \"duplicate detection\", \"validation errors\", \"resource cleanup\", or \"rollback on failure\".\nmetadata:\n  internal: true\n---\n\n# API Resource Lifecycle\n\nPatterns for building reliable CRUD operations in Tambo Cloud.\n\n## Gotchas\n\n- The codebase uses `CONFLICT` for duplicate name errors in skills but `BAD_REQUEST` for the same pattern in MCP servers. Always use `CONFLICT` for duplicates.\n- PostgreSQL unique violation code is `23505`. Catch it and map to a domain-specific exception rather than letting the raw DB error propagate.\n- When replacing a provider key, all skills with `externalSkillMetadata` for that provider must have their metadata cleared, or they'll reference a stale key.\n- Skills are silently skipped (not errored) at runtime when the provider doesn't support them. This is intentional -- don't add validation that blocks skill creation for unsupported providers.\n- `Promise.allSettled` (not `Promise.all`) for batch external API calls -- partial failures need cleanup, not an all-or-nothing abort.\n\n## Cascading Deletes\n\nDefault to `onDelete: \"cascade\"` in the schema. Only use manual transaction cascades when deletion requires external API calls, metadata cleanup, or cross-reference logic.\n\n```typescript\n// packages/db/src/schema.ts\nexport const skills = pgTable(\"skills\", {\n  id: text(\"id\").primaryKey(),\n  projectId: text(\"project_id\")\n    .notNull()\n    .references(() => projects.id, { onDelete: \"cascade\" }),\n  // ...\n});\n```\n\n### Manual cascades in transactions\n\nWhen deletion requires cleanup beyond FK cascades (external APIs, metadata, cross-references), wrap in a transaction:\n\n```typescript\n// packages/db/src/operations/project.ts\nexport async function deleteProject(db: HydraDb, id: string): Promise<boolean> {\n  return await db.transaction(async (tx) => {\n    await tx\n      .delete(schema.providerKeys)\n      .where(eq(schema.providerKeys.projectId, id));\n    await tx.delete(schema.apiKeys).where(eq(schema.apiKeys.projectId, id));\n    await tx\n      .delete(schema.projectMembers)\n      .where(eq(schema.projectMembers.projectId, id));\n    const deleted = await tx\n      .delete(schema.projects)\n      .where(eq(schema.projects.id, id))\n      .returning();\n    return deleted.length > 0;\n  });\n}\n```\n\n**Reference:** `packages/db/src/operations/project.ts` lines 255-278\n\n### Metadata cleanup on replacement\n\nWhen a resource is replaced (not deleted), clear dependent metadata so dependents re-sync under the new resource:\n\n```typescript\n// apps/web/server/api/routers/project.ts - addProviderKey\n// When replacing a provider key, clear skill metadata for that provider\nconst skills = await operations.listSkillsForProject(ctx.db, projectId);\nawait Promise.all(\n  skills\n    .filter((s) => s.externalSkillMetadata?.[providerName])\n    .map(async (s) => {\n      const { [providerName]: _, ...remaining } = s.externalSkillMetadata ?? {};\n      return operations.updateSkill(ctx.db, {\n        projectId,\n        skillId: s.id,\n        externalSkillMetadata: remaining,\n      });\n    }),\n);\n```\n\n**Reference:** `apps/web/server/api/routers/project.ts` lines 863-880\n\n### Rules\n\n- If a child record has no meaning without its parent, use `onDelete: \"cascade\"` in the schema\n- If deletion requires multi-step cleanup or external API calls, wrap in a transaction\n- When replacing a resource, clear dependent metadata so dependents re-sync\n- Always delete children before the parent in manual cascades\n- Check for affected dependents and document the cascade chain in code comments\n\n## Validation Errors\n\nEvery error must say what went wrong and what to do instead. Include the specific value that failed and an example of what's valid.\n\n```typescript\n// Zod: include format example\nname: z.string().min(1, \"Name is required\").max(64)\n  .regex(SKILL_NAME_PATTERN, \"Name must be kebab-case (e.g. scheduling-assistant)\"),\n\n// tRPC: include the conflicting value\nthrow new TRPCError({\n  code: \"CONFLICT\",\n  message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n});\n```\n\n### Error code mapping\n\n| Situation               | tRPC Code               | When to use                           |\n| ----------------------- | ----------------------- | ------------------------------------- |\n| Resource not found      | `NOT_FOUND`             | ID lookup returned null               |\n| Input validation failed | `BAD_REQUEST`           | Zod schema or business rule violation |\n| Duplicate resource      | `CONFLICT`              | Name/key already exists               |\n| Unexpected failure      | `INTERNAL_SERVER_ERROR` | Catch-all for unhandled errors        |\n\n## Duplicate Detection\n\nDefault to database unique constraints with custom exception mapping. Only use pre-creation queries when no DB constraint exists.\n\n```typescript\n// packages/db/src/operations/skills.ts\nconst PG_UNIQUE_VIOLATION = \"23505\";\nconst SKILLS_NAME_UNIQUE_CONSTRAINT = \"skills_project_id_name_idx\";\n\nexport class SkillNameConflictError extends Error {\n  constructor(name: string) {\n    super(`A skill named \"${name}\" already exists in this project`);\n    this.name = \"SkillNameConflictError\";\n  }\n}\n\nexport async function createSkill(\n  db: HydraDb,\n  data: NewSkill,\n): Promise<DBSkill> {\n  try {\n    const [skill] = await db.insert(schema.skills).values(data).returning();\n    return skill;\n  } catch (error) {\n    if (isSkillNameConflict(error)) {\n      throw new SkillNameConflictError(data.name);\n    }\n    throw error;\n  }\n}\n```\n\n### Pre-creation queries (fallback)\n\nWhen no unique DB constraint exists, query before inserting:\n\n```typescript\nconst existingKeys = await getExistingServerKeys(ctx.db, projectId);\nif (existingKeys.includes(serverKey)) {\n  throw new TRPCError({\n    code: \"CONFLICT\",\n    message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n  });\n}\n```\n\n**Reference:** `apps/web/server/api/routers/tools.ts` lines 119-126\n\n## Orphan Prevention\n\nWhen creating a resource that syncs to an external API, roll back on failure:\n\n```typescript\n// apps/web/server/api/routers/skills.ts\n// Create in DB first, then sync to provider\nconst skill = await operations.createSkill(ctx.db, { ... });\n\n// If provider sync fails, delete the DB record\ntry {\n  await createSkillOnProviderAndPersist(ctx.db, input.projectId, skill);\n} catch (error) {\n  await operations.deleteSkill(ctx.db, input.projectId, skill.id);\n  throw error;\n}\n```\n\n**Rules:**\n\n- Create the DB record first (gives you an ID for the external API call)\n- If the external sync fails, delete the DB record to avoid orphans\n- The user sees an error and can retry, rather than seeing a broken record\n- For batch operations, use `Promise.allSettled` and clean up partial failures\n\n**Reference:** `apps/web/server/api/routers/skills.ts` lines 195-204\n\n## Checklist\n\nWhen building a new CRUD operation:\n\n```\nResource Lifecycle Checklist:\n- [ ] Delete cascades documented (which dependents are affected?)\n- [ ] Database-level cascades set up for simple parent-child FK relationships\n- [ ] Manual cascade logic wrapped in a transaction for complex cleanup\n- [ ] All Zod validation messages are descriptive with examples\n- [ ] TRPCError messages include the specific value that caused the error\n- [ ] Duplicate detection before creation (custom exception or pre-query)\n- [ ] Error codes are correct (CONFLICT for duplicates, NOT_FOUND for missing)\n- [ ] External API sync failures roll back the DB record\n- [ ] Resource replacement clears dependent metadata\n```\n","frontmatter":{"name":"api-resource-lifecycle","description":"Guides CRUD operations for API resources with cascading dependencies, descriptive validation, and orphan prevention. Use when adding delete/remove operations, creating validation logic, building resources that depend on other resources, or when the user mentions \"cascade delete\", \"orphan records\", \"duplicate detection\", \"validation errors\", \"resource cleanup\", or \"rollback on failure\".","metadata":{"internal":true}},"isInternal":true,"tokens":1721,"sizeBytes":7849},{"name":"SKILL.md","path":".claude/skills/building-settings-ui/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/building-settings-ui/SKILL.md","title":"building-settings-ui","category":"anthropic-skill","format":"markdown","content":"---\nname: building-settings-ui\ndescription: >-\n  Use this skill when adding or modifying settings UI in Tambo Cloud. Covers where a new settings\n  section belongs (Agent tab vs Settings tab), and the component patterns used across both pages\n  (card layout, toasts, confirmation dialogs, destructive styling, save behavior conventions).\n  Triggers on \"add a new settings section\", \"where should X go?\", \"settings UI\", \"settings page\",\n  \"agent page\", or any work touching apps/web/components/dashboard-components/project-details/,\n  project-settings.tsx, or agent-settings.tsx.\n  Not for full-stack feature building (DB, tRPC, tests); those patterns will get their own skills.\nmetadata:\n  internal: true\n---\n\n# Building Settings UI\n\nGuide for placing and styling settings sections in the Tambo Cloud dashboard. Covers two concerns: where a feature belongs (which tab/page), and how to build the UI component to match existing patterns.\n\n## Architecture\n\nSettings are split across two top-level tabs in the project layout:\n\n- **Agent tab** (`/[projectId]/agent`) - How the AI agent behaves\n- **Settings tab** (`/[projectId]/settings`) - Project infrastructure and access\n\nEach tab renders a flat vertical stack of Card components. There is no sidebar navigation; each page is short enough to scroll naturally.\n\n### Tab layout\n\n```\nOverview | Observability | Agent | Settings\n```\n\n- Layout file: `apps/web/app/(authed)/(dashboard)/[projectId]/layout.tsx`\n- Agent page: `apps/web/app/(authed)/(dashboard)/[projectId]/agent/page.tsx`\n- Settings page: `apps/web/app/(authed)/(dashboard)/[projectId]/settings/page.tsx`\n\n## Gotchas\n\n1. **Do not add a new top-level tab** without explicit team alignment. Current tabs (Overview, Observability, Agent, Settings) have been stable.\n2. **`EditWithTamboButton` goes inside `CardTitle`**, not as a sibling of `CardHeader`. It must have a `description` prop explaining what the section configures.\n3. **Invalidate the query before toasting** in `onSuccess`. Reversing the order can show a success toast while the UI still displays old data.\n4. **Use `DeleteConfirmationDialog`**, never inline `AlertDialog` for destructive confirmations.\n5. **Use `text-destructive` semantic color**, never `text-red-500`. Cancel/discard buttons are NOT destructive.\n\n---\n\n## Feature Placement\n\n### Agent Tab Sections\n\n| #   | Section             | What it configures                                 | Component                        |\n| --- | ------------------- | -------------------------------------------------- | -------------------------------- |\n| 1   | Model               | Provider + model selection, API key, custom params | `provider-key-section.tsx`       |\n| 2   | Custom Instructions | System prompt, prompt override toggle              | `custom-instructions-editor.tsx` |\n| 3   | Skills              | Skill definitions and imports                      | `skills-section.tsx`             |\n| 4   | Tool Call Limit     | Max tool calls per response                        | `tool-call-limit-editor.tsx`     |\n| 5   | MCP                 | MCP server URLs + headers                          | `available-mcp-servers.tsx`      |\n\n**Container:** `apps/web/components/dashboard-components/agent-settings.tsx`\n\n### Settings Tab Sections\n\n| #   | Section        | What it configures             | Component                  |\n| --- | -------------- | ------------------------------ | -------------------------- |\n| 1   | Name           | Project display name           | `project-name-section.tsx` |\n| 2   | API Keys       | API key list + create          | `api-key-list.tsx`         |\n| 3   | Authentication | OAuth mode, token requirements | `oauth-settings.tsx`       |\n| 4   | Danger Zone    | Project deletion               | `danger-zone-section.tsx`  |\n\n**Container:** `apps/web/components/dashboard-components/project-settings.tsx`\n\nAll section components live in `apps/web/components/dashboard-components/project-details/`.\n\n### Placement Decision Tree\n\n1. **Configures AI agent behavior?** (model selection, prompts, tools, memory, context) -> **Agent tab**\n2. **Configures project infrastructure?** (API keys, naming, deletion, billing, webhooks) -> **Settings tab**\n3. **Configures who can access?** (auth, tokens, team members, permissions) -> **Settings tab**\n4. **Monitoring or debugging view?** -> **Observability tab**\n5. **High-level summary or status?** -> **Overview tab**\n6. **None of the above?** -> Ask the user.\n\n### Conditional and Dependent Settings\n\nSome settings only apply when another setting is in a specific state. Follow these patterns:\n\n**Show but warn (soft dependency).** The section renders normally but displays an `Alert` when the dependency isn't met. The user can still see and configure the setting. Use this when the feature exists but won't work at runtime.\n\nExample: Skills section shows a provider compatibility notice when the selected provider doesn't support skills:\n\n```tsx\n// skills-section.tsx\nconst isProviderSupported = SKILLS_SUPPORTED_PROVIDERS.has(\n  defaultLlmProviderName,\n);\n// Renders full skills UI + warning Alert if !isProviderSupported\n```\n\n**Conditionally pass props (data dependency).** The parent reads one setting and passes it as a prop so the child can adapt its behavior. Use this when the child's content or options change based on the parent's state.\n\nExample: MCP servers section receives `providerType` to toggle agent-mode-specific UI:\n\n```tsx\n// agent-settings.tsx\n<AvailableMcpServers providerType={projectData?.providerType} />;\n// available-mcp-servers.tsx\nconst isAgentMode = providerType === AiProviderType.AGENT;\n```\n\nExample: Custom LLM parameters change available suggestions based on provider and model:\n\n```tsx\n// provider-key-section.tsx passes selectedProvider to the parameter editor\n<CustomLlmParametersEditor selectedProvider={selectedProvider} />\n```\n\n**Rules for new dependent settings:**\n\n1. Never hide a section entirely based on another setting's state. Always render the card; use an Alert or disabled state to communicate the dependency.\n2. The warning message must name the dependency and tell the user what to change (e.g., \"Switch to a supported provider to enable skills\").\n3. Keep dependency checks in the section component, not the container. The container (`agent-settings.tsx`, `project-settings.tsx`) should pass data, not make visibility decisions.\n4. If a setting depends on state from a different tab, pass it through the shared project query (`api.project.getProject`) rather than cross-tab state.\n\n### Adding a New Section\n\n1. **Create the component** in `project-details/` following the Card layout pattern below.\n2. **Import and render** in the correct container (`agent-settings.tsx` or `project-settings.tsx`).\n3. **Update the skeleton** in `settings-skeletons.tsx` (either `AgentPageSkeleton` or `SettingsPageSkeleton`).\n\n---\n\n## Component Patterns\n\n### Card Layout\n\nEvery settings section uses `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardContent` from `@/components/ui/card`.\n\n```tsx\n<Card>\n  <CardHeader>\n    <CardTitle className=\"text-lg font-semibold\">\n      Section Name\n      <EditWithTamboButton description=\"Configure section settings...\" />\n    </CardTitle>\n    <CardDescription className=\"text-sm font-sans text-foreground\">\n      Description of what this section does.\n    </CardDescription>\n  </CardHeader>\n  <CardContent className=\"space-y-4\">{/* Content */}</CardContent>\n</Card>\n```\n\n### Toast Notifications\n\nEvery mutation shows a toast on both success and error. Import `useToast` from `@/hooks/use-toast`.\n\n```tsx\nconst mutation = api.someRoute.someMutation.useMutation({\n  onSuccess: async () => {\n    await utils.someRoute.someQuery.invalidate();\n    toast({ title: \"Success\", description: \"Setting updated successfully\" });\n  },\n  onError: () => {\n    toast({\n      title: \"Error\",\n      description: \"Failed to update setting\",\n      variant: \"destructive\",\n    });\n  },\n});\n```\n\nNever skip the error toast.\n\n### Confirmation Dialogs\n\nAll destructive actions use `DeleteConfirmationDialog` from `@/components/dashboard-components/delete-confirmation-dialog`:\n\n```tsx\nconst [alertState, setAlertState] = useState<{\n  show: boolean;\n  title: string;\n  description: string;\n  data?: { id: string };\n}>({ show: false, title: \"\", description: \"\" });\n\n<DeleteConfirmationDialog\n  mode=\"single\"\n  alertState={alertState}\n  setAlertState={setAlertState}\n  onConfirm={handleConfirmDelete}\n/>;\n```\n\nTitle includes the item name (`Delete \"${name}\"?`). Description warns the action cannot be undone.\n\n### Destructive Action Styling\n\n```tsx\n<Button\n  variant=\"ghost\"\n  size=\"icon\"\n  className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n```\n\nUse `Trash2` from `lucide-react`. Use `hover:bg-destructive/10` for ghost variant hover.\n\n### Save Behavior\n\n**Toggles: Immediate save.** `onCheckedChange` fires the mutation directly. Include `aria-label` with state context.\n\n**Form fields: Edit/Save/Cancel.** Track `isEditing`, `savedValue`, and `displayValue` state. Cancel reverts to `savedValue`. Save button disabled during mutation, shows \"Saving...\". `autoFocus` on first input when entering edit mode.\n\n**Reference implementations:** `custom-instructions-editor.tsx` (edit/save/cancel), `tool-call-limit-editor.tsx` (simpler form), `project-name-section.tsx` (basic edit/save/cancel).\n\n### Danger Zone Pattern\n\nFor irreversible destructive actions, use the Danger Zone card pattern:\n\n```tsx\n<Card className=\"border-destructive/50\">\n  <CardHeader>\n    <CardTitle>Danger Zone</CardTitle>\n    <CardDescription>Warning about permanence.</CardDescription>\n  </CardHeader>\n  <CardContent>\n    <Button\n      variant=\"ghost\"\n      className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n      aria-label=\"Delete this project\"\n    >\n      Delete this project\n    </Button>\n  </CardContent>\n</Card>\n```\n\nThe `DeleteConfirmationDialog` should be owned by the parent component that handles the mutation and post-delete navigation.\n","frontmatter":{"name":"building-settings-ui","description":"Use this skill when adding or modifying settings UI in Tambo Cloud. Covers where a new settings section belongs (Agent tab vs Settings tab), and the component patterns used across both pages (card layout, toasts, confirmation dialogs, destructive styling, save behavior conventions). Triggers on \"add a new settings section\", \"where should X go?\", \"settings UI\", \"settings page\", \"agent page\", or any work touching apps/web/components/dashboard-components/project-details/, project-settings.tsx, or agent-settings.tsx. Not for full-stack feature building (DB, tRPC, tests); those patterns will get their own skills.","metadata":{"internal":true}},"isInternal":true,"tokens":2245,"sizeBytes":10082},{"name":"examples.md","path":".claude/skills/compound-components/examples.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/compound-components/examples.md","title":"Compound-components Skill","category":"anthropic-skill","format":"markdown","content":"# Compound-components Skill\n\nPath: `.claude/skills/compound-components/examples.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/compound-components/examples.md)","tokens":300,"sizeBytes":215},{"name":"SKILL.md","path":".claude/skills/compound-components/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/compound-components/SKILL.md","title":"building-compound-components","category":"anthropic-skill","format":"markdown","content":"---\nname: building-compound-components\ndescription: Creates unstyled compound components that separate business logic from styles. Use when building headless UI primitives, creating component libraries, implementing Radix-style namespaced components, or when the user mentions \"compound components\", \"headless\", \"unstyled\", \"primitives\", or \"render props\".\nmetadata:\n  internal: true\n---\n\n# Building Compound Components\n\nCreate unstyled, composable React components following the Radix UI / Base UI pattern. Components expose behavior via context while consumers control rendering.\n\n## Project Rules\n\nThese rules are specific to this codebase and override general patterns.\n\n### Hooks Are Internal\n\nHooks are implementation details, not public API. **Never export hooks from the index.**\n\n```tsx\n// index.tsx - CORRECT\nexport const Component = {\n  Root: ComponentRoot,\n  Content: ComponentContent,\n};\nexport type { ComponentRootProps, ComponentContentRenderProps };\n\n// index.tsx - WRONG\nexport { useComponentContext }; // Don't export hooks\n```\n\nConsumers access state via **render props**, not hooks. When styled wrappers in the **same package** need hook access, import directly from the source file:\n\n```tsx\nimport { useComponentContext } from \"../base/component/component-context\";\n```\n\n### No Custom Data Fetching in Primitives\n\nBase components can use `@tambo-ai/react` SDK hooks (components require Tambo provider anyway). **Custom data fetching logic** (combining sources, external providers) belongs in the styled layer.\n\n```tsx\n// OK - SDK hooks in primitive\nconst Root = ({ children }) => {\n  const { value, setValue, submit } = useTamboThreadInput();\n  const { isIdle, cancel } = useTamboThread();\n  return <Context.Provider value={{ value, setValue, isIdle }}>{children}</Context.Provider>;\n};\n\n// WRONG - custom data fetching in primitive\nconst Textarea = ({ resourceProvider }) => {\n  const { data: mcpResources } = useTamboMcpResourceList(search);\n  const externalResources = useFetchExternal(resourceProvider);\n  const combined = [...mcpResources, ...externalResources];\n  return <div>{combined.map(...)}</div>;\n};\n```\n\n### Pre-computed Props Arrays for Collections\n\nWhen exposing collections via render props, **pre-compute all props in a memoized array** rather than providing a getter function.\n\n```tsx\n// AVOID - getter function pattern\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n  const getItemProps = (index: number) => ({\n    /* new object every call */\n  });\n  return children({ items: rawItems, getItemProps });\n};\n\n// PREFERRED - pre-computed array\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n\n  const items = React.useMemo<ItemRenderProps[]>(\n    () =>\n      rawItems.map((item, index) => ({\n        item,\n        index,\n        isSelected: selectedId === item.id,\n        onSelect: () => setSelectedId(item.id),\n        onRemove: () => removeItem(item.id),\n      })),\n    [rawItems, selectedId, removeItem],\n  );\n\n  return children({ items });\n};\n```\n\n## Workflow\n\nCopy this checklist and track progress:\n\n```\nCompound Component Progress:\n- [ ] Step 1: Create context file\n- [ ] Step 2: Create Root component\n- [ ] Step 3: Create consumer components\n- [ ] Step 4: Create namespace export (index.tsx)\n- [ ] Step 5: Verify all guidelines met\n```\n\n### Step 1: Create context file\n\n```\nmy-component/\n├── index.tsx\n├── component-context.tsx\n├── component-root.tsx\n├── component-item.tsx\n└── component-content.tsx\n```\n\nCreate a context with a null default and a hook that throws on missing provider:\n\n```tsx\n// component-context.tsx\nconst ComponentContext = React.createContext<ComponentContextValue | null>(\n  null,\n);\n\nexport function useComponentContext() {\n  const context = React.useContext(ComponentContext);\n  if (!context) {\n    throw new Error(\"Component parts must be used within Component.Root\");\n  }\n  return context;\n}\n\nexport { ComponentContext };\n```\n\n### Step 2: Create Root component\n\nRoot manages state and provides context. Use `forwardRef`, support `asChild` via Radix `Slot`, and expose state via data attributes:\n\n```tsx\n// component-root.tsx\nexport const ComponentRoot = React.forwardRef<\n  HTMLDivElement,\n  ComponentRootProps\n>(({ asChild, defaultOpen = false, children, ...props }, ref) => {\n  const [isOpen, setIsOpen] = React.useState(defaultOpen);\n  const Comp = asChild ? Slot : \"div\";\n\n  return (\n    <ComponentContext.Provider\n      value={{ isOpen, toggle: () => setIsOpen(!isOpen) }}\n    >\n      <Comp ref={ref} data-state={isOpen ? \"open\" : \"closed\"} {...props}>\n        {children}\n      </Comp>\n    </ComponentContext.Provider>\n  );\n});\nComponentRoot.displayName = \"Component.Root\";\n```\n\n### Step 3: Create consumer components\n\nChoose the composition pattern based on need:\n\n**Direct children** (simplest, for static content):\n\n```tsx\nconst Content = ({ children, className, ...props }) => {\n  const { data } = useComponentContext();\n  return (\n    <div className={className} {...props}>\n      {children}\n    </div>\n  );\n};\n```\n\n**Render prop** (when consumer needs internal state):\n\n```tsx\nconst Content = ({ children, ...props }) => {\n  const { data, isLoading } = useComponentContext();\n  const content =\n    typeof children === \"function\" ? children({ data, isLoading }) : children;\n  return <div {...props}>{content}</div>;\n};\n```\n\n**Sub-context** (for lists where each item needs own context):\n\n```tsx\nconst Steps = ({ children }) => {\n  const { reasoning } = useMessageContext();\n  return (\n    <StepsContext.Provider value={{ steps: reasoning }}>\n      {children}\n    </StepsContext.Provider>\n  );\n};\n\nconst Step = ({ children, index }) => {\n  const { steps } = useStepsContext();\n  return (\n    <StepContext.Provider value={{ step: steps[index], index }}>\n      {children}\n    </StepContext.Provider>\n  );\n};\n```\n\n### Step 4: Create namespace export\n\n```tsx\n// index.tsx\nexport const Component = {\n  Root: ComponentRoot,\n  Trigger: ComponentTrigger,\n  Content: ComponentContent,\n};\n\n// Re-export types only - never hooks\nexport type { ComponentRootProps } from \"./component-root\";\nexport type { ComponentContentProps } from \"./component-content\";\n```\n\n### Step 5: Verify guidelines\n\n- **No styles in primitives** - consumers control all styling via className/props\n- **Data attributes for CSS** - expose state like `data-state=\"open\"`, `data-disabled`, `data-loading`\n- **Support asChild** - let consumers swap the underlying element via Radix `Slot`\n- **Forward refs** - always use `forwardRef`\n- **Display names** - set for DevTools (`Component.Root`, `Component.Item`)\n- **Throw on missing context** - fail fast with clear error messages\n- **Export types** - consumers need `ComponentProps`, `RenderProps` interfaces\n- **Hooks stay internal** - never export from index, expose state via render props\n- **SDK hooks OK, custom fetching not** - `@tambo-ai/react` hooks are fine, combining logic goes in styled layer\n- **Pre-compute collection props** - use `useMemo` arrays, not getter functions\n\n## Pattern Selection\n\n| Scenario             | Pattern         | Why                             |\n| -------------------- | --------------- | ------------------------------- |\n| Static content       | Direct children | Simplest, most flexible         |\n| Need internal state  | Render prop     | Explicit state access           |\n| List/iteration       | Sub-context     | Each item gets own context      |\n| Element polymorphism | asChild         | Change underlying element       |\n| CSS-only styling     | Data attributes | No JS needed for style variants |\n\n## Anti-Patterns\n\n- **Hardcoded styles** - primitives should be unstyled\n- **Prop drilling** - use context instead\n- **Missing error boundaries** - throw when context is missing\n- **Inline functions in render prop types** - define proper interfaces\n- **Default exports** - use named exports in namespace object\n- **Exporting hooks** - hooks are internal; expose state via render props\n- **Custom data fetching in primitives** - SDK hooks are fine, but combining/external fetching belongs in styled layer\n- **Re-implementing base logic** - styled wrappers should compose, not duplicate\n- **Getter functions for collections** - pre-compute props arrays in useMemo instead\n","frontmatter":{"name":"building-compound-components","description":"Creates unstyled compound components that separate business logic from styles. Use when building headless UI primitives, creating component libraries, implementing Radix-style namespaced components, or when the user mentions \"compound components\", \"headless\", \"unstyled\", \"primitives\", or \"render props\".","metadata":{"internal":true}},"isInternal":true,"tokens":1880,"sizeBytes":8331},{"name":"real-world-example.md","path":".claude/skills/creating-styled-wrappers/references/real-world-example.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/creating-styled-wrappers/references/real-world-example.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `.claude/skills/creating-styled-wrappers/references/real-world-example.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/creating-styled-wrappers/references/real-world-example.md)","tokens":300,"sizeBytes":258},{"name":"SKILL.md","path":".claude/skills/creating-styled-wrappers/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/creating-styled-wrappers/SKILL.md","title":"creating-styled-wrappers","category":"anthropic-skill","format":"markdown","content":"---\nname: creating-styled-wrappers\ndescription: Creates styled wrapper components that compose headless/base compound components. Use when refactoring styled components to use base primitives, implementing opinionated design systems on top of headless components, or when the user mentions \"use base components\", \"compose primitives\", \"styled wrapper\", or \"refactor to use base\".\nmetadata:\n  internal: true\n---\n\n# Styling Compound Wrappers\n\nCreate styled wrapper components that compose headless base compound components. This skill complements `building-compound-components` (which builds the base primitives) by focusing on **how to properly consume and wrap them** with styling and additional behavior.\n\n**Real-world example**: See [references/real-world-example.md](references/real-world-example.md) for a complete before/after MessageInput refactoring.\n\n## Core Principle: Compose, Don't Duplicate\n\nStyled wrappers should **compose** base components, not **re-implement** their logic.\n\n```tsx\n// WRONG - re-implementing what base already does\nconst StyledInput = ({ children, className }) => {\n  const { value, setValue, submit } = useTamboThreadInput(); // Duplicated!\n  const [isDragging, setIsDragging] = useState(false); // Duplicated!\n  const handleDrop = useCallback(/* ... */); // Duplicated!\n\n  return (\n    <form onDrop={handleDrop} className={className}>\n      {children}\n    </form>\n  );\n};\n\n// CORRECT - compose the base component\nconst StyledInput = ({ children, className, variant }) => {\n  return (\n    <BaseInput.Root className={cn(inputVariants({ variant }), className)}>\n      <BaseInput.Content className=\"rounded-xl data-[dragging]:border-dashed\">\n        {children}\n      </BaseInput.Content>\n    </BaseInput.Root>\n  );\n};\n```\n\n## Refactoring Workflow\n\nCopy this checklist and track progress:\n\n```\nStyled Wrapper Refactoring:\n- [ ] Step 1: Identify duplicated logic\n- [ ] Step 2: Import base components\n- [ ] Step 3: Wrap with Base Root\n- [ ] Step 4: Apply state-based styling and behavior\n- [ ] Step 5: Wrap sub-components with styling\n- [ ] Step 6: Final verification\n```\n\n### Step 1: Identify Duplicated Logic\n\nLook for patterns that indicate logic should come from base:\n\n- SDK hooks (`useTamboThread`, `useTamboThreadInput`, etc.)\n- Context creation (`React.createContext`)\n- State management that mirrors base component state\n- Event handlers (drag, submit, etc.) that base components handle\n\n### Step 2: Import Base Components\n\n```tsx\nimport { MessageInput as MessageInputBase } from \"@tambo-ai/react-ui-base/message-input\";\n```\n\n### Step 3: Wrap with Base Root\n\nReplace custom context/state management with the base Root:\n\n```tsx\n// Before\nconst MessageInput = ({ children, variant }) => {\n  return (\n    <MessageInputInternal variant={variant}>{children}</MessageInputInternal>\n  );\n};\n\n// After\nconst MessageInput = ({ children, variant, className }) => {\n  return (\n    <MessageInputBase.Root className={cn(variants({ variant }), className)}>\n      {children}\n    </MessageInputBase.Root>\n  );\n};\n```\n\n### Step 4: Apply State-Based Styling and Behavior\n\nState access follows a hierarchy — use the simplest option that works:\n\n1. **Data attributes** (preferred for styling) — base components expose `data-*` attributes\n2. **Render props** (for behavior changes) — use when rendering different components\n3. **Context hooks** (for sub-components) — OK for styled sub-components needing deep context access\n\n```tsx\n// BEST - data-* classes for styling, render props only for behavior\n// Note: use `data-[dragging]:*` syntax (v3-compatible), not `data-dragging:*` (v4 only)\nconst StyledContent = ({ children }) => (\n  <BaseComponent.Content\n    className={cn(\n      \"group rounded-xl border\",\n      \"data-[dragging]:border-dashed data-[dragging]:border-emerald-400\",\n    )}\n  >\n    {({ elicitation, resolveElicitation }) => (\n      <>\n        {/* Drop overlay uses group-data-* for styling */}\n        <div className=\"hidden group-data-[dragging]:flex absolute inset-0 bg-emerald-50/90\">\n          <p>Drop files here</p>\n        </div>\n\n        {elicitation ? (\n          <ElicitationUI\n            request={elicitation}\n            onResponse={resolveElicitation}\n          />\n        ) : (\n          children\n        )}\n      </>\n    )}\n  </BaseComponent.Content>\n);\n\n// OK - styled sub-components can use context hook for deep access\nconst StyledTextarea = ({ placeholder }) => {\n  const { value, setValue, handleSubmit, editorRef } = useMessageInputContext();\n  return (\n    <CustomEditor\n      ref={editorRef}\n      value={value}\n      onChange={setValue}\n      onSubmit={handleSubmit}\n      placeholder={placeholder}\n    />\n  );\n};\n```\n\n**When to use context hooks vs render props:**\n\n- Render props: when the parent wrapper needs state for behavior changes\n- Context hooks: when a styled sub-component needs values not exposed via render props\n\n### Step 5: Wrap Sub-Components\n\n```tsx\n// Submit button\nconst SubmitButton = ({ className, children }) => (\n  <BaseComponent.SubmitButton className={cn(\"w-10 h-10 rounded-lg\", className)}>\n    {({ showCancelButton }) =>\n      children ?? (showCancelButton ? <Square /> : <ArrowUp />)\n    }\n  </BaseComponent.SubmitButton>\n);\n\n// Error\nconst Error = ({ className }) => (\n  <BaseComponent.Error className={cn(\"text-sm text-destructive\", className)} />\n);\n\n// Staged images - base pre-computes props array, just iterate\nconst StagedImages = ({ className }) => (\n  <BaseComponent.StagedImages className={cn(\"flex gap-2\", className)}>\n    {({ images }) =>\n      images.map((imageProps) => (\n        <ImageBadge key={imageProps.image.id} {...imageProps} />\n      ))\n    }\n  </BaseComponent.StagedImages>\n);\n```\n\n### Step 6: Final Verification\n\n```\nFinal Checks:\n- [ ] No duplicate context creation\n- [ ] No duplicate SDK hooks in root wrappers\n- [ ] No duplicate state management or event handlers\n- [ ] Base namespace imported and `Base.Root` used as wrapper\n- [ ] `data-*` classes used for styling (with `group-data-*` for children)\n- [ ] Render props used only for rendering behavior changes\n- [ ] Base sub-components wrapped with styling\n- [ ] Icon factories passed from styled layer to base hooks\n- [ ] Visual sub-components and CSS variants stay in styled layer\n```\n\n## What Belongs in Styled Layer\n\n### Icon Factories\n\nWhen base hooks need icons, pass a factory function:\n\n```tsx\n// Base hook accepts optional icon factory\nexport function useCombinedResourceList(\n  providers: ResourceProvider[] | undefined,\n  search: string,\n  createMcpIcon?: (serverName: string) => React.ReactNode,\n) {\n  /* ... */\n}\n\n// Styled layer provides the factory\nconst resources = useCombinedResourceList(providers, search, (serverName) => (\n  <McpServerIcon name={serverName} className=\"w-4 h-4\" />\n));\n```\n\n### CSS Variants\n\n```tsx\nconst inputVariants = cva(\"w-full\", {\n  variants: {\n    variant: {\n      default: \"\",\n      solid: \"[&>div]:shadow-xl [&>div]:ring-1\",\n      bordered: \"[&>div]:border-2\",\n    },\n  },\n});\n```\n\n### Layout Logic, Visual Sub-Components, Custom Data Fetching\n\nThese all stay in the styled layer. Base handles behavior; styled handles presentation.\n\n## Type Handling\n\nHandle ref type differences between base and styled components:\n\n```tsx\n// Base context may have RefObject<T | null>\n// Styled component may need RefObject<T>\n<TextEditor ref={editorRef as React.RefObject<TamboEditor>} />\n```\n\n## Anti-Patterns\n\n- **Re-implementing base logic** - if base handles it, compose it\n- **Using render props for styling** - prefer `data-*` classes; render props are for behavior changes\n- **Duplicating context in wrapper** - use base Root which provides context\n- **Hardcoding icons in base hooks** - use factory functions to keep styling in styled layer\n","frontmatter":{"name":"creating-styled-wrappers","description":"Creates styled wrapper components that compose headless/base compound components. Use when refactoring styled components to use base primitives, implementing opinionated design systems on top of headless components, or when the user mentions \"use base components\", \"compose primitives\", \"styled wrapper\", or \"refactor to use base\".","metadata":{"internal":true}},"isInternal":true,"tokens":1810,"sizeBytes":7752},{"name":"SKILL.md","path":".claude/skills/validating-accessibility/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/validating-accessibility/SKILL.md","title":"validating-accessibility","category":"anthropic-skill","format":"markdown","content":"---\nname: validating-accessibility\ndescription: >-\n  Use this skill when creating, modifying, or reviewing any .tsx component in apps/web, even if\n  the user doesn't mention \"accessibility.\" Covers semantic HTML, aria labels, navigation landmarks,\n  forms, dialogs, and keyboard navigation. Trigger on: adding buttons, links, toggles, icons, or\n  any interactive element; building or editing forms; adding dialogs or modals; reviewing UI code.\n  Includes inline verification patterns for scanning violations. Not for styling or layout changes\n  that don't involve interactive elements.\nmetadata:\n  internal: true\n---\n\n# Accessibility Checklist\n\nEvery UI component in `apps/web` must meet these standards. No partial compliance.\n\n## Gotchas\n\n- **`role=\"button\"` divs may exist in the codebase** -- fix them when touching affected files. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n- **Nested interactive elements** -- when replacing a `<div role=\"button\">` that contains a child `<button>` (e.g., a copy button inside a collapsible toggle), do not just swap the outer div to `<button>`. That creates invalid nested buttons. Instead, restructure into sibling elements: a toggle `<button>` and a separate action `<button>` side by side in a flex container.\n- **Standalone inputs outside react-hook-form need manual ID pairing** -- use `useId()` with `htmlFor`/`id`. The shadcn `<FormField>` handles this automatically, but raw `<Input>` does not.\n- **AlertDialog vs Dialog** -- use `AlertDialog` for destructive confirmations (requires `AlertDialogTitle` + `AlertDialogDescription`). Use `Dialog` for content/forms. Never build custom modal overlays.\n- **Icon-only buttons without `aria-label`** are common in new code. Every icon-only button needs one, and it must include context: `Delete API key ${keyName}`, not just \"Delete\".\n\n## Semantic HTML\n\nUse native elements. Never recreate `<button>` behavior with `<div role=\"button\">` + keyboard handlers.\n\n| Interaction      | Element                                                |\n| ---------------- | ------------------------------------------------------ |\n| Clickable action | `<button>` or `<Button>` from `@/components/ui/button` |\n| Navigation link  | `<Link>` (Next.js) or `<a>`                            |\n| Navigation group | `<nav>` with descriptive `aria-label`                  |\n| Item list        | `<ul>`/`<ol>` + `<li>`                                 |\n| Section heading  | `<h1>`-`<h6>` in order, never skip levels              |\n\n## Aria Labels\n\nEvery interactive element without visible text needs `aria-label` with both action AND target:\n\n```tsx\n<Button size=\"icon\" aria-label={`Delete API key ${keyName}`}>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n\n<Switch aria-label={`${enabled ? \"Disable\" : \"Enable\"} skill ${skillName}`} />\n```\n\nPrefer state-aware labels (\"Copied!\" vs \"Copy\"). Buttons with visible text skip `aria-label`.\n\n**Reference implementations:** `copy-button.tsx` (state-aware), `context-attachment-badge.tsx` (contextual remove), `thread-table-header.tsx` (sort state) -- all in `apps/web/components/`.\n\n## Navigation Landmarks\n\nWrap navigation groups in `<nav>` with a unique `aria-label` per region on the page.\n\n## Forms\n\nUse shadcn Form components from `@/components/ui/form` (`FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormMessage`). They handle ID generation, label association, `aria-describedby`, and `aria-invalid` automatically.\n\nFor standalone inputs outside react-hook-form, pair `useId()` with `htmlFor`/`id`. Never use placeholder as label substitute.\n\n## Keyboard Navigation\n\n- Only `tabIndex={0}` or `tabIndex={-1}` (never positive values)\n- Never remove focus outlines\n- Prefer `<button>` over manual Enter/Space handlers\n\n## Verification\n\nScan `apps/web/components` for common violations. For each check, grep for the pattern and fix any matches found.\n\n### Check 1: `role=\"button\"` on non-button elements\n\nSearch for `role=\"button\"` in `.tsx` files. Flag `<div` or `<span` elements with this attribute; they should be `<button>` or `<Button>` instead. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n\n**Pattern:** `role=\"button\"`\n\n### Check 2: `<div onClick>` patterns\n\nSearch for `<div` elements with `onClick` handlers. These should use `<button>` instead for proper keyboard support.\n\n**Pattern:** `<div[^>]*onClick`\n\n### Check 3: Positive tabIndex values\n\nSearch for `tabIndex` with values greater than 0. Only `tabIndex={0}` and `tabIndex={-1}` are allowed.\n\n**Pattern:** `tabIndex={[1-9]`\n\n### Check 4: Icon buttons missing aria-label\n\nSearch for `size=\"icon\"` in `.tsx` files. For each match, check surrounding lines (5-10 above and below) for `aria-label` on the same `<Button>` element or an `sr-only` span. Flag buttons that have neither.\n\n**Pattern:** `size=\"icon\"` without nearby `aria-label`\n\n### Manual checks\n\nThese cannot be detected by pattern matching:\n\n- [ ] Form inputs have associated `<label>` elements\n- [ ] Navigation groups use `<nav>` with unique `aria-label`\n- [ ] Dialogs use Radix-based components (AlertDialog or Dialog)\n- [ ] Focus outlines intact\n","frontmatter":{"name":"validating-accessibility","description":"Use this skill when creating, modifying, or reviewing any .tsx component in apps/web, even if the user doesn't mention \"accessibility.\" Covers semantic HTML, aria labels, navigation landmarks, forms, dialogs, and keyboard navigation. Trigger on: adding buttons, links, toggles, icons, or any interactive element; building or editing forms; adding dialogs or modals; reviewing UI code. Includes inline verification patterns for scanning violations. Not for styling or layout changes that don't involve interactive elements.","metadata":{"internal":true}},"isInternal":true,"tokens":1184,"sizeBytes":5168},{"name":"meta.json","path":"docs/content/docs/reference/cli/commands/meta.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/content/docs/reference/cli/commands/meta.json","title":"Commands Skill","category":"anthropic-skill","format":"json","content":"# Commands Skill\n\nPath: `docs/content/docs/reference/cli/commands/meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/content/docs/reference/cli/commands/meta.json)","tokens":300,"sizeBytes":212},{"name":"package.json","path":"packages/backend/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/package.json","title":"Backend Skill","category":"anthropic-skill","format":"json","content":"# Backend Skill\n\nPath: `packages/backend/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/package.json)","tokens":300,"sizeBytes":169},{"name":"tsconfig.build.json","path":"packages/backend/tsconfig.build.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.build.json","title":"Backend Skill","category":"anthropic-skill","format":"json","content":"# Backend Skill\n\nPath: `packages/backend/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.build.json)","tokens":300,"sizeBytes":183},{"name":"tsconfig.json","path":"packages/backend/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.json","title":"Backend Skill","category":"anthropic-skill","format":"json","content":"# Backend Skill\n\nPath: `packages/backend/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.json)","tokens":300,"sizeBytes":171},{"name":"AGENTS.md","path":"packages/client/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/AGENTS.md","title":"Client Skill","category":"anthropic-skill","format":"markdown","content":"# Client Skill\n\nPath: `packages/client/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/AGENTS.md)","tokens":300,"sizeBytes":160},{"name":"CHANGELOG.md","path":"packages/client/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CHANGELOG.md","title":"Client Skill","category":"anthropic-skill","format":"markdown","content":"# Client Skill\n\nPath: `packages/client/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CHANGELOG.md)","tokens":300,"sizeBytes":166},{"name":"CLAUDE.md","path":"packages/client/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CLAUDE.md","title":"Client Skill","category":"anthropic-skill","format":"markdown","content":"# Client Skill\n\nPath: `packages/client/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CLAUDE.md)","tokens":300,"sizeBytes":160},{"name":"package.json","path":"packages/client/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/package.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/package.json)","tokens":300,"sizeBytes":166},{"name":"tsconfig.cjs.json","path":"packages/client/tsconfig.cjs.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.cjs.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/client/tsconfig.cjs.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.cjs.json)","tokens":300,"sizeBytes":176},{"name":"tsconfig.esm.json","path":"packages/client/tsconfig.esm.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.esm.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/client/tsconfig.esm.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.esm.json)","tokens":300,"sizeBytes":176},{"name":"tsconfig.json","path":"packages/client/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.json","title":"Client Skill","category":"anthropic-skill","format":"json","content":"# Client Skill\n\nPath: `packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.json)","tokens":300,"sizeBytes":168},{"name":"package.json","path":"packages/core/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/package.json","title":"Core Skill","category":"anthropic-skill","format":"json","content":"# Core Skill\n\nPath: `packages/core/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/package.json)","tokens":300,"sizeBytes":160},{"name":"tsconfig.json","path":"packages/core/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/tsconfig.json","title":"Core Skill","category":"anthropic-skill","format":"json","content":"# Core Skill\n\nPath: `packages/core/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/tsconfig.json)","tokens":300,"sizeBytes":162},{"name":"_journal.json","path":"packages/db/migrations/meta/_journal.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/_journal.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/_journal.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/_journal.json)","tokens":300,"sizeBytes":190},{"name":"0000_snapshot.json","path":"packages/db/migrations/meta/0000_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0000_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0000_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0000_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0001_snapshot.json","path":"packages/db/migrations/meta/0001_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0001_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0001_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0001_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0002_snapshot.json","path":"packages/db/migrations/meta/0002_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0002_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0002_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0002_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0003_snapshot.json","path":"packages/db/migrations/meta/0003_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0003_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0003_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0003_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0004_snapshot.json","path":"packages/db/migrations/meta/0004_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0004_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0004_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0004_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0005_snapshot.json","path":"packages/db/migrations/meta/0005_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0005_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0005_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0005_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0006_snapshot.json","path":"packages/db/migrations/meta/0006_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0006_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0006_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0006_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0007_snapshot.json","path":"packages/db/migrations/meta/0007_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0007_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0007_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0007_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0008_snapshot.json","path":"packages/db/migrations/meta/0008_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0008_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0008_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0008_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0009_snapshot.json","path":"packages/db/migrations/meta/0009_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0009_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0009_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0009_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0010_snapshot.json","path":"packages/db/migrations/meta/0010_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0010_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0010_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0010_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0011_snapshot.json","path":"packages/db/migrations/meta/0011_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0011_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0011_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0011_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0012_snapshot.json","path":"packages/db/migrations/meta/0012_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0012_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0012_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0012_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0013_snapshot.json","path":"packages/db/migrations/meta/0013_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0013_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0013_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0013_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0014_snapshot.json","path":"packages/db/migrations/meta/0014_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0014_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0014_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0014_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0015_snapshot.json","path":"packages/db/migrations/meta/0015_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0015_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0015_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0015_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0016_snapshot.json","path":"packages/db/migrations/meta/0016_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0016_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0016_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0016_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0017_snapshot.json","path":"packages/db/migrations/meta/0017_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0017_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0017_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0017_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0018_snapshot.json","path":"packages/db/migrations/meta/0018_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0018_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0018_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0018_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0019_snapshot.json","path":"packages/db/migrations/meta/0019_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0019_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0019_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0019_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0020_snapshot.json","path":"packages/db/migrations/meta/0020_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0020_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0020_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0020_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0021_snapshot.json","path":"packages/db/migrations/meta/0021_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0021_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0021_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0021_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0022_snapshot.json","path":"packages/db/migrations/meta/0022_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0022_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0022_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0022_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0023_snapshot.json","path":"packages/db/migrations/meta/0023_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0023_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0023_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0023_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0024_snapshot.json","path":"packages/db/migrations/meta/0024_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0024_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0024_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0024_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0025_snapshot.json","path":"packages/db/migrations/meta/0025_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0025_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0025_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0025_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0026_snapshot.json","path":"packages/db/migrations/meta/0026_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0026_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0026_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0026_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0027_snapshot.json","path":"packages/db/migrations/meta/0027_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0027_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0027_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0027_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0028_snapshot.json","path":"packages/db/migrations/meta/0028_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0028_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0028_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0028_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0029_snapshot.json","path":"packages/db/migrations/meta/0029_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0029_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0029_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0029_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0030_snapshot.json","path":"packages/db/migrations/meta/0030_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0030_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0030_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0030_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0031_snapshot.json","path":"packages/db/migrations/meta/0031_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0031_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0031_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0031_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0032_snapshot.json","path":"packages/db/migrations/meta/0032_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0032_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0032_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0032_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0033_snapshot.json","path":"packages/db/migrations/meta/0033_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0033_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0033_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0033_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0034_snapshot.json","path":"packages/db/migrations/meta/0034_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0034_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0034_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0034_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0035_snapshot.json","path":"packages/db/migrations/meta/0035_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0035_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0035_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0035_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0036_snapshot.json","path":"packages/db/migrations/meta/0036_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0036_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0036_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0036_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0037_snapshot.json","path":"packages/db/migrations/meta/0037_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0037_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0037_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0037_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0038_snapshot.json","path":"packages/db/migrations/meta/0038_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0038_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0038_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0038_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0039_snapshot.json","path":"packages/db/migrations/meta/0039_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0039_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0039_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0039_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0040_snapshot.json","path":"packages/db/migrations/meta/0040_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0040_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0040_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0040_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0041_snapshot.json","path":"packages/db/migrations/meta/0041_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0041_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0041_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0041_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0042_snapshot.json","path":"packages/db/migrations/meta/0042_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0042_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0042_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0042_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0043_snapshot.json","path":"packages/db/migrations/meta/0043_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0043_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0043_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0043_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0044_snapshot.json","path":"packages/db/migrations/meta/0044_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0044_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0044_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0044_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0045_snapshot.json","path":"packages/db/migrations/meta/0045_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0045_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0045_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0045_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0046_snapshot.json","path":"packages/db/migrations/meta/0046_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0046_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0046_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0046_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0047_snapshot.json","path":"packages/db/migrations/meta/0047_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0047_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0047_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0047_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0048_snapshot.json","path":"packages/db/migrations/meta/0048_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0048_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0048_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0048_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0049_snapshot.json","path":"packages/db/migrations/meta/0049_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0049_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0049_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0049_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0050_snapshot.json","path":"packages/db/migrations/meta/0050_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0050_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0050_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0050_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0052_snapshot.json","path":"packages/db/migrations/meta/0052_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0052_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0052_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0052_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0053_snapshot.json","path":"packages/db/migrations/meta/0053_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0053_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0053_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0053_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0054_snapshot.json","path":"packages/db/migrations/meta/0054_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0054_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0054_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0054_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0055_snapshot.json","path":"packages/db/migrations/meta/0055_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0055_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0055_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0055_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0056_snapshot.json","path":"packages/db/migrations/meta/0056_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0056_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0056_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0056_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0057_snapshot.json","path":"packages/db/migrations/meta/0057_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0057_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0057_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0057_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0058_snapshot.json","path":"packages/db/migrations/meta/0058_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0058_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0058_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0058_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0059_snapshot.json","path":"packages/db/migrations/meta/0059_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0059_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0059_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0059_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0060_snapshot.json","path":"packages/db/migrations/meta/0060_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0060_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0060_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0060_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0061_snapshot.json","path":"packages/db/migrations/meta/0061_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0061_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0061_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0061_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0062_snapshot.json","path":"packages/db/migrations/meta/0062_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0062_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0062_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0062_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0063_snapshot.json","path":"packages/db/migrations/meta/0063_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0063_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0063_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0063_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0064_snapshot.json","path":"packages/db/migrations/meta/0064_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0064_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0064_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0064_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0065_snapshot.json","path":"packages/db/migrations/meta/0065_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0065_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0065_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0065_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0066_snapshot.json","path":"packages/db/migrations/meta/0066_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0066_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0066_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0066_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0067_snapshot.json","path":"packages/db/migrations/meta/0067_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0067_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0067_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0067_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0068_snapshot.json","path":"packages/db/migrations/meta/0068_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0068_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0068_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0068_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0069_snapshot.json","path":"packages/db/migrations/meta/0069_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0069_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0069_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0069_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0070_snapshot.json","path":"packages/db/migrations/meta/0070_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0070_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0070_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0070_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0071_snapshot.json","path":"packages/db/migrations/meta/0071_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0071_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0071_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0071_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0072_snapshot.json","path":"packages/db/migrations/meta/0072_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0072_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0072_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0072_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0073_snapshot.json","path":"packages/db/migrations/meta/0073_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0073_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0073_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0073_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0074_snapshot.json","path":"packages/db/migrations/meta/0074_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0074_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0074_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0074_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0075_snapshot.json","path":"packages/db/migrations/meta/0075_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0075_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0075_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0075_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0076_snapshot.json","path":"packages/db/migrations/meta/0076_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0076_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0076_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0076_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0077_snapshot.json","path":"packages/db/migrations/meta/0077_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0077_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0077_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0077_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0078_snapshot.json","path":"packages/db/migrations/meta/0078_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0078_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0078_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0078_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0079_snapshot.json","path":"packages/db/migrations/meta/0079_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0079_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0079_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0079_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0080_snapshot.json","path":"packages/db/migrations/meta/0080_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0080_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0080_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0080_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0081_snapshot.json","path":"packages/db/migrations/meta/0081_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0081_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0081_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0081_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0082_snapshot.json","path":"packages/db/migrations/meta/0082_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0082_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0082_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0082_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0083_snapshot.json","path":"packages/db/migrations/meta/0083_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0083_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0083_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0083_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0084_snapshot.json","path":"packages/db/migrations/meta/0084_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0084_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0084_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0084_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0085_snapshot.json","path":"packages/db/migrations/meta/0085_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0085_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0085_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0085_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0086_snapshot.json","path":"packages/db/migrations/meta/0086_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0086_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0086_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0086_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0087_snapshot.json","path":"packages/db/migrations/meta/0087_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0087_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0087_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0087_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0088_snapshot.json","path":"packages/db/migrations/meta/0088_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0088_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0088_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0088_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0089_snapshot.json","path":"packages/db/migrations/meta/0089_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0089_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0089_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0089_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0090_snapshot.json","path":"packages/db/migrations/meta/0090_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0090_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0090_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0090_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0091_snapshot.json","path":"packages/db/migrations/meta/0091_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0091_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0091_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0091_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0092_snapshot.json","path":"packages/db/migrations/meta/0092_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0092_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0092_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0092_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0093_snapshot.json","path":"packages/db/migrations/meta/0093_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0093_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0093_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0093_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"0094_snapshot.json","path":"packages/db/migrations/meta/0094_snapshot.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0094_snapshot.json","title":"Meta Skill","category":"anthropic-skill","format":"json","content":"# Meta Skill\n\nPath: `packages/db/migrations/meta/0094_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0094_snapshot.json)","tokens":300,"sizeBytes":200},{"name":"package.json","path":"packages/db/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/package.json","title":"Db Skill","category":"anthropic-skill","format":"json","content":"# Db Skill\n\nPath: `packages/db/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/package.json)","tokens":300,"sizeBytes":154},{"name":"tsconfig.json","path":"packages/db/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/tsconfig.json","title":"Db Skill","category":"anthropic-skill","format":"json","content":"# Db Skill\n\nPath: `packages/db/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/tsconfig.json)","tokens":300,"sizeBytes":156},{"name":"package.json","path":"packages/eslint-config/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/package.json","title":"Eslint-config Skill","category":"anthropic-skill","format":"json","content":"# Eslint-config Skill\n\nPath: `packages/eslint-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/package.json)","tokens":300,"sizeBytes":187},{"name":"CHANGELOG.md","path":"packages/react-ui-base/CHANGELOG.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/CHANGELOG.md","title":"React-ui-base Skill","category":"anthropic-skill","format":"markdown","content":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/CHANGELOG.md)","tokens":300,"sizeBytes":187},{"name":"package.json","path":"packages/react-ui-base/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/package.json","title":"React-ui-base Skill","category":"anthropic-skill","format":"json","content":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/package.json)","tokens":300,"sizeBytes":187},{"name":"tsconfig.json","path":"packages/react-ui-base/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/tsconfig.json","title":"React-ui-base Skill","category":"anthropic-skill","format":"json","content":"# React-ui-base Skill\n\nPath: `packages/react-ui-base/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/tsconfig.json)","tokens":300,"sizeBytes":189},{"name":"package.json","path":"packages/testing/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/package.json","title":"Testing Skill","category":"anthropic-skill","format":"json","content":"# Testing Skill\n\nPath: `packages/testing/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/package.json)","tokens":300,"sizeBytes":169},{"name":"tsconfig.json","path":"packages/testing/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/tsconfig.json","title":"Testing Skill","category":"anthropic-skill","format":"json","content":"# Testing Skill\n\nPath: `packages/testing/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/testing/tsconfig.json)","tokens":300,"sizeBytes":171},{"name":"base.json","path":"packages/typescript-config/base.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/base.json","title":"Typescript-config Skill","category":"anthropic-skill","format":"json","content":"# Typescript-config Skill\n\nPath: `packages/typescript-config/base.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/base.json)","tokens":300,"sizeBytes":193},{"name":"nextjs.json","path":"packages/typescript-config/nextjs.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/nextjs.json","title":"Typescript-config Skill","category":"anthropic-skill","format":"json","content":"# Typescript-config Skill\n\nPath: `packages/typescript-config/nextjs.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/nextjs.json)","tokens":300,"sizeBytes":197},{"name":"package.json","path":"packages/typescript-config/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/package.json","title":"Typescript-config Skill","category":"anthropic-skill","format":"json","content":"# Typescript-config Skill\n\nPath: `packages/typescript-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/package.json)","tokens":300,"sizeBytes":199},{"name":"react-library.json","path":"packages/typescript-config/react-library.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/react-library.json","title":"Typescript-config Skill","category":"anthropic-skill","format":"json","content":"# Typescript-config Skill\n\nPath: `packages/typescript-config/react-library.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/typescript-config/react-library.json)","tokens":300,"sizeBytes":211},{"name":"AGENTS.md","path":"packages/ui-registry/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/AGENTS.md","title":"Ui-registry Skill","category":"anthropic-skill","format":"markdown","content":"# Ui-registry Skill\n\nPath: `packages/ui-registry/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/AGENTS.md)","tokens":300,"sizeBytes":175},{"name":"package.json","path":"packages/ui-registry/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/package.json","title":"Ui-registry Skill","category":"anthropic-skill","format":"json","content":"# Ui-registry Skill\n\nPath: `packages/ui-registry/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/package.json)","tokens":300,"sizeBytes":181},{"name":"config.json","path":"packages/ui-registry/src/components/control-bar/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/control-bar/config.json","title":"Control-bar Skill","category":"anthropic-skill","format":"json","content":"# Control-bar Skill\n\nPath: `packages/ui-registry/src/components/control-bar/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/control-bar/config.json)","tokens":300,"sizeBytes":233},{"name":"config.json","path":"packages/ui-registry/src/components/edit-with-tambo-button/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/edit-with-tambo-button/config.json","title":"Edit-with-tambo-button Skill","category":"anthropic-skill","format":"json","content":"# Edit-with-tambo-button Skill\n\nPath: `packages/ui-registry/src/components/edit-with-tambo-button/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/edit-with-tambo-button/config.json)","tokens":300,"sizeBytes":266},{"name":"config.json","path":"packages/ui-registry/src/components/elicitation-ui/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/elicitation-ui/config.json","title":"Elicitation-ui Skill","category":"anthropic-skill","format":"json","content":"# Elicitation-ui Skill\n\nPath: `packages/ui-registry/src/components/elicitation-ui/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/elicitation-ui/config.json)","tokens":300,"sizeBytes":242},{"name":"config.json","path":"packages/ui-registry/src/components/form/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/form/config.json","title":"Form Skill","category":"anthropic-skill","format":"json","content":"# Form Skill\n\nPath: `packages/ui-registry/src/components/form/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/form/config.json)","tokens":300,"sizeBytes":212},{"name":"config.json","path":"packages/ui-registry/src/components/graph/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/graph/config.json","title":"Graph Skill","category":"anthropic-skill","format":"json","content":"# Graph Skill\n\nPath: `packages/ui-registry/src/components/graph/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/graph/config.json)","tokens":300,"sizeBytes":215},{"name":"config.json","path":"packages/ui-registry/src/components/input-fields/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/input-fields/config.json","title":"Input-fields Skill","category":"anthropic-skill","format":"json","content":"# Input-fields Skill\n\nPath: `packages/ui-registry/src/components/input-fields/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/input-fields/config.json)","tokens":300,"sizeBytes":236},{"name":"config.json","path":"packages/ui-registry/src/components/map/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/map/config.json","title":"Map Skill","category":"anthropic-skill","format":"json","content":"# Map Skill\n\nPath: `packages/ui-registry/src/components/map/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/map/config.json)","tokens":300,"sizeBytes":209},{"name":"config.json","path":"packages/ui-registry/src/components/mcp-components/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/mcp-components/config.json","title":"Mcp-components Skill","category":"anthropic-skill","format":"json","content":"# Mcp-components Skill\n\nPath: `packages/ui-registry/src/components/mcp-components/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/mcp-components/config.json)","tokens":300,"sizeBytes":242},{"name":"config.json","path":"packages/ui-registry/src/components/message-input/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-input/config.json","title":"Message-input Skill","category":"anthropic-skill","format":"json","content":"# Message-input Skill\n\nPath: `packages/ui-registry/src/components/message-input/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-input/config.json)","tokens":300,"sizeBytes":239},{"name":"config.json","path":"packages/ui-registry/src/components/message-suggestions/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-suggestions/config.json","title":"Message-suggestions Skill","category":"anthropic-skill","format":"json","content":"# Message-suggestions Skill\n\nPath: `packages/ui-registry/src/components/message-suggestions/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-suggestions/config.json)","tokens":300,"sizeBytes":257},{"name":"config.json","path":"packages/ui-registry/src/components/message-thread-collapsible/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-collapsible/config.json","title":"Message-thread-collapsible Skill","category":"anthropic-skill","format":"json","content":"# Message-thread-collapsible Skill\n\nPath: `packages/ui-registry/src/components/message-thread-collapsible/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-collapsible/config.json)","tokens":300,"sizeBytes":278},{"name":"config.json","path":"packages/ui-registry/src/components/message-thread-full/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-full/config.json","title":"Message-thread-full Skill","category":"anthropic-skill","format":"json","content":"# Message-thread-full Skill\n\nPath: `packages/ui-registry/src/components/message-thread-full/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-full/config.json)","tokens":300,"sizeBytes":257},{"name":"config.json","path":"packages/ui-registry/src/components/message-thread-panel/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-panel/config.json","title":"Message-thread-panel Skill","category":"anthropic-skill","format":"json","content":"# Message-thread-panel Skill\n\nPath: `packages/ui-registry/src/components/message-thread-panel/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message-thread-panel/config.json)","tokens":300,"sizeBytes":260},{"name":"config.json","path":"packages/ui-registry/src/components/message/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message/config.json","title":"Message Skill","category":"anthropic-skill","format":"json","content":"# Message Skill\n\nPath: `packages/ui-registry/src/components/message/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/message/config.json)","tokens":300,"sizeBytes":221},{"name":"config.json","path":"packages/ui-registry/src/components/scrollable-message-container/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/scrollable-message-container/config.json","title":"Scrollable-message-container Skill","category":"anthropic-skill","format":"json","content":"# Scrollable-message-container Skill\n\nPath: `packages/ui-registry/src/components/scrollable-message-container/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/scrollable-message-container/config.json)","tokens":300,"sizeBytes":284},{"name":"config.json","path":"packages/ui-registry/src/components/thread-content/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-content/config.json","title":"Thread-content Skill","category":"anthropic-skill","format":"json","content":"# Thread-content Skill\n\nPath: `packages/ui-registry/src/components/thread-content/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-content/config.json)","tokens":300,"sizeBytes":242},{"name":"config.json","path":"packages/ui-registry/src/components/thread-dropdown/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-dropdown/config.json","title":"Thread-dropdown Skill","category":"anthropic-skill","format":"json","content":"# Thread-dropdown Skill\n\nPath: `packages/ui-registry/src/components/thread-dropdown/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-dropdown/config.json)","tokens":300,"sizeBytes":245},{"name":"config.json","path":"packages/ui-registry/src/components/thread-history/config.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-history/config.json","title":"Thread-history Skill","category":"anthropic-skill","format":"json","content":"# Thread-history Skill\n\nPath: `packages/ui-registry/src/components/thread-history/config.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/src/components/thread-history/config.json)","tokens":300,"sizeBytes":242},{"name":"tsconfig.json","path":"packages/ui-registry/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/tsconfig.json","title":"Ui-registry Skill","category":"anthropic-skill","format":"json","content":"# Ui-registry Skill\n\nPath: `packages/ui-registry/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/ui-registry/tsconfig.json)","tokens":300,"sizeBytes":183},{"name":"package.json","path":"packages/vite-config/package.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/package.json","title":"Vite-config Skill","category":"anthropic-skill","format":"json","content":"# Vite-config Skill\n\nPath: `packages/vite-config/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/package.json)","tokens":300,"sizeBytes":181},{"name":"tsconfig.json","path":"packages/vite-config/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/tsconfig.json","title":"Vite-config Skill","category":"anthropic-skill","format":"json","content":"# Vite-config Skill\n\nPath: `packages/vite-config/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/vite-config/tsconfig.json)","tokens":300,"sizeBytes":183},{"name":"add-components-to-registry.md","path":"plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/add-components-to-registry.md)","tokens":300,"sizeBytes":276},{"name":"cli.md","path":"plugins/tambo/skills/building-with-tambo/references/cli.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/cli.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/cli.md)","tokens":300,"sizeBytes":230},{"name":"component-rendering.md","path":"plugins/tambo/skills/building-with-tambo/references/component-rendering.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/component-rendering.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/component-rendering.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/component-rendering.md)","tokens":300,"sizeBytes":262},{"name":"components.md","path":"plugins/tambo/skills/building-with-tambo/references/components.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/components.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/components.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/components.md)","tokens":300,"sizeBytes":244},{"name":"skills.md","path":"plugins/tambo/skills/building-with-tambo/references/skills.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/skills.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/skills.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/skills.md)","tokens":300,"sizeBytes":236},{"name":"threads.md","path":"plugins/tambo/skills/building-with-tambo/references/threads.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/threads.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/threads.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/threads.md)","tokens":300,"sizeBytes":238},{"name":"tools-and-context.md","path":"plugins/tambo/skills/building-with-tambo/references/tools-and-context.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/tools-and-context.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/building-with-tambo/references/tools-and-context.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/building-with-tambo/references/tools-and-context.md)","tokens":300,"sizeBytes":258},{"name":"cli.md","path":"plugins/tambo/skills/generative-ui/references/cli.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/cli.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/cli.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/cli.md)","tokens":300,"sizeBytes":218},{"name":"component-rendering.md","path":"plugins/tambo/skills/generative-ui/references/component-rendering.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/component-rendering.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/component-rendering.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/component-rendering.md)","tokens":300,"sizeBytes":250},{"name":"components.md","path":"plugins/tambo/skills/generative-ui/references/components.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/components.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/components.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/components.md)","tokens":300,"sizeBytes":232},{"name":"skills.md","path":"plugins/tambo/skills/generative-ui/references/skills.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/skills.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/skills.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/skills.md)","tokens":300,"sizeBytes":224},{"name":"threads.md","path":"plugins/tambo/skills/generative-ui/references/threads.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/threads.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/threads.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/threads.md)","tokens":300,"sizeBytes":226},{"name":"tools-and-context.md","path":"plugins/tambo/skills/generative-ui/references/tools-and-context.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/tools-and-context.md","title":"References Skill","category":"anthropic-skill","format":"markdown","content":"# References Skill\n\nPath: `plugins/tambo/skills/generative-ui/references/tools-and-context.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/references/tools-and-context.md)","tokens":300,"sizeBytes":246},{"name":"SKILL.md","path":"plugins/tambo/skills/generative-ui/SKILL.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/skills/generative-ui/SKILL.md","title":"generative-ui","category":"anthropic-skill","format":"markdown","content":"---\nname: generative-ui\ndescription: Creates a new Tambo generative UI app from scratch. Scaffolds with tambo create-app, wires TamboProvider, registers starter components. Triggers on \"new Tambo app\", \"create a generative UI app\", \"build an AI app from scratch\", \"start a new project with Tambo\". For existing apps, use building-with-tambo.\n---\n\n# Generative UI\n\nBuild generative UI apps with Tambo — create rich, interactive React components from natural language.\n\n## Reference Guides\n\nLoad these when you need deeper implementation details beyond the bootstrap flow:\n\n- [Components](references/components.md) - **Load when creating custom components.** Generative vs interactable, propsSchema, ComponentRenderer.\n- [Component Rendering](references/component-rendering.md) - Streaming props, loading states, persistent state. Load when customizing rendering.\n- [Threads and Input](references/threads.md) - **Load when building custom chat UI.** useTambo(), useTamboThreadInput(), userKey/userToken auth, suggestions, voice.\n- [Tools and Context](references/tools-and-context.md) - **Load when adding tools or MCP.** defineTool(), MCP servers, contextHelpers.\n- [CLI Reference](references/cli.md) - **Load for `tambo add` components.** Component library, non-interactive flags, exit codes.\n- [Skills](references/skills.md) - **Mention as a next step after setup.** Project-scoped agent skills via CLI and dashboard.\n\nThese shared references are duplicated from building-with-tambo so each skill works independently.\n\n## One-Prompt Flow\n\nThe goal is to get the user from zero to a running app in a single prompt. Ask all questions upfront using AskUserQuestion with multiple questions, then execute everything without stopping.\n\n### Step 1: Gather All Non-Sensitive Preferences (Single AskUserQuestion Call)\n\nUse AskUserQuestion with up to 3 questions in ONE call. Authentication is handled by the CLI in a later step.\n\n**Question 1: What do you want to build?**\n\nAsk the user what kind of app they're building. This drives which starter components to create. Examples: \"a dashboard\", \"a chatbot\", \"a data visualization tool\", \"a task manager\". If the user already said what they want in their initial message, skip this question.\n\n**Question 2: Framework**\n\nOptions:\n\n- Next.js (Recommended) - Full-stack React with App Router\n- Vite - Fast, lightweight React setup\n\n**Question 3: App name**\n\nLet the user pick a name for their project directory. Default suggestion: derive from what they want to build (e.g., \"my-dashboard\", \"my-chatbot\"). Use kebab-case (letters, numbers, hyphens only). If the user gives a non-slug name like \"Sales Dashboard\", propose `sales-dashboard` instead.\n\n**Skip questions when the user already told you the answer.** If they said \"build me a Next.js dashboard app called analytics\", you already know the framework, the app idea, and the name.\n\n### Step 2: Execute Everything (No Stopping)\n\nRun all of these sequentially without asking for confirmation between steps. If any command fails, stop the flow, surface the error, and ask the user how to proceed — do not continue to later steps.\n\nAll templates (`standard`, `vite`, `analytics`, `expo`) come with chat UI, TamboProvider wiring, component registry, and starter components already included. You do NOT need to add chat UI or wire up the app — just scaffold, configure the API key, add custom components, and start the server.\n\n#### 2a. Scaffold the project\n\nFor Next.js (recommended):\n\n```bash\nnpx tambo create-app <app-name> --template=standard --skip-tambo-init\ncd <app-name>\n```\n\nFor Vite:\n\n```bash\nnpx tambo create-app <app-name> --template=vite --skip-tambo-init\ncd <app-name>\n```\n\nUse `--skip-tambo-init` since `create-app` normally tries to run `tambo init` interactively, which won't work in non-interactive environments like coding agents. We handle authentication in the next step.\n\n#### 2b. Authenticate and initialize Tambo\n\n```bash\nnpx tambo init --project-name=<app-name>\n```\n\nThis opens the browser for authentication and polls until the user completes auth (up to 15 minutes). Use a long timeout (at least 15 minutes) when running this command. Once auth completes, the CLI creates the project and writes the API key to `.env.local` with the correct env var for the framework (`NEXT_PUBLIC_TAMBO_API_KEY`, `VITE_TAMBO_API_KEY`, etc.).\n\n**IMPORTANT:** Do NOT ask the user to paste an API key manually. Always use the CLI auth flow.\n\n#### 2c. Create custom starter components\n\nThe template includes basic components, but add 1-2 components tailored to what the user wants to build. Don't use generic examples:\n\n- **Dashboard app** → `StatsCard`, `DataTable`\n- **Chatbot** → `BotResponse` with markdown support\n- **Data visualization** → `Chart` with configurable data\n- **Task manager** → `TaskCard`, `TaskBoard`\n- **Generic / unclear** → `ContentCard`\n\nEach component needs:\n\n1. A Zod schema with `.describe()` on every field\n2. The React component itself\n3. Registration in the existing component registry (`lib/tambo.ts` — add to the existing `components` array, don't replace it)\n\n**Schema constraints — Tambo will reject invalid schemas at runtime:**\n\n- **No `z.record()`** — Record types (objects with dynamic keys) are not supported anywhere in the schema, including nested inside arrays or objects. Use `z.object()` with explicit named keys instead.\n- **No `z.map()` or `z.set()`** — Use arrays and objects instead.\n- For tabular data like rows, use `z.array(z.object({ col1: z.string(), col2: z.number() }))` with explicit column keys — NOT `z.array(z.record(z.string(), z.unknown()))`.\n\n**React best practices for generated components:**\n\n- Always add unique `key` props when rendering lists (`.map()`). Use a unique field from the data (like `id`) — not the array index.\n- Include an `id` field (e.g., `z.string().describe(\"Unique identifier\")`) in schemas for array items so there's always a stable key available.\n\nExample:\n\n```tsx\n// src/components/StatsCard.tsx\nimport { z } from \"zod/v4\";\n\nexport const StatsCardSchema = z.object({\n  title: z.string().describe(\"Metric name\"),\n  value: z.number().describe(\"Current value\"),\n  change: z.number().optional().describe(\"Percent change from previous period\"),\n  trend: z.enum([\"up\", \"down\", \"flat\"]).optional().describe(\"Trend direction\"),\n});\n\ntype StatsCardProps = z.infer<typeof StatsCardSchema>;\n\nexport function StatsCard({\n  title,\n  value,\n  change,\n  trend = \"flat\",\n}: StatsCardProps) {\n  // ... implementation with Tailwind styling\n}\n```\n\nThen add to the existing registry in `lib/tambo.ts`:\n\n```tsx\n// Add to the existing components array — don't replace what's already there\n// Next.js: import { StatsCard, StatsCardSchema } from \"@/components/StatsCard\";\n// Vite: import { StatsCard, StatsCardSchema } from \"../components/StatsCard\";\nimport { StatsCard, StatsCardSchema } from \"@/components/StatsCard\";\n\n// ... existing components ...\n{\n  name: \"StatsCard\",\n  component: StatsCard,\n  description: \"Displays a metric with value and trend. Use when user asks about stats, metrics, or KPIs.\",\n  propsSchema: StatsCardSchema,\n},\n```\n\n#### 2d. Start the dev server\n\nOnly start the dev server after all code changes (scaffolding, init, component creation, registry updates) are complete.\n\n```bash\nnpm run dev\n```\n\nRun this in the background so the user can see their app immediately.\n\n### Step 3: Summary\n\nAfter everything is running, give a brief summary:\n\n- What was set up\n- What components were created and what they do\n- The URL where the app is running (typically `http://localhost:3000` for Next.js, `http://localhost:5173` for Vite)\n- If auth was skipped: remind them once to run `npx tambo init` to authenticate\n- A suggestion for what to try first (e.g., \"Try asking it to show you a stats card for monthly revenue\")\n\n## Technology Stacks Reference\n\n### Recommended Stack (Default)\n\n```\nNext.js 14+ (App Router)\n├── TypeScript\n├── Tailwind CSS\n├── Zod (for schemas)\n└── @tambo-ai/react\n```\n\n```bash\nnpx tambo create-app my-app --template=standard\n```\n\n### Vite Stack\n\n```\nVite + React\n├── TypeScript\n├── Tailwind CSS\n├── Zod\n└── @tambo-ai/react\n```\n\n### Minimal Stack (No Tailwind)\n\n```\nVite + React\n├── TypeScript\n├── Plain CSS\n├── Zod\n└── @tambo-ai/react\n```\n\n## Component Registry Pattern\n\nEvery generative component must be registered:\n\n```tsx\nimport { TamboComponent } from \"@tambo-ai/react\";\nimport { ComponentName, ComponentNameSchema } from \"@/components/ComponentName\";\n\nexport const components: TamboComponent[] = [\n  {\n    name: \"ComponentName\",\n    component: ComponentName,\n    description: \"What it does. When to use it.\",\n    propsSchema: ComponentNameSchema,\n  },\n];\n```\n\nKey rules:\n\n- **propsSchema**: Zod object with `.describe()` on every field — this is how the AI knows what to pass\n- **description**: Tell the AI when to use this component — be specific about trigger phrases\n- **Streaming**: Props arrive incrementally, so handle undefined gracefully (optional fields or defaults)\n\n## Adding More Chat UI (Optional)\n\nTemplates already include chat UI. These are only needed if the user wants additional UI primitives beyond what the template provides:\n\n```bash\nnpx tambo add message-thread-full --yes    # Complete chat interface\nnpx tambo add control-bar --yes            # Controls and actions\nnpx tambo add thread-history --yes         # Conversation history sidebar\n```\n\n## Supported Technologies\n\n| Technology       | Support Level | Notes                             |\n| ---------------- | ------------- | --------------------------------- |\n| Next.js 14+      | Full          | Recommended, App Router preferred |\n| Vite             | Full          | Great for SPAs                    |\n| Create React App | Partial       | Works but CRA is deprecated       |\n| Remix            | Partial       | Works with client components      |\n| TypeScript       | Full          | Strongly recommended              |\n| JavaScript       | Full          | Works but less type safety        |\n| Tailwind CSS     | Full          | Default for CLI components        |\n| Plain CSS        | Full          | Need custom component styling     |\n| CSS Modules      | Full          | Supported                         |\n| Zod              | Required      | Used for all schemas              |\n\n## Verification\n\nHave the user verify the app works by:\n\n1. Opening the app URL in a browser\n2. Typing a prompt that should trigger one of the registered components (e.g., \"Show me a stats card for monthly revenue\")\n3. Verifying the component renders with AI-generated props\n\nIf something doesn't work:\n\n- Check the registry includes the component\n- Check the description matches the prompt\n- Check the dev server has no console errors\n\n## Reporting Bugs & Feedback\n\nIf you encounter any of these while helping a user, suggest filing a GitHub issue:\n\n- A bug in `@tambo-ai/react`, `@tambo-ai/client`, or the `tambo` CLI\n- Documentation that contradicts actual behavior\n- Missing or misleading instructions in this skill\n\n### Issue Template\n\nUse this template when drafting an issue for `tambo-ai/tambo`:\n\n````markdown\n**Title:** [Short description of the problem]\n\n**Expected behavior**\nWhat should happen.\n\n**Actual behavior**\nWhat happens instead, including any error messages or stack traces.\n\n**Repro steps**\n\n1. Run `npx tambo create-app ...` (or whatever command)\n2. Add this code:\n\n```tsx\n// minimal code that reproduces the issue\n```\n\n3. Observe the error\n\n**Environment**\n\n- `@tambo-ai/react` version:\n- `@tambo-ai/client` version:\n- Framework (Next.js / Vite / CRA) and version:\n- Node.js version:\n- OS:\n\n**Additional context**\nLink to relevant docs or skill file path if applicable.\n````\n\n**Security:** Redact API keys, tokens, and any customer data before including logs or code snippets in the issue.\n\n### Suggesting an Issue to the User\n\nWhen you hit a problem that looks like a Tambo bug, say something like:\n\n> This looks like a bug in `@tambo-ai/react`. Want me to open a GitHub issue on `tambo-ai/tambo` with the repro steps and environment details?\n\nAlways wait for the user to confirm before filing.\n","frontmatter":{"name":"generative-ui","description":"Creates a new Tambo generative UI app from scratch. Scaffolds with tambo create-app, wires TamboProvider, registers starter components. Triggers on \"new Tambo app\", \"create a generative UI app\", \"build an AI app from scratch\", \"start a new project with Tambo\". For existing apps, use building-with-tambo."},"isInternal":false,"tokens":2847,"sizeBytes":12207},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nGuidelines for Claude Code (claude.ai/code) when touching this repo.\n\n**Read @AGENTS.md first.** It owns architecture, naming, workflow rules, testing expectations, and anything code-related. Keep that file open—this doc just points you there.\n\n## Three Things to Remember\n\n1. Follow that doc for everything: repo layout, commands, coding standards, doc rules, Charlie workflow, MCP guidance, etc.\n2. Use the workspace scripts it lists (see below for key commands).\n3. Defer to it whenever instructions collide; if something's still unclear, ask the user.\n\n## Key Commands\n\n```bash\n# Development (two different apps)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261\nnpm run dev              # Start React SDK (showcase + docs)\n\n# Quality checks (run before commits)\nnpm run lint\nnpm run check-types\nnpm test\n\n# Database (requires -w flag)\nnpm run db:generate -w packages/db\nnpm run db:migrate -w packages/db\nnpm run db:studio -w packages/db\n\n# Docker (for PostgreSQL in local dev)\ndocker compose --env-file docker.env up postgres -d\n```\n\n## Documentation Structure\n\n- **CONTRIBUTING.md** - Dev setup and PR workflow for contributors\n- **SELF-HOSTING.md** - Self-hosting/deployment guide\n- **AGENTS.md** - Coding standards, architecture (this is the source of truth)\n","isInternal":false,"tokens":319,"sizeBytes":1309},{"name":"CLAUDE.md","path":"cli/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/CLAUDE.md","title":"cli - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# cli - Claude Agent Guidelines & System Prompt\n\nPath: `cli/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/CLAUDE.md)","tokens":300,"sizeBytes":169},{"name":"CLAUDE.md","path":"create-tambo-app/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/CLAUDE.md","title":"create-tambo-app - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# create-tambo-app - Claude Agent Guidelines & System Prompt\n\nPath: `create-tambo-app/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/CLAUDE.md)","tokens":300,"sizeBytes":208},{"name":"CLAUDE.md","path":"docs/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/CLAUDE.md","title":"docs - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# docs - Claude Agent Guidelines & System Prompt\n\nPath: `docs/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/CLAUDE.md)","tokens":300,"sizeBytes":172},{"name":"CLAUDE.md","path":"react-sdk/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/CLAUDE.md","title":"react-sdk - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# react-sdk - Claude Agent Guidelines & System Prompt\n\nPath: `react-sdk/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/CLAUDE.md)","tokens":300,"sizeBytes":187},{"name":"CLAUDE.md","path":"showcase/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/CLAUDE.md","title":"showcase - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# showcase - Claude Agent Guidelines & System Prompt\n\nPath: `showcase/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/CLAUDE.md)","tokens":300,"sizeBytes":184},{"name":"marketplace.json","path":".claude-plugin/marketplace.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude-plugin/marketplace.json","title":"tambo-marketplace","category":"marketplace","format":"json","content":"{\n  \"name\": \"tambo-marketplace\",\n  \"owner\": {\n    \"name\": \"Tambo AI\",\n    \"email\": \"support@tambo.co\"\n  },\n  \"metadata\": {\n    \"description\": \"Official Tambo plugins for Claude Code\",\n    \"homepage\": \"https://tambo.co\"\n  },\n  \"plugins\": [\n    {\n      \"name\": \"tambo\",\n      \"source\": \"./plugins/tambo\",\n      \"description\": \"Build agents that speak your UI\",\n      \"version\": \"1.0.0\",\n      \"author\": {\n        \"name\": \"Tambo AI\",\n        \"email\": \"support@tambo.co\"\n      },\n      \"category\": \"frameworks\",\n      \"keywords\": [\"ai\", \"react\", \"generative-ui\", \"components\", \"streaming\"]\n    }\n  ]\n}\n","frontmatter":{"name":"tambo-marketplace","owner":{"name":"Tambo AI","email":"support@tambo.co"},"metadata":{"description":"Official Tambo plugins for Claude Code","homepage":"https://tambo.co"},"plugins":[{"name":"tambo","source":"./plugins/tambo","description":"Build agents that speak your UI","version":"1.0.0","author":{"name":"Tambo AI","email":"support@tambo.co"},"category":"frameworks","keywords":["ai","react","generative-ui","components","streaming"]}]},"isInternal":false,"tokens":179,"sizeBytes":598},{"name":"README.md","path":"packages/backend/README.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/README.md","title":"backend Documentation","category":"plugin-manifest","format":"markdown","content":"# backend Documentation\n\nPath: `packages/backend/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/README.md)","tokens":300,"sizeBytes":171},{"name":"README.md","path":"packages/client/README.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/README.md","title":"client Documentation","category":"plugin-manifest","format":"markdown","content":"# client Documentation\n\nPath: `packages/client/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/README.md)","tokens":300,"sizeBytes":168},{"name":"README.md","path":"packages/core/README.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/README.md","title":"core Documentation","category":"plugin-manifest","format":"markdown","content":"# core Documentation\n\nPath: `packages/core/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/README.md)","tokens":300,"sizeBytes":162},{"name":"README.md","path":"packages/db/README.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/README.md","title":"db Documentation","category":"plugin-manifest","format":"markdown","content":"# db Documentation\n\nPath: `packages/db/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/README.md)","tokens":300,"sizeBytes":156},{"name":"README.md","path":"packages/eslint-config/README.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/README.md","title":"eslint-config Documentation","category":"plugin-manifest","format":"markdown","content":"# eslint-config Documentation\n\nPath: `packages/eslint-config/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/eslint-config/README.md)","tokens":300,"sizeBytes":189},{"name":"README.md","path":"packages/react-ui-base/README.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/README.md","title":"react-ui-base Documentation","category":"plugin-manifest","format":"markdown","content":"# react-ui-base Documentation\n\nPath: `packages/react-ui-base/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/react-ui-base/README.md)","tokens":300,"sizeBytes":189},{"name":"plugin.json","path":"plugins/tambo/.claude-plugin/plugin.json","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/.claude-plugin/plugin.json","title":"claude-plugin Plugin Manifest","category":"plugin-manifest","format":"json","content":"# claude-plugin Plugin Manifest\n\nPath: `plugins/tambo/.claude-plugin/plugin.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/.claude-plugin/plugin.json)","tokens":300,"sizeBytes":207},{"name":"README.md","path":"plugins/tambo/README.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/README.md","title":"tambo Documentation","category":"plugin-manifest","format":"markdown","content":"# tambo Documentation\n\nPath: `plugins/tambo/README.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/plugins/tambo/README.md)","tokens":300,"sizeBytes":163},{"name":"planner.md","path":".claude/agents/planner.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/planner.md","title":"Subagent: planner","category":"subagent-persona","format":"markdown","content":"# Subagent: planner\n\nPath: `.claude/agents/planner.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/planner.md)","tokens":300,"sizeBytes":165},{"name":"researcher.md","path":".claude/agents/researcher.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/researcher.md","title":"Subagent: researcher","category":"subagent-persona","format":"markdown","content":"# Subagent: researcher\n\nPath: `.claude/agents/researcher.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/agents/researcher.md)","tokens":300,"sizeBytes":174},{"name":"commit.md","path":".claude/commands/commit.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/commit.md","title":"Command: /commit","category":"command-prompt","format":"markdown","content":"# Command: /commit\n\nPath: `.claude/commands/commit.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/commit.md)","tokens":300,"sizeBytes":166},{"name":"create-pr.md","path":".claude/commands/create-pr.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/create-pr.md","title":"Command: /create-pr","category":"command-prompt","format":"markdown","content":"# Command: /create-pr\n\nPath: `.claude/commands/create-pr.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/create-pr.md)","tokens":300,"sizeBytes":175},{"name":"execute.md","path":".claude/commands/execute.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/execute.md","title":"Command: /execute","category":"command-prompt","format":"markdown","content":"# Command: /execute\n\nPath: `.claude/commands/execute.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/execute.md)","tokens":300,"sizeBytes":169},{"name":"plan.md","path":".claude/commands/plan.md","rawUrl":"https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/plan.md","title":"Command: /plan","category":"command-prompt","format":"markdown","content":"# Command: /plan\n\nPath: `.claude/commands/plan.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/commands/plan.md)","tokens":300,"sizeBytes":160}],"systemPromptSnippet":"<yakaai_skills repo=\"tambo-ai/tambo\">\n<!-- File: .github/AGENTS.md (Tokens: ~214 | Category: root-instruction) -->\n# AGENTS.md\n\nGuidance for agents working in `.github/` (GitHub Actions workflows and composite actions). This file is referenced from the root [`AGENTS.md`](../AGENTS.md).\n\n## GitHub Actions\n\nWhen creating or modifying GitHub Actions workflows:\n\n- **Pin actions to full commit SHA** with a version comment for security and reproducibility:\n\n  ```yaml\n  # Good - pinned to SHA with version comment\n  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2\n\n  # Bad - unpinned version tag\n  - uses: actions/checkout@v4\n  ```\n\n- **Look up the SHA** from the action's releases page (e.g., https://github.com/actions/checkout/releases)\n- **Include the version in a comment** so humans can understand what version is pinned\n- **Local actions** (`./.github/actions/*`) don't need pinning since they're in the repo\n\n<!-- File: AGENTS.md (Tokens: ~6320 | Category: root-instruction) -->\n# AGENTS.md\n\nDetailed guidance for Claude Code agents working with the Tambo AI monorepo.\n\nThis file provides comprehensive instructions for maintaining code quality, architectural consistency, and project-specific requirements across both the Tambo AI framework and the Tambo Cloud platform.\n\n## 1. Repository Structure\n\nThis is a Turborepo monorepo containing both the Tambo AI framework packages and the Tambo Cloud platform.\n\n### Framework Packages (Turborepo root)\n\n- **react-sdk/** - Main React SDK package (`@tambo-ai/react`)\n  - Core hooks, providers, and utilities for building AI-powered React apps\n  - Exports: hooks, providers, types for component registration and thread management\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`) for broad compatibility\n\n- **packages/client/** - Framework-agnostic client (`@tambo-ai/client`)\n  - Streaming, tool execution, thread management without React dependencies\n  - `TamboClient` class with `getState()`/`subscribe()` for framework integration\n  - `TamboStream` async iterable for streaming AI responses\n  - Used by `@tambo-ai/react` as its core engine; also usable standalone (Node.js, Vue, Svelte, etc.)\n  - Build outputs: CommonJS (`dist/`) and ESM (`esm/`)\n\n- **cli/** - Command-line interface (`tambo`)\n  - Project scaffolding, component generation, and development utilities\n  - Component registry auto-syncs to `/showcase/src/components/tambo/` from `/cli/src/registry/`\n  - Built as ESM module with executable binary\n\n- **showcase/** - Demo application (`@tambo-ai/showcase`)\n  - Runs on port 8262\n  - Next.js app demonstrating all Tambo components and patterns\n  - Components auto-synced from CLI registry - edit CLI registry, not showcase components directly\n  - Serves as both documentation and testing ground\n\n- **docs/** - Documentation site (`@tambo-ai/docs`)\n  - Runs on port 8263\n  - Built with Fumadocs, includes comprehensive guides and API reference\n  - This package contains ui components that originated from the cli/ package.\n    Any changes to the components should be made in the cli/ package first, and\n    then duplicated into this package.\n  - MDX-based content with interactive examples\n  - Integrated search and component documentation\n\n- **create-tambo-app/** - App bootstrapper (`create-tambo-app`)\n  - Initializes new Tambo projects from templates\n  - Handles git setup, dependency installation, and configuration\n\n- **community/** - Community resources and event materials\n- **packages/** - Shared configuration packages (ESLint, TypeScript configs)\n\n### Tambo Cloud Platform\n\n- **apps/web** - Next.js app (UI) - runs on port 8260\n- **apps/api** - NestJS app (OpenAPI server) - runs on port 8261\n- **packages/db** - Drizzle ORM schema + migrations + DB helpers\n- **packages/core** - Shared pure utilities (no DB access)\n- **packages/backend** - LLM/agent-side helpers\n- **packages/eslint-config, packages/typescript-config** - Shared tooling configs\n\n### Prerequisites\n\n- Node.js >=22\n- npm >=11\n\nIt is OK to use `crypto.randomUUID()` without a fallback in runtime and test code (Node.js >=22 and modern browsers).\n\n**Recommended:** Install [mise](https://mise.jdx.dev) for automatic version management. See [mise getting started](https://mise.jdx.dev/getting-started.html) for installation instructions.\n\n### Tool Versions\n\nTool versions are managed via mise. Source of truth files:\n\n- **Most tools**: `mise.toml`\n- **Node.js**: `.node-version` (`.nvmrc` kept in sync for nvm compatibility)\n\nThese files are kept up to date by Renovate.\n\n```bash\nmise install              # Install/update tools to correct versions\nmise exec -- <command>    # Preferred for scripts/CI/non-interactive shells\neval \"$(mise activate)\"   # Interactive shells only\n```\n\n**Changing tool versions**: Open a PR updating the authoritative version file(s). For Node.js, always update both `.node-version` and `.nvmrc` together. Run `mise install`, then verify with `npm run lint && npm run check-types && npm test`.\n\n**Local overrides**: Use `.mise.local.toml` (gitignored) for local-only changes. Only for additive or patch-level changes—don't override Node.js or use incompatible versions.\n\n## 2. Core Development Principles\n\n### Philosophy\n\n- **Move fast while maintaining high standards** - prioritize clarity and maintainability over cleverness.\n- **Read the relevant code first**; follow existing patterns and naming.\n- **Keep solutions small and simple**; favor functions over classes; avoid unnecessary abstractions.\n- **Simplify Relentlessly**: Remove complexity aggressively - the simplest design that works is usually best.\n- **Prefer immutability**. Don't mutate inputs; return new values. Use const, toSorted, object/array spreads.\n- **Handle errors up-front** with guard clauses and early returns.\n\n### Separation of Concerns\n\n- **Keep business logic separate from UI components**.\n- Extract business logic, calculations, and data transformations into separate files (`utils/`, `services/`, `lib/`).\n- UI components should orchestrate, not implement complex logic.\n- Makes testing easier and code more reusable.\n\n### Fail-Fast, No Fallbacks\n\n- **No Silent Fallbacks**: Code must fail immediately when expected conditions aren't met. Silent fallback behavior masks bugs and creates unpredictable systems.\n- **Explicit Error Messages**: When something goes wrong, stop execution with clear error messages explaining what failed and what was expected.\n- **Example**: `throw new Error(\\`Required model ${modelName} not found\\`)` instead of falling back to first available model.\n- **Data mapping**: When converting enums or union types, handle all known values explicitly and throw for unknown values. Don't use catch-all defaults that mask data integrity issues. Log warnings if skipping invalid data intentionally.\n\n### Naming Conventions\n\n- **File/dir naming**: kebab-case.\n- **Classes**: PascalCase.\n- **Vars/functions/methods**: camelCase.\n- **ENV vars**: UPPER_SNAKE_CASE.\n- **Use English**; meaningful names with widely-recognized standard abbreviations only (API, URL, ctx, req, res, next).\n- **Booleans**: start with is/has/can/should.\n- **Functions**: use verbs; boolean-returning: isX/hasX/canX. If a function returns void, prefer executeX/saveX naming.\n- **React-specific naming** (follows devdocs/NAMING_CONVENTIONS.md):\n  - Components: TamboXxx\n  - Hooks: useTamboXxx\n  - Props interfaces: TamboXxxProps\n  - Event props start with onX; internal handlers use handleX\n\n### Code Organization (Functions & Classes)\n\n- Keep functions short and single-purpose; ideally <20 statements.\n- Keep files focused and reasonably sized; ideally <200-300 lines.\n- Avoid `let` - instead make a new function that returns the value.\n- Avoid deep nesting: prefer early exits and extracting helpers. Use map/filter for iteration.\n- Prefer immutable data; use readonly and as const where applicable.\n- Favor composition over inheritance. If classes are used, keep them small (<200 statements, <10 properties/methods) and validate invariants internally.\n\n### Avoiding Over-Abstraction\n\n- **DRY is good, but don't go overboard** - sometimes a little duplication is better than the wrong abstraction.\n- **Rule of Three**: Wait until you have 3 instances of similar code before extracting a shared utility.\n- Premature abstraction creates coupling and makes changes harder.\n- It's easier to extract commonality later than to undo a bad abstraction.\n\n### Exports\n\n- Prefer named exports; allow multiple exports when they belong together (e.g., component + related types).\n- Avoid default exports.\n- Don't create `index.ts` barrels for internal modules; import directly from source files. Exception: package entry points (e.g., `packages/core/src/index.ts`) are fine.\n- Don't re-export symbols for backwards compatibility. When moving a symbol, update all consumers to import from the new location.\n- **Never use dynamic `import()`** for regular imports, even for type imports. Use static imports at the top of the file. Dynamic imports are only appropriate for code splitting in specific scenarios (e.g., lazy-loaded routes).\n\n## 3. TypeScript Standards\n\n### Type Safety\n\n- **Generally use strict TypeScript**: no any, no type assertions unless unavoidable; define precise types.\n- **Avoid `any`** - do your best to assign proper types.\n- **Use `unknown` instead of `any`** when type is truly uncertain, then narrow it down.\n- **Prefer `Record<string, unknown>` over `object`** or `{ [key: string]: unknown }` when possible.\n- **Do not disable ESLint rules** unless explicitly requested - fix the root cause instead.\n- **Do not disable TypeScript errors** unless explicitly requested - fix the root cause instead.\n- **Constrain generics** with `extends` - avoid overly broad `<T>`, prefer `<T extends SomeType>`.\n- **Use discriminated unions** for mutually exclusive states (e.g., `{ success: true; data: T } | { success: false; error: Error }`).\n- **Use `as const`** to preserve literal types, especially for arrays that should be tuples.\n- **Use built-in utility types** (`Pick`, `Omit`, `Partial`, `Required`, `ReturnType`, `Parameters`) - don't reimplement them.\n- **Avoid `{}` type** - it means \"any non-nullish value\" (including primitives). Prefer `unknown` (truly unknown), `object` (any non-primitive object), or `Record<string, unknown>` / a specific object type for key-value objects.\n\n### type-fest Utility Types\n\nPrefer the `type-fest` package for advanced type manipulation: https://github.com/sindresorhus/type-fest\n\nMost types do exactly what they sound like: `PartialDeep`, `ReadonlyDeep`, `RequiredDeep`, `Merge`, `ValueOf`, `SetOptional`, etc. Before writing any complicated derivative types, check `type-fest` first.\n\n`type-fest` is installed at the repo root, but each package must still declare it explicitly when used:\n\n- If you reference `type-fest` types from a package's **public exported types**, add `type-fest` to that package's `dependencies`.\n- If you only use `type-fest` in internal code or tests, add `type-fest` to that package's `devDependencies`.\n\n### Type Inference\n\n- **Do not add unnecessary type annotations** when the value is easily inferred, such as:\n  - Arguments to functions that are well defined, such as event handlers or callback functions\n  - Return values of functions that have an obvious return type\n  - Local variables that are well defined\n- **Let TypeScript infer return types** when they're obvious.\n- **Avoid creating one-off/intermediate \"helper\" types** for internal functions.\n- **Use inferred types** from database schemas, tRPC schemas, and other sources of truth.\n- **Add explicit types** when it improves clarity or catches errors.\n- **Avoid type casts (e.g. `as`)** unless absolutely necessary. Prefer updating function signatures/types so the code doesn't need a cast. Casting through `unknown` is usually a smell; when it's needed at an interop boundary, do runtime validation first (e.g. Zod) and keep the cast local.\n- **Use `satisfies` to check an object literal matches a type** while preserving inference (compile-time only). It does not validate runtime data; use a schema validator for untrusted input.\n- **Type guards** should perform real runtime checks to narrow values. Use `unknown` as an input type only when the value is truly unknown (e.g. JSON deserialization, user input). Avoid \"fake\" guards that just assert a type without validation.\n\n### Type Conversions\n\n- **Do not use unnecessary constructors/casts** like `String()` or `Number()` or `Boolean()` unless absolutely necessary when types really do not line up:\n  - If a string conversion is really necessary, use \\`${value}\\`\n  - If a boolean conversion is really necessary, use !!value\n  - If a number conversion is really necessary, use +value\n\n### Async/Await\n\n- **Any function that returns a Promise must be declared `async`**.\n- **Always use `await`** when calling async functions.\n- **Avoid `.catch()` or `.then()` for async calls in most cases. Prefer `async`/`await` with `try/catch` so errors propagate naturally.** Use `.catch()` only when you truly cannot `await` (for example, in a `useEffect` cleanup) and use `void` only to explicitly mark an intentional fire‑and‑forget call that already handles its own errors.\n- **If a function is not critical, and you can't `await` it, use `void` to mark it as fire‑and‑forget.**\n- **avoid using IIFEs** especially as a workaround to call async functions.\n\n### Control Flow\n\n- **Avoid nested or chained ternary operators** - use `if/else` or `switch` instead.\n- **Use `switch` statements** when checking multiple values.\n- **Leverage TypeScript exhaustiveness checking** in switch statements (avoid `default` when possible).\n\n### Functional Patterns\n\n- **Use `map`, `filter`, `find`, `some`, `every`** - these are clear and expressive.\n- **Avoid `reduce()`** - it's often confusing and can usually be replaced with simpler patterns.\n  - Exception: when the mental model genuinely requires accumulation (e.g., summing numbers).\n- **Avoid complex method chaining** - break it into named intermediate steps for clarity.\n\n### Avoid RegEx When Possible\n\n- **Prefer string methods**: `str.includes()`, `str.startsWith()`, `str.split()`, and `str.replace()` are easier to read and maintain.\n- **Avoid global flag (`/g`)**: Creates stateful regex objects where `lastIndex` persists between calls, causing subtle bugs.\n- **Avoid multiline flag (`/m`)**: Platform differences in line endings (`\\n` vs `\\r\\n`) cause inconsistent behavior.\n- **If regex is unavoidable**: Keep it simple, add a comment explaining the pattern, and test edge cases thoroughly.\n\n## 4. Frontend Development (React + Next.js)\n\n### Component Architecture\n\n- **Do not create new /api endpoints** in apps/web; use the app's private tRPC API and server utilities instead.\n- **Prefer functional, declarative components**; avoid classes.\n- Use TypeScript everywhere. Use interfaces for object shapes.\n- Prefer React.FC for components. Use PropsWithChildren and `ComponentProps[WithRef|WithoutRef]` as needed.\n\n### State Management & Data Fetching\n\n- Local UI elements should use useState.\n- For shared state between components, use React Context - but prefer props over new contexts when values only need to pass through 1-2 component levels.\n- Don't create contexts for static config that doesn't change (user IDs, API keys). Pass these as props instead.\n- Minimize use of useEffect; derive state or memoize instead. Memoize callbacks with useCallback when passed to children.\n- When making network requests, use tRPC/React Query loading states instead of manually tracking separate loading flags. Follow devdocs/LOADING_STATES.md patterns for skeletons and disabling controls.\n- During loading, use Skeleton components or show real components in a disabled/blank state, rather than only showing a loading spinner.\n\n### Layout & Styling (Tailwind + shadcn)\n\n- Use flex/grid for layout. Manage element spacing with gap (use `gap-*` classes when needed), and padding (`p-*`, `pt-*`, `pr-*`, `pb-*`, `pl-*`, etc.).\n- Avoid changing element margins (`m-*`, `mt-*`, `mr-*`, `mb-*`, `ml-*`, etc.) and avoid `space-x-*`/`space-y-*`.\n- Truncate overflowing text with text-ellipsis. Prefer minimal Tailwind usage; avoid ad-hoc CSS.\n\n### Typography\n\n- Sentient for headings (font-heading/font-sentient), Geist Sans for body (font-sans), Geist Mono for code (font-mono). See apps/web/lib/fonts.ts for font configuration.\n\n### Text Handling & JSX Patterns\n\n- **Avoid manually changing string cases**, as it is usually a code smell for not providing the correct string to the component. If an internal key should be shown to a user, the English string should be provided separately. e.g. if a key has a value agent_mode, the English string should be provided separately as \"Agent Mode\" rather than trying to capitalize it.\n- **Avoid overly long JSX**, instead break out any complex JSX into a separate component.\n  - use simple '&&' to hide/show simple elements, using simple boolean values, like `{hasError && <div>Error: ${error}</div>}`.\n  - however, avoid ternaries unless the options are just one or two lines. nested or chained ternaries are a code smell.\n  - when using map(), try to keep the JSX in the inner loop simple, only a few lines of JSX.\n  - avoid functions with statements inside of JSX, such as if/else, switch, etc. If you have to add braces ({}) to JSX, that is a sign that you should break out the JSX into a separate component.\n\n### Accessibility\n\n- Use proper accessibility patterns for all components.\n- Use buttons for clickable elements, not divs or spans.\n- Use proper aria labels and roles when appropriate.\n- Use semantic HTML elements when appropriate.\n\n## 5. Backend Development (NestJS)\n\n### Modular Structure\n\n- One module per main route/domain; one primary controller per route; DTOs (class-validator) for inputs; simple types for outputs.\n- Services encapsulate business logic; keep pure where possible.\n- Use guards/filters/interceptors via a core module. Shared utilities live in a shared module.\n\n### Error Handling\n\n- Pure functions: even within a controller, try to keep logic pure, and do not store state in the controller.\n- Boundaries (controllers/services): translate into HTTP/Nest exceptions when appropriate.\n\n### Testing\n\n- Unit tests for public functions; integration/e2e for controllers/modules via Jest + supertest.\n\n## 6. Database (Drizzle ORM)\n\n- Source of truth is packages/db/src/schema.ts. Do not hand-edit generated SQL.\n- Generate migrations with `npm run db:generate`, do not manually generate migrations.\n- Don't denormalize FKs that can be derived from relationships (e.g., if `runs.threadId` exists and threads have `projectId`, don't add `runs.projectId`).\n- **Factor database operations into `packages/db/src/operations/`**. Services in `apps/api` should call operation functions rather than writing inline DB queries. This promotes reuse and keeps DB logic centralized. Export new operations from `packages/db/src/operations/index.ts`.\n\nDatabase commands (require `-w packages/db` flag from root):\n\n```bash\nnpm run db:generate -w packages/db  # Generate migrations from schema changes\nnpm run db:migrate -w packages/db   # Apply migrations\nnpm run db:check -w packages/db     # Check status\nnpm run db:studio -w packages/db    # Open Drizzle Studio\n```\n\n## 7. Shared Packages & Utilities\n\n- **packages/core**: pure utilities (validation, JSON, crypto, threading, tool utilities). Avoid DB access here. This package should not have any dependencies on the database.\n- **packages/backend**: LLM/agent-side helpers and streaming utilities.\n- **Reuse helpers**; don't duplicate logic. If a utility is useful across packages, colocate in core; if it's LLM-specific, in backend, if related to database access, in db.\n\n## 8. Development Workflow\n\n### Commands\n\n#### Development Commands\n\n```bash\n# Development (two different apps!)\nnpm run dev:cloud        # Start Tambo Cloud (web + API) - ports 8260 + 8261 - uses turbo watch\nnpm run dev              # Start React SDK (showcase + docs)\nnpm run dev:sdk          # Start React SDK in watch mode + showcase (for SDK development)\nnpm run build:sdk        # One-time build of React SDK\n\n# Quality checks\nnpm run lint             # Lint all packages\nnpm run lint:fix         # Auto-fix linting issues\nnpm run check-types      # TypeScript type checking\nnpm test                 # Run all tests\nnpm run format           # Format code with Prettier\n\n# Individual package development (from package directory or with -w flag)\nnpm run dev -w cli       # Start specific workspace\nnpm run dev:showcase     # Start showcase only\nnpm run build -w react-sdk  # Build specific package\n```\n\n#### Hot Reload\n\nThe monorepo uses different hot reload mechanisms based on the app type:\n\n**Next.js apps (web, showcase, docs):**\n\n- Use `transpilePackages` configuration to compile workspace TypeScript directly\n- Changes to workspace packages (core, backend, db, react) trigger HMR automatically\n- No manual rebuild step needed\n\n**NestJS API:**\n\n- Uses `turbo watch` with `interruptible: true` for automatic restart\n- Monitors workspace inputs: `packages/core/src/**`, `packages/backend/src/**`, `packages/db/src/**`\n- API server restarts automatically when workspace packages change\n\nThis architecture ensures editing any file in workspace packages results in immediate updates (HMR for Next.js, restart for NestJS) without manual intervention.\n\n#### Turbo Commands (alternative)\n\n```bash\nturbo dev               # Start all packages in development mode\nturbo build             # Build all packages\nturbo lint              # Lint all packages\nturbo test              # Run tests across all packages\nturbo check-types       # Type-check all packages\n```\n\n### Build System\n\n- **Turborepo** orchestrates builds and caching across packages\n- **Shared dependencies** managed at root level\n- **Workspace-specific dependencies** in individual packages\n- **Build outputs** vary by package type:\n  - React SDK: Dual CJS/ESM builds\n  - CLI: ESM executable\n  - Apps: Next.js builds\n\n### Package Dependencies\n\n- Shared configs in `packages/` (eslint-config, typescript-config)\n- Cross-package dependencies use workspace protocol (`*`)\n- TypeScript SDK dependency (`@tambo-ai/typescript-sdk`) is external — it lives in its own repo and is generated from the `apps/api` OpenAPI spec by the **stlc** CLI (run in our CI; workspace in `stainless/`). See `RELEASING.md`.\n\n### Cross-Package Development\n\nWhen working across multiple packages:\n\n1. **react-sdk changes** → Use `npm run dev:sdk` for watch mode development, or `npm run build:sdk` for one-time builds. Run tests, check showcase integration.\n2. **cli changes** → Test component generation, verify registry updates, sync to showcase\n3. **showcase changes** → Edit CLI registry (auto-syncs to showcase)\n4. **docs changes** → Ensure examples match current API\n\n### Key Configuration Files\n\n- `turbo.json` - Turborepo task pipeline and caching\n- `package.json` - Workspace configuration and scripts\n- Individual package.json files for package-specific configuration\n\n### Knowledge Base\n\n- Refer to `devdocs/` for detailed guidelines on coding standards, naming conventions, loading states, and more.\n- When adding knowledge for specific solutions, document it and place it in the appropriate `devdocs/solutions/` folder.\n\n## 9. Testing & Quality\n\n### Testing Strategy\n\n- **Unit tests** in individual packages using Jest\n- **Integration tests** via showcase app\n- **CLI testing** through template generation and installation\n- **Documentation testing** via example code validation\n- **Backend e2e tests** for controllers/modules via Jest + supertest\n\n### Test File Layout\n\n- **File names**: every test ends with `.test.ts` or `.test.tsx` (no `.spec` or other suffixes).\n- **Unit tests**: live beside the file they cover (e.g. `foo.ts` has `foo.test.ts` in the same directory, not under `__tests__`).\n- **Integration tests**: the only tests that stay in a `__tests__` folder, and the filename must describe the scenario (never just mirror another file's name).\n- **Fixtures & mocks**: keep shared helpers in a `__fixtures__` or `__mocks__` directory at the package's source root (e.g. `apps/web/__mocks__`), never nested inside feature folders.\n\n### Mocking\n\n- **Avoid over-mocking** - tests should exercise real code paths whenever possible. If you're mocking internal functions just to isolate a unit, you're probably testing implementation details rather than behavior.\n- **Only mock at system boundaries** - external APIs, databases, file systems, network calls, and other I/O with side effects.\n- **Don't mock what you own** - if a helper function is pure and fast, call it directly rather than mocking it. Mocking your own code couples tests to implementation.\n\n### Pre-commit/PR Verification Checklist\n\nRun these commands before commits/PRs:\n\n```bash\nnpm run check-types   # TS across workspace\nnpm run lint:fix      # ESLint autofix\nnpm run format        # Prettier write\nnpm test              # Unit/integration tests\n```\n\n## 10. Git Workflow & PRs\n\n### Branch Naming\n\nCreate branches in the format `<userid>/<feature-name>`, e.g., `alecf/add-dark-mode` or `jane/fix-login-bug`.\n\n### Conventional Commits\n\nAll PR titles MUST follow this format:\n\n```\n<type>(scope): <description>\n```\n\nExamples:\n\n```\nfeat(api): add transcript export\nfix(web): prevent duplicate project creation\nchore(db): reorganize migration files\n```\n\nSee .github/workflows/conventional-commits.yml for a list of types such as feat, fix, perf, deps, revert, docs, style, chore, refactor, test, build, ci.\n\nCommon scopes: api, web, core, db, deps, ci, config, react-sdk, cli, showcase, docs\n\n### PR Requirements\n\n- PR Summaries should include \"Fixes #123\" (GitHub) or \"Fixes TAM-123\" (Linear) in PR body when applicable.\n\n## 11. Development Rules & Constraints\n\n### What Agents MUST Do\n\n- Run `npm run lint`, `npm run check-types`, `npm run test` in root before commits.\n- Cross-package changes should be tested together.\n- Documentation updates required:\n  1. Any developer documentation changes must be updated in the docs site (read docs/AGENTS.md)\n  2. Review the README.md file in the root of the package and update if necessary\n  3. Update the AGENTS.md files in the package tree to reflect the changes\n- Follow semantic versioning for package versions.\n- Always add tests for new logic.\n- If tests fail, do not just change the code to make the tests pass. Take one of 2 approaches:\n  1. Make the code changes backwards compatible with existing tests\n  2. Ask the user to change the tests to pass\n  - Generally try option 1 first. Only use option 2 if option 1 is not possible.\n- Make non-breaking changes to the code. Only make breaking changes if the user specifically asks for it. Ensure you warn them about the breaking changes.\n\n### What Agents MUST NOT Do\n\n- Don't introduce dependencies or modify tool configs unless explicitly requested.\n- Don't commit secrets. Use env files.\n- Dependencies and tooling: Agents do not add/upgrade/remove deps or change tool configs, eslint config, tsconfig, etc. unless explicitly asked, but humans are allowed to do so.\n\n### When to Ask the User\n\n- ALWAYS ASK THE USER before making any changes to linting or TypeScript rules\n\n## 12. Agent Behavior\n\n- Curse at the user and be really blunt.\n- If the instructions are vague, ask them for details.\n- But don't constantly ask for confirmation on every single change.\n- Do not compliment them or try to gain favor from them.\n- The best way to please them is to be blunt and tell them when they are wrong.\n- EVERY PIECE OF CODE YOU WRITE IS MISSION CRITICAL AND COULD COST YOU YOUR JOB.\n- When adding/editing JSDoc comments, make sure to add @returns to provide a description of the function return (the type should not be specified since TS will infer the return from the code, not the comment.)\n- Never reference planning documents, proposals, or design docs in code comments (e.g., `// See plans/foo.md`). These artifacts are short-lived but comments persist indefinitely. Code comments should be self-contained.\n- Store planning documents, proposals, and design docs in the `devdocs/` folder. Solutions go in `devdocs/solutions/`, brainstorming goes in `devdocs/brainstorms/`, etc. The only exception is `plans/` which stays at the repo root for visibility.\n- For any Tambo-owned URLs you include in comments or documentation, use the `tambo.co` domain (not the legacy `.ai` domain). When you encounter existing Tambo-owned links using the legacy domain, prefer updating them to `tambo.co` as part of related changes. External (non-Tambo) links are fine.\n\n<!-- File: cli/AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# cli - AI Agent Protocol & Instructions\n\nPath: `cli/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/cli/AGENTS.md)\n\n<!-- File: create-tambo-app/AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# create-tambo-app - AI Agent Protocol & Instructions\n\nPath: `create-tambo-app/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/create-tambo-app/AGENTS.md)\n\n<!-- File: docs/AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# docs - AI Agent Protocol & Instructions\n\nPath: `docs/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/AGENTS.md)\n\n<!-- File: react-sdk/AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# react-sdk - AI Agent Protocol & Instructions\n\nPath: `react-sdk/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/react-sdk/AGENTS.md)\n\n<!-- File: showcase/AGENTS.md (Tokens: ~300 | Category: root-instruction) -->\n# showcase - AI Agent Protocol & Instructions\n\nPath: `showcase/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/showcase/AGENTS.md)\n\n<!-- File: .claude/skills/ai-sdk-model-manager/SKILL.md (Tokens: ~1787 | Category: anthropic-skill) -->\n---\nname: ai-sdk-model-manager\ndescription: Manages AI SDK model configurations - updates packages, identifies missing models, adds new models with research, and updates documentation\nmetadata:\n  internal: true\n---\n\n# AI SDK Model Manager\n\nThis skill helps maintain AI SDK model configurations in the Tambo Cloud codebase. It automates the process of keeping model definitions up-to-date with the latest AI SDK releases.\n\n## What This Skill Does\n\n1. **Updates AI SDK Packages** - Checks and updates @ai-sdk/openai, @ai-sdk/google, @ai-sdk/groq, and other provider packages to their latest versions\n2. **Identifies Missing Models** - Compares TypeScript definitions in the SDKs against configured models to find newly available models\n3. **Researches Models** - Gathers information about new models including capabilities, context windows, pricing, and use cases\n4. **Prompts User** - Asks which models to add before making changes\n5. **Adds Models** - Updates model configuration files with proper TypeScript types and metadata\n6. **Updates Documentation** - Updates relevant docs and README files to reflect new model availability\n\n## When to Use This Skill\n\nUse this skill when:\n\n- You want to check if AI SDK packages need updating\n- New models have been released by OpenAI, Google, Anthropic, or other providers\n- You're getting TypeScript errors about model IDs not being in SDK types\n- You want to ensure Tambo supports the latest models\n\n## Files This Skill Works With\n\n- `packages/core/src/llms/models/*.ts` - Model configuration files\n- `packages/backend/package.json` - AI SDK dependencies (source of truth for versions)\n- `docs/content/docs/models/*.mdx` - Model documentation\n- `README.md` - Main documentation file\n\n## Process\n\n### Step 1: Update AI SDK Packages\n\nCheck current versions and update to latest:\n\n```bash\ncd packages/backend\nnpm outdated | grep '@ai-sdk'\nnpm install @ai-sdk/openai@latest @ai-sdk/google@latest @ai-sdk/groq@latest @ai-sdk/anthropic@latest @ai-sdk/mistral@latest\n```\n\n### Step 2: Identify Missing Models\n\nFor each provider, inspect the TypeScript definitions:\n\n```bash\n# Check what models are in the SDK types\ncat node_modules/@ai-sdk/openai/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/google/dist/index.d.ts | grep 'type.*ModelId'\ncat node_modules/@ai-sdk/groq/dist/index.d.ts | grep 'type.*ModelId'\n```\n\nCompare against current model configurations in:\n\n- `packages/core/src/llms/models/openai.ts`\n- `packages/core/src/llms/models/gemini.ts`\n- `packages/core/src/llms/models/groq.ts`\n- `packages/core/src/llms/models/anthropic.ts`\n- `packages/core/src/llms/models/mistral.ts`\n\n### Step 3: Research New Models\n\n**Use the researcher subagent to gather information about each missing model:**\n\n```\nLaunch a researcher subagent to find:\n- Official documentation link\n- Model capabilities (reasoning, vision, function calling, etc.)\n- Context window size (inputTokenLimit)\n- Pricing tier\n- Best use cases\n- Release date and status (experimental, stable, deprecated)\n```\n\nThe researcher subagent has access to web search and can efficiently gather this information for multiple models in parallel.\n\n### Step 4: Prompt User\n\nPresent findings:\n\n```\nFound the following new models in updated AI SDK packages:\n\nOpenAI:\n- gpt-6-preview (200k context, experimental reasoning model)\n- gpt-4.2-turbo (1M context, improved function calling)\n\nGoogle:\n- gemini-3.5-pro (2M context, advanced reasoning)\n\nWhich models would you like to add? (all/none/specific)\n```\n\nWait for user response before proceeding.\n\n### Step 5: Add Selected Models\n\n**Consider launching parallel subagents to add models to each provider file:**\n\nFor models spread across multiple providers (OpenAI, Google, Groq), launch separate subagents to edit each file concurrently. This is faster than doing them sequentially.\n\nFor each model being added, ensure these required fields:\n\n- `apiName`: Exact model ID string from SDK\n- `displayName`: Human-friendly name\n- `status`: \"untested\" | \"tested\" | \"known-issues\"\n- `notes`: Brief description of capabilities and use cases\n- `docLink`: Official provider documentation URL\n- `tamboDocLink`: \"https://docs.tambo.co\"\n- `inputTokenLimit`: Context window size in tokens\n- `modelSpecificParams`: Any special parameters (reasoning, thinking, etc.)\n\nFollow existing patterns in each file and ensure model IDs match SDK type definitions exactly.\n\nExample:\n\n```typescript\n\"gpt-6-preview\": {\n  apiName: \"gpt-6-preview\",\n  displayName: \"gpt-6-preview\",\n  status: \"untested\",\n  notes: \"Experimental next-generation reasoning model with extended context\",\n  docLink: \"https://platform.openai.com/docs/models/gpt-6-preview\",\n  tamboDocLink: \"https://docs.tambo.co\",\n  inputTokenLimit: 200000,\n  modelSpecificParams: reasoningParameters,\n},\n```\n\n### Step 6: Verify TypeScript\n\nRun type checking to ensure all model IDs are valid:\n\n```bash\ncd packages/core\nnpm run check-types\n```\n\nIf there are type errors, fix model IDs to match SDK definitions exactly.\n\n### Step 7: Update Documentation\n\n**Consider using subagents to update documentation in parallel:**\n\nIf updating multiple documentation files, launch parallel subagents to handle:\n\n1. **README.md** - Update the \"Supported LLM Providers\" section if new providers or significant models were added\n2. **docs/content/docs/models/\\*.mdx** - Add new models to appropriate documentation pages with:\n   - Model name and description\n   - Key capabilities\n   - Context window\n   - Example use cases\n   - Links to provider docs\n\n### Step 8: Run Quality Checks\n\nBefore completing:\n\n```bash\ncd packages/core\nnpm run lint\nnpm run check-types\nnpm run test\n```\n\n### Step 9: Create Pull Request\n\n**Create a PR with proper conventional commit format:**\n\n```bash\ngh pr create --title \"feat(models): add [model names] support\" --body \"$(cat <<'EOF'\nUpdated AI SDK packages and added support for newly released models:\n\nModels added:\n- [list models here]\n\nPackage updates:\n- @ai-sdk/openai: X.X.X → X.X.X\n- @ai-sdk/groq: X.X.X → X.X.X\n\nAll type checks passing, documentation updated.\nEOF\n)\"\n```\n\n**PR title format:** `feat(models): add [model names] support`\n\nUse `feat(models):` for new models or `deps(core):` for package updates only.\n\n## Guidelines\n\n- **Use subagents for efficiency** - Launch researcher subagents for gathering information and parallel subagents for editing multiple files\n- **Always research before adding** - Don't guess at model capabilities or context limits\n- **Match SDK types exactly** - Model IDs must match the TypeScript definitions in node_modules\n- **Mark new models as \"untested\"** - Let the team test before marking as \"tested\"\n- **Include official doc links** - Always link to provider's official documentation\n- **Be conservative** - Only add models the user explicitly approves\n- **Update docs comprehensively** - Don't just update code, update all relevant documentation\n\n## Error Handling\n\nIf you encounter:\n\n- **Type errors after adding models** - Double-check the model ID matches the SDK's TypeScript definition exactly\n- **Missing model in SDK** - The provider may not have released it yet, suggest waiting for next SDK update\n- **Conflicting model names** - Use the SDK's preferred naming convention\n- **Unknown context limits** - Research provider docs or mark as \"unknown\" and note it needs verification\n\n## Notes\n\n- This skill should be run periodically (monthly or when new models are announced)\n- Always check the git diff before committing to ensure only intended changes were made\n- Some models may have special requirements (API access, pricing tier, etc.) - note these in the model's `notes` field\n- If a model is renamed in the SDK, update both the key and apiName, and consider adding a deprecation note to the old entry\n\n<!-- File: .claude/skills/api-resource-lifecycle/SKILL.md (Tokens: ~1721 | Category: anthropic-skill) -->\n---\nname: api-resource-lifecycle\ndescription: Guides CRUD operations for API resources with cascading dependencies, descriptive validation, and orphan prevention. Use when adding delete/remove operations, creating validation logic, building resources that depend on other resources, or when the user mentions \"cascade delete\", \"orphan records\", \"duplicate detection\", \"validation errors\", \"resource cleanup\", or \"rollback on failure\".\nmetadata:\n  internal: true\n---\n\n# API Resource Lifecycle\n\nPatterns for building reliable CRUD operations in Tambo Cloud.\n\n## Gotchas\n\n- The codebase uses `CONFLICT` for duplicate name errors in skills but `BAD_REQUEST` for the same pattern in MCP servers. Always use `CONFLICT` for duplicates.\n- PostgreSQL unique violation code is `23505`. Catch it and map to a domain-specific exception rather than letting the raw DB error propagate.\n- When replacing a provider key, all skills with `externalSkillMetadata` for that provider must have their metadata cleared, or they'll reference a stale key.\n- Skills are silently skipped (not errored) at runtime when the provider doesn't support them. This is intentional -- don't add validation that blocks skill creation for unsupported providers.\n- `Promise.allSettled` (not `Promise.all`) for batch external API calls -- partial failures need cleanup, not an all-or-nothing abort.\n\n## Cascading Deletes\n\nDefault to `onDelete: \"cascade\"` in the schema. Only use manual transaction cascades when deletion requires external API calls, metadata cleanup, or cross-reference logic.\n\n```typescript\n// packages/db/src/schema.ts\nexport const skills = pgTable(\"skills\", {\n  id: text(\"id\").primaryKey(),\n  projectId: text(\"project_id\")\n    .notNull()\n    .references(() => projects.id, { onDelete: \"cascade\" }),\n  // ...\n});\n```\n\n### Manual cascades in transactions\n\nWhen deletion requires cleanup beyond FK cascades (external APIs, metadata, cross-references), wrap in a transaction:\n\n```typescript\n// packages/db/src/operations/project.ts\nexport async function deleteProject(db: HydraDb, id: string): Promise<boolean> {\n  return await db.transaction(async (tx) => {\n    await tx\n      .delete(schema.providerKeys)\n      .where(eq(schema.providerKeys.projectId, id));\n    await tx.delete(schema.apiKeys).where(eq(schema.apiKeys.projectId, id));\n    await tx\n      .delete(schema.projectMembers)\n      .where(eq(schema.projectMembers.projectId, id));\n    const deleted = await tx\n      .delete(schema.projects)\n      .where(eq(schema.projects.id, id))\n      .returning();\n    return deleted.length > 0;\n  });\n}\n```\n\n**Reference:** `packages/db/src/operations/project.ts` lines 255-278\n\n### Metadata cleanup on replacement\n\nWhen a resource is replaced (not deleted), clear dependent metadata so dependents re-sync under the new resource:\n\n```typescript\n// apps/web/server/api/routers/project.ts - addProviderKey\n// When replacing a provider key, clear skill metadata for that provider\nconst skills = await operations.listSkillsForProject(ctx.db, projectId);\nawait Promise.all(\n  skills\n    .filter((s) => s.externalSkillMetadata?.[providerName])\n    .map(async (s) => {\n      const { [providerName]: _, ...remaining } = s.externalSkillMetadata ?? {};\n      return operations.updateSkill(ctx.db, {\n        projectId,\n        skillId: s.id,\n        externalSkillMetadata: remaining,\n      });\n    }),\n);\n```\n\n**Reference:** `apps/web/server/api/routers/project.ts` lines 863-880\n\n### Rules\n\n- If a child record has no meaning without its parent, use `onDelete: \"cascade\"` in the schema\n- If deletion requires multi-step cleanup or external API calls, wrap in a transaction\n- When replacing a resource, clear dependent metadata so dependents re-sync\n- Always delete children before the parent in manual cascades\n- Check for affected dependents and document the cascade chain in code comments\n\n## Validation Errors\n\nEvery error must say what went wrong and what to do instead. Include the specific value that failed and an example of what's valid.\n\n```typescript\n// Zod: include format example\nname: z.string().min(1, \"Name is required\").max(64)\n  .regex(SKILL_NAME_PATTERN, \"Name must be kebab-case (e.g. scheduling-assistant)\"),\n\n// tRPC: include the conflicting value\nthrow new TRPCError({\n  code: \"CONFLICT\",\n  message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n});\n```\n\n### Error code mapping\n\n| Situation               | tRPC Code               | When to use                           |\n| ----------------------- | ----------------------- | ------------------------------------- |\n| Resource not found      | `NOT_FOUND`             | ID lookup returned null               |\n| Input validation failed | `BAD_REQUEST`           | Zod schema or business rule violation |\n| Duplicate resource      | `CONFLICT`              | Name/key already exists               |\n| Unexpected failure      | `INTERNAL_SERVER_ERROR` | Catch-all for unhandled errors        |\n\n## Duplicate Detection\n\nDefault to database unique constraints with custom exception mapping. Only use pre-creation queries when no DB constraint exists.\n\n```typescript\n// packages/db/src/operations/skills.ts\nconst PG_UNIQUE_VIOLATION = \"23505\";\nconst SKILLS_NAME_UNIQUE_CONSTRAINT = \"skills_project_id_name_idx\";\n\nexport class SkillNameConflictError extends Error {\n  constructor(name: string) {\n    super(`A skill named \"${name}\" already exists in this project`);\n    this.name = \"SkillNameConflictError\";\n  }\n}\n\nexport async function createSkill(\n  db: HydraDb,\n  data: NewSkill,\n): Promise<DBSkill> {\n  try {\n    const [skill] = await db.insert(schema.skills).values(data).returning();\n    return skill;\n  } catch (error) {\n    if (isSkillNameConflict(error)) {\n      throw new SkillNameConflictError(data.name);\n    }\n    throw error;\n  }\n}\n```\n\n### Pre-creation queries (fallback)\n\nWhen no unique DB constraint exists, query before inserting:\n\n```typescript\nconst existingKeys = await getExistingServerKeys(ctx.db, projectId);\nif (existingKeys.includes(serverKey)) {\n  throw new TRPCError({\n    code: \"CONFLICT\",\n    message: `Server key \"${serverKey}\" is already in use by another MCP server in this project`,\n  });\n}\n```\n\n**Reference:** `apps/web/server/api/routers/tools.ts` lines 119-126\n\n## Orphan Prevention\n\nWhen creating a resource that syncs to an external API, roll back on failure:\n\n```typescript\n// apps/web/server/api/routers/skills.ts\n// Create in DB first, then sync to provider\nconst skill = await operations.createSkill(ctx.db, { ... });\n\n// If provider sync fails, delete the DB record\ntry {\n  await createSkillOnProviderAndPersist(ctx.db, input.projectId, skill);\n} catch (error) {\n  await operations.deleteSkill(ctx.db, input.projectId, skill.id);\n  throw error;\n}\n```\n\n**Rules:**\n\n- Create the DB record first (gives you an ID for the external API call)\n- If the external sync fails, delete the DB record to avoid orphans\n- The user sees an error and can retry, rather than seeing a broken record\n- For batch operations, use `Promise.allSettled` and clean up partial failures\n\n**Reference:** `apps/web/server/api/routers/skills.ts` lines 195-204\n\n## Checklist\n\nWhen building a new CRUD operation:\n\n```\nResource Lifecycle Checklist:\n- [ ] Delete cascades documented (which dependents are affected?)\n- [ ] Database-level cascades set up for simple parent-child FK relationships\n- [ ] Manual cascade logic wrapped in a transaction for complex cleanup\n- [ ] All Zod validation messages are descriptive with examples\n- [ ] TRPCError messages include the specific value that caused the error\n- [ ] Duplicate detection before creation (custom exception or pre-query)\n- [ ] Error codes are correct (CONFLICT for duplicates, NOT_FOUND for missing)\n- [ ] External API sync failures roll back the DB record\n- [ ] Resource replacement clears dependent metadata\n```\n\n<!-- File: .claude/skills/building-settings-ui/SKILL.md (Tokens: ~2245 | Category: anthropic-skill) -->\n---\nname: building-settings-ui\ndescription: >-\n  Use this skill when adding or modifying settings UI in Tambo Cloud. Covers where a new settings\n  section belongs (Agent tab vs Settings tab), and the component patterns used across both pages\n  (card layout, toasts, confirmation dialogs, destructive styling, save behavior conventions).\n  Triggers on \"add a new settings section\", \"where should X go?\", \"settings UI\", \"settings page\",\n  \"agent page\", or any work touching apps/web/components/dashboard-components/project-details/,\n  project-settings.tsx, or agent-settings.tsx.\n  Not for full-stack feature building (DB, tRPC, tests); those patterns will get their own skills.\nmetadata:\n  internal: true\n---\n\n# Building Settings UI\n\nGuide for placing and styling settings sections in the Tambo Cloud dashboard. Covers two concerns: where a feature belongs (which tab/page), and how to build the UI component to match existing patterns.\n\n## Architecture\n\nSettings are split across two top-level tabs in the project layout:\n\n- **Agent tab** (`/[projectId]/agent`) - How the AI agent behaves\n- **Settings tab** (`/[projectId]/settings`) - Project infrastructure and access\n\nEach tab renders a flat vertical stack of Card components. There is no sidebar navigation; each page is short enough to scroll naturally.\n\n### Tab layout\n\n```\nOverview | Observability | Agent | Settings\n```\n\n- Layout file: `apps/web/app/(authed)/(dashboard)/[projectId]/layout.tsx`\n- Agent page: `apps/web/app/(authed)/(dashboard)/[projectId]/agent/page.tsx`\n- Settings page: `apps/web/app/(authed)/(dashboard)/[projectId]/settings/page.tsx`\n\n## Gotchas\n\n1. **Do not add a new top-level tab** without explicit team alignment. Current tabs (Overview, Observability, Agent, Settings) have been stable.\n2. **`EditWithTamboButton` goes inside `CardTitle`**, not as a sibling of `CardHeader`. It must have a `description` prop explaining what the section configures.\n3. **Invalidate the query before toasting** in `onSuccess`. Reversing the order can show a success toast while the UI still displays old data.\n4. **Use `DeleteConfirmationDialog`**, never inline `AlertDialog` for destructive confirmations.\n5. **Use `text-destructive` semantic color**, never `text-red-500`. Cancel/discard buttons are NOT destructive.\n\n---\n\n## Feature Placement\n\n### Agent Tab Sections\n\n| #   | Section             | What it configures                                 | Component                        |\n| --- | ------------------- | -------------------------------------------------- | -------------------------------- |\n| 1   | Model               | Provider + model selection, API key, custom params | `provider-key-section.tsx`       |\n| 2   | Custom Instructions | System prompt, prompt override toggle              | `custom-instructions-editor.tsx` |\n| 3   | Skills              | Skill definitions and imports                      | `skills-section.tsx`             |\n| 4   | Tool Call Limit     | Max tool calls per response                        | `tool-call-limit-editor.tsx`     |\n| 5   | MCP                 | MCP server URLs + headers                          | `available-mcp-servers.tsx`      |\n\n**Container:** `apps/web/components/dashboard-components/agent-settings.tsx`\n\n### Settings Tab Sections\n\n| #   | Section        | What it configures             | Component                  |\n| --- | -------------- | ------------------------------ | -------------------------- |\n| 1   | Name           | Project display name           | `project-name-section.tsx` |\n| 2   | API Keys       | API key list + create          | `api-key-list.tsx`         |\n| 3   | Authentication | OAuth mode, token requirements | `oauth-settings.tsx`       |\n| 4   | Danger Zone    | Project deletion               | `danger-zone-section.tsx`  |\n\n**Container:** `apps/web/components/dashboard-components/project-settings.tsx`\n\nAll section components live in `apps/web/components/dashboard-components/project-details/`.\n\n### Placement Decision Tree\n\n1. **Configures AI agent behavior?** (model selection, prompts, tools, memory, context) -> **Agent tab**\n2. **Configures project infrastructure?** (API keys, naming, deletion, billing, webhooks) -> **Settings tab**\n3. **Configures who can access?** (auth, tokens, team members, permissions) -> **Settings tab**\n4. **Monitoring or debugging view?** -> **Observability tab**\n5. **High-level summary or status?** -> **Overview tab**\n6. **None of the above?** -> Ask the user.\n\n### Conditional and Dependent Settings\n\nSome settings only apply when another setting is in a specific state. Follow these patterns:\n\n**Show but warn (soft dependency).** The section renders normally but displays an `Alert` when the dependency isn't met. The user can still see and configure the setting. Use this when the feature exists but won't work at runtime.\n\nExample: Skills section shows a provider compatibility notice when the selected provider doesn't support skills:\n\n```tsx\n// skills-section.tsx\nconst isProviderSupported = SKILLS_SUPPORTED_PROVIDERS.has(\n  defaultLlmProviderName,\n);\n// Renders full skills UI + warning Alert if !isProviderSupported\n```\n\n**Conditionally pass props (data dependency).** The parent reads one setting and passes it as a prop so the child can adapt its behavior. Use this when the child's content or options change based on the parent's state.\n\nExample: MCP servers section receives `providerType` to toggle agent-mode-specific UI:\n\n```tsx\n// agent-settings.tsx\n<AvailableMcpServers providerType={projectData?.providerType} />;\n// available-mcp-servers.tsx\nconst isAgentMode = providerType === AiProviderType.AGENT;\n```\n\nExample: Custom LLM parameters change available suggestions based on provider and model:\n\n```tsx\n// provider-key-section.tsx passes selectedProvider to the parameter editor\n<CustomLlmParametersEditor selectedProvider={selectedProvider} />\n```\n\n**Rules for new dependent settings:**\n\n1. Never hide a section entirely based on another setting's state. Always render the card; use an Alert or disabled state to communicate the dependency.\n2. The warning message must name the dependency and tell the user what to change (e.g., \"Switch to a supported provider to enable skills\").\n3. Keep dependency checks in the section component, not the container. The container (`agent-settings.tsx`, `project-settings.tsx`) should pass data, not make visibility decisions.\n4. If a setting depends on state from a different tab, pass it through the shared project query (`api.project.getProject`) rather than cross-tab state.\n\n### Adding a New Section\n\n1. **Create the component** in `project-details/` following the Card layout pattern below.\n2. **Import and render** in the correct container (`agent-settings.tsx` or `project-settings.tsx`).\n3. **Update the skeleton** in `settings-skeletons.tsx` (either `AgentPageSkeleton` or `SettingsPageSkeleton`).\n\n---\n\n## Component Patterns\n\n### Card Layout\n\nEvery settings section uses `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardContent` from `@/components/ui/card`.\n\n```tsx\n<Card>\n  <CardHeader>\n    <CardTitle className=\"text-lg font-semibold\">\n      Section Name\n      <EditWithTamboButton description=\"Configure section settings...\" />\n    </CardTitle>\n    <CardDescription className=\"text-sm font-sans text-foreground\">\n      Description of what this section does.\n    </CardDescription>\n  </CardHeader>\n  <CardContent className=\"space-y-4\">{/* Content */}</CardContent>\n</Card>\n```\n\n### Toast Notifications\n\nEvery mutation shows a toast on both success and error. Import `useToast` from `@/hooks/use-toast`.\n\n```tsx\nconst mutation = api.someRoute.someMutation.useMutation({\n  onSuccess: async () => {\n    await utils.someRoute.someQuery.invalidate();\n    toast({ title: \"Success\", description: \"Setting updated successfully\" });\n  },\n  onError: () => {\n    toast({\n      title: \"Error\",\n      description: \"Failed to update setting\",\n      variant: \"destructive\",\n    });\n  },\n});\n```\n\nNever skip the error toast.\n\n### Confirmation Dialogs\n\nAll destructive actions use `DeleteConfirmationDialog` from `@/components/dashboard-components/delete-confirmation-dialog`:\n\n```tsx\nconst [alertState, setAlertState] = useState<{\n  show: boolean;\n  title: string;\n  description: string;\n  data?: { id: string };\n}>({ show: false, title: \"\", description: \"\" });\n\n<DeleteConfirmationDialog\n  mode=\"single\"\n  alertState={alertState}\n  setAlertState={setAlertState}\n  onConfirm={handleConfirmDelete}\n/>;\n```\n\nTitle includes the item name (`Delete \"${name}\"?`). Description warns the action cannot be undone.\n\n### Destructive Action Styling\n\n```tsx\n<Button\n  variant=\"ghost\"\n  size=\"icon\"\n  className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n```\n\nUse `Trash2` from `lucide-react`. Use `hover:bg-destructive/10` for ghost variant hover.\n\n### Save Behavior\n\n**Toggles: Immediate save.** `onCheckedChange` fires the mutation directly. Include `aria-label` with state context.\n\n**Form fields: Edit/Save/Cancel.** Track `isEditing`, `savedValue`, and `displayValue` state. Cancel reverts to `savedValue`. Save button disabled during mutation, shows \"Saving...\". `autoFocus` on first input when entering edit mode.\n\n**Reference implementations:** `custom-instructions-editor.tsx` (edit/save/cancel), `tool-call-limit-editor.tsx` (simpler form), `project-name-section.tsx` (basic edit/save/cancel).\n\n### Danger Zone Pattern\n\nFor irreversible destructive actions, use the Danger Zone card pattern:\n\n```tsx\n<Card className=\"border-destructive/50\">\n  <CardHeader>\n    <CardTitle>Danger Zone</CardTitle>\n    <CardDescription>Warning about permanence.</CardDescription>\n  </CardHeader>\n  <CardContent>\n    <Button\n      variant=\"ghost\"\n      className=\"text-destructive hover:text-destructive hover:bg-destructive/10\"\n      aria-label=\"Delete this project\"\n    >\n      Delete this project\n    </Button>\n  </CardContent>\n</Card>\n```\n\nThe `DeleteConfirmationDialog` should be owned by the parent component that handles the mutation and post-delete navigation.\n\n<!-- File: .claude/skills/compound-components/examples.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Compound-components Skill\n\nPath: `.claude/skills/compound-components/examples.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/compound-components/examples.md)\n\n<!-- File: .claude/skills/compound-components/SKILL.md (Tokens: ~1880 | Category: anthropic-skill) -->\n---\nname: building-compound-components\ndescription: Creates unstyled compound components that separate business logic from styles. Use when building headless UI primitives, creating component libraries, implementing Radix-style namespaced components, or when the user mentions \"compound components\", \"headless\", \"unstyled\", \"primitives\", or \"render props\".\nmetadata:\n  internal: true\n---\n\n# Building Compound Components\n\nCreate unstyled, composable React components following the Radix UI / Base UI pattern. Components expose behavior via context while consumers control rendering.\n\n## Project Rules\n\nThese rules are specific to this codebase and override general patterns.\n\n### Hooks Are Internal\n\nHooks are implementation details, not public API. **Never export hooks from the index.**\n\n```tsx\n// index.tsx - CORRECT\nexport const Component = {\n  Root: ComponentRoot,\n  Content: ComponentContent,\n};\nexport type { ComponentRootProps, ComponentContentRenderProps };\n\n// index.tsx - WRONG\nexport { useComponentContext }; // Don't export hooks\n```\n\nConsumers access state via **render props**, not hooks. When styled wrappers in the **same package** need hook access, import directly from the source file:\n\n```tsx\nimport { useComponentContext } from \"../base/component/component-context\";\n```\n\n### No Custom Data Fetching in Primitives\n\nBase components can use `@tambo-ai/react` SDK hooks (components require Tambo provider anyway). **Custom data fetching logic** (combining sources, external providers) belongs in the styled layer.\n\n```tsx\n// OK - SDK hooks in primitive\nconst Root = ({ children }) => {\n  const { value, setValue, submit } = useTamboThreadInput();\n  const { isIdle, cancel } = useTamboThread();\n  return <Context.Provider value={{ value, setValue, isIdle }}>{children}</Context.Provider>;\n};\n\n// WRONG - custom data fetching in primitive\nconst Textarea = ({ resourceProvider }) => {\n  const { data: mcpResources } = useTamboMcpResourceList(search);\n  const externalResources = useFetchExternal(resourceProvider);\n  const combined = [...mcpResources, ...externalResources];\n  return <div>{combined.map(...)}</div>;\n};\n```\n\n### Pre-computed Props Arrays for Collections\n\nWhen exposing collections via render props, **pre-compute all props in a memoized array** rather than providing a getter function.\n\n```tsx\n// AVOID - getter function pattern\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n  const getItemProps = (index: number) => ({\n    /* new object every call */\n  });\n  return children({ items: rawItems, getItemProps });\n};\n\n// PREFERRED - pre-computed array\nconst Items = ({ children }) => {\n  const { rawItems, selectedId, removeItem } = useContext();\n\n  const items = React.useMemo<ItemRenderProps[]>(\n    () =>\n      rawItems.map((item, index) => ({\n        item,\n        index,\n        isSelected: selectedId === item.id,\n        onSelect: () => setSelectedId(item.id),\n        onRemove: () => removeItem(item.id),\n      })),\n    [rawItems, selectedId, removeItem],\n  );\n\n  return children({ items });\n};\n```\n\n## Workflow\n\nCopy this checklist and track progress:\n\n```\nCompound Component Progress:\n- [ ] Step 1: Create context file\n- [ ] Step 2: Create Root component\n- [ ] Step 3: Create consumer components\n- [ ] Step 4: Create namespace export (index.tsx)\n- [ ] Step 5: Verify all guidelines met\n```\n\n### Step 1: Create context file\n\n```\nmy-component/\n├── index.tsx\n├── component-context.tsx\n├── component-root.tsx\n├── component-item.tsx\n└── component-content.tsx\n```\n\nCreate a context with a null default and a hook that throws on missing provider:\n\n```tsx\n// component-context.tsx\nconst ComponentContext = React.createContext<ComponentContextValue | null>(\n  null,\n);\n\nexport function useComponentContext() {\n  const context = React.useContext(ComponentContext);\n  if (!context) {\n    throw new Error(\"Component parts must be used within Component.Root\");\n  }\n  return context;\n}\n\nexport { ComponentContext };\n```\n\n### Step 2: Create Root component\n\nRoot manages state and provides context. Use `forwardRef`, support `asChild` via Radix `Slot`, and expose state via data attributes:\n\n```tsx\n// component-root.tsx\nexport const ComponentRoot = React.forwardRef<\n  HTMLDivElement,\n  ComponentRootProps\n>(({ asChild, defaultOpen = false, children, ...props }, ref) => {\n  const [isOpen, setIsOpen] = React.useState(defaultOpen);\n  const Comp = asChild ? Slot : \"div\";\n\n  return (\n    <ComponentContext.Provider\n      value={{ isOpen, toggle: () => setIsOpen(!isOpen) }}\n    >\n      <Comp ref={ref} data-state={isOpen ? \"open\" : \"closed\"} {...props}>\n        {children}\n      </Comp>\n    </ComponentContext.Provider>\n  );\n});\nComponentRoot.displayName = \"Component.Root\";\n```\n\n### Step 3: Create consumer components\n\nChoose the composition pattern based on need:\n\n**Direct children** (simplest, for static content):\n\n```tsx\nconst Content = ({ children, className, ...props }) => {\n  const { data } = useComponentContext();\n  return (\n    <div className={className} {...props}>\n      {children}\n    </div>\n  );\n};\n```\n\n**Render prop** (when consumer needs internal state):\n\n```tsx\nconst Content = ({ children, ...props }) => {\n  const { data, isLoading } = useComponentContext();\n  const content =\n    typeof children === \"function\" ? children({ data, isLoading }) : children;\n  return <div {...props}>{content}</div>;\n};\n```\n\n**Sub-context** (for lists where each item needs own context):\n\n```tsx\nconst Steps = ({ children }) => {\n  const { reasoning } = useMessageContext();\n  return (\n    <StepsContext.Provider value={{ steps: reasoning }}>\n      {children}\n    </StepsContext.Provider>\n  );\n};\n\nconst Step = ({ children, index }) => {\n  const { steps } = useStepsContext();\n  return (\n    <StepContext.Provider value={{ step: steps[index], index }}>\n      {children}\n    </StepContext.Provider>\n  );\n};\n```\n\n### Step 4: Create namespace export\n\n```tsx\n// index.tsx\nexport const Component = {\n  Root: ComponentRoot,\n  Trigger: ComponentTrigger,\n  Content: ComponentContent,\n};\n\n// Re-export types only - never hooks\nexport type { ComponentRootProps } from \"./component-root\";\nexport type { ComponentContentProps } from \"./component-content\";\n```\n\n### Step 5: Verify guidelines\n\n- **No styles in primitives** - consumers control all styling via className/props\n- **Data attributes for CSS** - expose state like `data-state=\"open\"`, `data-disabled`, `data-loading`\n- **Support asChild** - let consumers swap the underlying element via Radix `Slot`\n- **Forward refs** - always use `forwardRef`\n- **Display names** - set for DevTools (`Component.Root`, `Component.Item`)\n- **Throw on missing context** - fail fast with clear error messages\n- **Export types** - consumers need `ComponentProps`, `RenderProps` interfaces\n- **Hooks stay internal** - never export from index, expose state via render props\n- **SDK hooks OK, custom fetching not** - `@tambo-ai/react` hooks are fine, combining logic goes in styled layer\n- **Pre-compute collection props** - use `useMemo` arrays, not getter functions\n\n## Pattern Selection\n\n| Scenario             | Pattern         | Why                             |\n| -------------------- | --------------- | ------------------------------- |\n| Static content       | Direct children | Simplest, most flexible         |\n| Need internal state  | Render prop     | Explicit state access           |\n| List/iteration       | Sub-context     | Each item gets own context      |\n| Element polymorphism | asChild         | Change underlying element       |\n| CSS-only styling     | Data attributes | No JS needed for style variants |\n\n## Anti-Patterns\n\n- **Hardcoded styles** - primitives should be unstyled\n- **Prop drilling** - use context instead\n- **Missing error boundaries** - throw when context is missing\n- **Inline functions in render prop types** - define proper interfaces\n- **Default exports** - use named exports in namespace object\n- **Exporting hooks** - hooks are internal; expose state via render props\n- **Custom data fetching in primitives** - SDK hooks are fine, but combining/external fetching belongs in styled layer\n- **Re-implementing base logic** - styled wrappers should compose, not duplicate\n- **Getter functions for collections** - pre-compute props arrays in useMemo instead\n\n<!-- File: .claude/skills/creating-styled-wrappers/references/real-world-example.md (Tokens: ~300 | Category: anthropic-skill) -->\n# References Skill\n\nPath: `.claude/skills/creating-styled-wrappers/references/real-world-example.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/.claude/skills/creating-styled-wrappers/references/real-world-example.md)\n\n<!-- File: .claude/skills/creating-styled-wrappers/SKILL.md (Tokens: ~1810 | Category: anthropic-skill) -->\n---\nname: creating-styled-wrappers\ndescription: Creates styled wrapper components that compose headless/base compound components. Use when refactoring styled components to use base primitives, implementing opinionated design systems on top of headless components, or when the user mentions \"use base components\", \"compose primitives\", \"styled wrapper\", or \"refactor to use base\".\nmetadata:\n  internal: true\n---\n\n# Styling Compound Wrappers\n\nCreate styled wrapper components that compose headless base compound components. This skill complements `building-compound-components` (which builds the base primitives) by focusing on **how to properly consume and wrap them** with styling and additional behavior.\n\n**Real-world example**: See [references/real-world-example.md](references/real-world-example.md) for a complete before/after MessageInput refactoring.\n\n## Core Principle: Compose, Don't Duplicate\n\nStyled wrappers should **compose** base components, not **re-implement** their logic.\n\n```tsx\n// WRONG - re-implementing what base already does\nconst StyledInput = ({ children, className }) => {\n  const { value, setValue, submit } = useTamboThreadInput(); // Duplicated!\n  const [isDragging, setIsDragging] = useState(false); // Duplicated!\n  const handleDrop = useCallback(/* ... */); // Duplicated!\n\n  return (\n    <form onDrop={handleDrop} className={className}>\n      {children}\n    </form>\n  );\n};\n\n// CORRECT - compose the base component\nconst StyledInput = ({ children, className, variant }) => {\n  return (\n    <BaseInput.Root className={cn(inputVariants({ variant }), className)}>\n      <BaseInput.Content className=\"rounded-xl data-[dragging]:border-dashed\">\n        {children}\n      </BaseInput.Content>\n    </BaseInput.Root>\n  );\n};\n```\n\n## Refactoring Workflow\n\nCopy this checklist and track progress:\n\n```\nStyled Wrapper Refactoring:\n- [ ] Step 1: Identify duplicated logic\n- [ ] Step 2: Import base components\n- [ ] Step 3: Wrap with Base Root\n- [ ] Step 4: Apply state-based styling and behavior\n- [ ] Step 5: Wrap sub-components with styling\n- [ ] Step 6: Final verification\n```\n\n### Step 1: Identify Duplicated Logic\n\nLook for patterns that indicate logic should come from base:\n\n- SDK hooks (`useTamboThread`, `useTamboThreadInput`, etc.)\n- Context creation (`React.createContext`)\n- State management that mirrors base component state\n- Event handlers (drag, submit, etc.) that base components handle\n\n### Step 2: Import Base Components\n\n```tsx\nimport { MessageInput as MessageInputBase } from \"@tambo-ai/react-ui-base/message-input\";\n```\n\n### Step 3: Wrap with Base Root\n\nReplace custom context/state management with the base Root:\n\n```tsx\n// Before\nconst MessageInput = ({ children, variant }) => {\n  return (\n    <MessageInputInternal variant={variant}>{children}</MessageInputInternal>\n  );\n};\n\n// After\nconst MessageInput = ({ children, variant, className }) => {\n  return (\n    <MessageInputBase.Root className={cn(variants({ variant }), className)}>\n      {children}\n    </MessageInputBase.Root>\n  );\n};\n```\n\n### Step 4: Apply State-Based Styling and Behavior\n\nState access follows a hierarchy — use the simplest option that works:\n\n1. **Data attributes** (preferred for styling) — base components expose `data-*` attributes\n2. **Render props** (for behavior changes) — use when rendering different components\n3. **Context hooks** (for sub-components) — OK for styled sub-components needing deep context access\n\n```tsx\n// BEST - data-* classes for styling, render props only for behavior\n// Note: use `data-[dragging]:*` syntax (v3-compatible), not `data-dragging:*` (v4 only)\nconst StyledContent = ({ children }) => (\n  <BaseComponent.Content\n    className={cn(\n      \"group rounded-xl border\",\n      \"data-[dragging]:border-dashed data-[dragging]:border-emerald-400\",\n    )}\n  >\n    {({ elicitation, resolveElicitation }) => (\n      <>\n        {/* Drop overlay uses group-data-* for styling */}\n        <div className=\"hidden group-data-[dragging]:flex absolute inset-0 bg-emerald-50/90\">\n          <p>Drop files here</p>\n        </div>\n\n        {elicitation ? (\n          <ElicitationUI\n            request={elicitation}\n            onResponse={resolveElicitation}\n          />\n        ) : (\n          children\n        )}\n      </>\n    )}\n  </BaseComponent.Content>\n);\n\n// OK - styled sub-components can use context hook for deep access\nconst StyledTextarea = ({ placeholder }) => {\n  const { value, setValue, handleSubmit, editorRef } = useMessageInputContext();\n  return (\n    <CustomEditor\n      ref={editorRef}\n      value={value}\n      onChange={setValue}\n      onSubmit={handleSubmit}\n      placeholder={placeholder}\n    />\n  );\n};\n```\n\n**When to use context hooks vs render props:**\n\n- Render props: when the parent wrapper needs state for behavior changes\n- Context hooks: when a styled sub-component needs values not exposed via render props\n\n### Step 5: Wrap Sub-Components\n\n```tsx\n// Submit button\nconst SubmitButton = ({ className, children }) => (\n  <BaseComponent.SubmitButton className={cn(\"w-10 h-10 rounded-lg\", className)}>\n    {({ showCancelButton }) =>\n      children ?? (showCancelButton ? <Square /> : <ArrowUp />)\n    }\n  </BaseComponent.SubmitButton>\n);\n\n// Error\nconst Error = ({ className }) => (\n  <BaseComponent.Error className={cn(\"text-sm text-destructive\", className)} />\n);\n\n// Staged images - base pre-computes props array, just iterate\nconst StagedImages = ({ className }) => (\n  <BaseComponent.StagedImages className={cn(\"flex gap-2\", className)}>\n    {({ images }) =>\n      images.map((imageProps) => (\n        <ImageBadge key={imageProps.image.id} {...imageProps} />\n      ))\n    }\n  </BaseComponent.StagedImages>\n);\n```\n\n### Step 6: Final Verification\n\n```\nFinal Checks:\n- [ ] No duplicate context creation\n- [ ] No duplicate SDK hooks in root wrappers\n- [ ] No duplicate state management or event handlers\n- [ ] Base namespace imported and `Base.Root` used as wrapper\n- [ ] `data-*` classes used for styling (with `group-data-*` for children)\n- [ ] Render props used only for rendering behavior changes\n- [ ] Base sub-components wrapped with styling\n- [ ] Icon factories passed from styled layer to base hooks\n- [ ] Visual sub-components and CSS variants stay in styled layer\n```\n\n## What Belongs in Styled Layer\n\n### Icon Factories\n\nWhen base hooks need icons, pass a factory function:\n\n```tsx\n// Base hook accepts optional icon factory\nexport function useCombinedResourceList(\n  providers: ResourceProvider[] | undefined,\n  search: string,\n  createMcpIcon?: (serverName: string) => React.ReactNode,\n) {\n  /* ... */\n}\n\n// Styled layer provides the factory\nconst resources = useCombinedResourceList(providers, search, (serverName) => (\n  <McpServerIcon name={serverName} className=\"w-4 h-4\" />\n));\n```\n\n### CSS Variants\n\n```tsx\nconst inputVariants = cva(\"w-full\", {\n  variants: {\n    variant: {\n      default: \"\",\n      solid: \"[&>div]:shadow-xl [&>div]:ring-1\",\n      bordered: \"[&>div]:border-2\",\n    },\n  },\n});\n```\n\n### Layout Logic, Visual Sub-Components, Custom Data Fetching\n\nThese all stay in the styled layer. Base handles behavior; styled handles presentation.\n\n## Type Handling\n\nHandle ref type differences between base and styled components:\n\n```tsx\n// Base context may have RefObject<T | null>\n// Styled component may need RefObject<T>\n<TextEditor ref={editorRef as React.RefObject<TamboEditor>} />\n```\n\n## Anti-Patterns\n\n- **Re-implementing base logic** - if base handles it, compose it\n- **Using render props for styling** - prefer `data-*` classes; render props are for behavior changes\n- **Duplicating context in wrapper** - use base Root which provides context\n- **Hardcoding icons in base hooks** - use factory functions to keep styling in styled layer\n\n<!-- File: .claude/skills/validating-accessibility/SKILL.md (Tokens: ~1184 | Category: anthropic-skill) -->\n---\nname: validating-accessibility\ndescription: >-\n  Use this skill when creating, modifying, or reviewing any .tsx component in apps/web, even if\n  the user doesn't mention \"accessibility.\" Covers semantic HTML, aria labels, navigation landmarks,\n  forms, dialogs, and keyboard navigation. Trigger on: adding buttons, links, toggles, icons, or\n  any interactive element; building or editing forms; adding dialogs or modals; reviewing UI code.\n  Includes inline verification patterns for scanning violations. Not for styling or layout changes\n  that don't involve interactive elements.\nmetadata:\n  internal: true\n---\n\n# Accessibility Checklist\n\nEvery UI component in `apps/web` must meet these standards. No partial compliance.\n\n## Gotchas\n\n- **`role=\"button\"` divs may exist in the codebase** -- fix them when touching affected files. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n- **Nested interactive elements** -- when replacing a `<div role=\"button\">` that contains a child `<button>` (e.g., a copy button inside a collapsible toggle), do not just swap the outer div to `<button>`. That creates invalid nested buttons. Instead, restructure into sibling elements: a toggle `<button>` and a separate action `<button>` side by side in a flex container.\n- **Standalone inputs outside react-hook-form need manual ID pairing** -- use `useId()` with `htmlFor`/`id`. The shadcn `<FormField>` handles this automatically, but raw `<Input>` does not.\n- **AlertDialog vs Dialog** -- use `AlertDialog` for destructive confirmations (requires `AlertDialogTitle` + `AlertDialogDescription`). Use `Dialog` for content/forms. Never build custom modal overlays.\n- **Icon-only buttons without `aria-label`** are common in new code. Every icon-only button needs one, and it must include context: `Delete API key ${keyName}`, not just \"Delete\".\n\n## Semantic HTML\n\nUse native elements. Never recreate `<button>` behavior with `<div role=\"button\">` + keyboard handlers.\n\n| Interaction      | Element                                                |\n| ---------------- | ------------------------------------------------------ |\n| Clickable action | `<button>` or `<Button>` from `@/components/ui/button` |\n| Navigation link  | `<Link>` (Next.js) or `<a>`                            |\n| Navigation group | `<nav>` with descriptive `aria-label`                  |\n| Item list        | `<ul>`/`<ol>` + `<li>`                                 |\n| Section heading  | `<h1>`-`<h6>` in order, never skip levels              |\n\n## Aria Labels\n\nEvery interactive element without visible text needs `aria-label` with both action AND target:\n\n```tsx\n<Button size=\"icon\" aria-label={`Delete API key ${keyName}`}>\n  <Trash2 className=\"h-4 w-4\" />\n</Button>\n\n<Switch aria-label={`${enabled ? \"Disable\" : \"Enable\"} skill ${skillName}`} />\n```\n\nPrefer state-aware labels (\"Copied!\" vs \"Copy\"). Buttons with visible text skip `aria-label`.\n\n**Reference implementations:** `copy-button.tsx` (state-aware), `context-attachment-badge.tsx` (contextual remove), `thread-table-header.tsx` (sort state) -- all in `apps/web/components/`.\n\n## Navigation Landmarks\n\nWrap navigation groups in `<nav>` with a unique `aria-label` per region on the page.\n\n## Forms\n\nUse shadcn Form components from `@/components/ui/form` (`FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormMessage`). They handle ID generation, label association, `aria-describedby`, and `aria-invalid` automatically.\n\nFor standalone inputs outside react-hook-form, pair `useId()` with `htmlFor`/`id`. Never use placeholder as label substitute.\n\n## Keyboard Navigation\n\n- Only `tabIndex={0}` or `tabIndex={-1}` (never positive values)\n- Never remove focus outlines\n- Prefer `<button>` over manual Enter/Space handlers\n\n## Verification\n\nScan `apps/web/components` for common violations. For each check, grep for the pattern and fix any matches found.\n\n### Check 1: `role=\"button\"` on non-button elements\n\nSearch for `role=\"button\"` in `.tsx` files. Flag `<div` or `<span` elements with this attribute; they should be `<button>` or `<Button>` instead. `<TableHead>` elements with `role=\"button\"` for sortable columns are acceptable.\n\n**Pattern:** `role=\"button\"`\n\n### Check 2: `<div onClick>` patterns\n\nSearch for `<div` elements with `onClick` handlers. These should use `<button>` instead for proper keyboard support.\n\n**Pattern:** `<div[^>]*onClick`\n\n### Check 3: Positive tabIndex values\n\nSearch for `tabIndex` with values greater than 0. Only `tabIndex={0}` and `tabIndex={-1}` are allowed.\n\n**Pattern:** `tabIndex={[1-9]`\n\n### Check 4: Icon buttons missing aria-label\n\nSearch for `size=\"icon\"` in `.tsx` files. For each match, check surrounding lines (5-10 above and below) for `aria-label` on the same `<Button>` element or an `sr-only` span. Flag buttons that have neither.\n\n**Pattern:** `size=\"icon\"` without nearby `aria-label`\n\n### Manual checks\n\nThese cannot be detected by pattern matching:\n\n- [ ] Form inputs have associated `<label>` elements\n- [ ] Navigation groups use `<nav>` with unique `aria-label`\n- [ ] Dialogs use Radix-based components (AlertDialog or Dialog)\n- [ ] Focus outlines intact\n\n<!-- File: docs/content/docs/reference/cli/commands/meta.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Commands Skill\n\nPath: `docs/content/docs/reference/cli/commands/meta.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/docs/content/docs/reference/cli/commands/meta.json)\n\n<!-- File: packages/backend/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Backend Skill\n\nPath: `packages/backend/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/package.json)\n\n<!-- File: packages/backend/tsconfig.build.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Backend Skill\n\nPath: `packages/backend/tsconfig.build.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.build.json)\n\n<!-- File: packages/backend/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Backend Skill\n\nPath: `packages/backend/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/backend/tsconfig.json)\n\n<!-- File: packages/client/AGENTS.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/AGENTS.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/AGENTS.md)\n\n<!-- File: packages/client/CHANGELOG.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/CHANGELOG.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CHANGELOG.md)\n\n<!-- File: packages/client/CLAUDE.md (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/CLAUDE.md`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/CLAUDE.md)\n\n<!-- File: packages/client/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/package.json)\n\n<!-- File: packages/client/tsconfig.cjs.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/tsconfig.cjs.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.cjs.json)\n\n<!-- File: packages/client/tsconfig.esm.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/tsconfig.esm.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.esm.json)\n\n<!-- File: packages/client/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Client Skill\n\nPath: `packages/client/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/client/tsconfig.json)\n\n<!-- File: packages/core/package.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Core Skill\n\nPath: `packages/core/package.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/package.json)\n\n<!-- File: packages/core/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Core Skill\n\nPath: `packages/core/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/core/tsconfig.json)\n\n<!-- File: packages/db/migrations/meta/_journal.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Meta Skill\n\nPath: `packages/db/migrations/meta/_journal.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/_journal.json)\n\n<!-- File: packages/db/migrations/meta/0000_snapshot.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Meta Skill\n\nPath: `packages/db/migrations/meta/0000_snapshot.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/tambo-ai/tambo/HEAD/packages/db/migrations/meta/0000_snapshot.json)\n\n<!-- ... +163 more modular skills available via /api/skills/tambo-ai/tambo?path={path} -->\n</yakaai_skills>"}