Imported from AstralBeamAI/astralbeam (
AGENTS.md). Install upstream withnpx skills add AstralBeamAI/astralbeam. Copyright stays with the author.
AstralBeam development
- Use the product glossary consistently: an Organization is an AstralBeam customer (typically a SaaS app), organization users are that customer's employees who use the AstralBeam dashboard, Tenants are the Organization's customers, and tenant users (
TenantUser) are the Tenants' users who interact with the embedded agent sidebar. - Organizations have immutable UUIDs and editable slugs. Only the organization table may have a
slugcolumn. Use organization slugs only for URLs and their validation, never as identity in credentials, tokens, relationships, or seed lookups. Changing the slug breaks old URLs. - Other entities use opaque UUIDs. First-party organization-owned tables use
(organization_id, id)primary keys. Better Auth tables retain their adapter-compatible keys. Compose public agent IDs asagent_<organizationId>_<id>and API-key IDs askey_<organizationId>_<id>.
Tooling and validation
- Use Deno from the affected project directory (
webapp,www,sdk, orexamples/todos) withdeno task <script>, or from the repository root withdeno task --cwd <project> <script>. The projects do not form a package-manager workspace. Deno is the only supported repository JavaScript runtime and package manager. Vite and npm tooling run through its compatibility layer. SDK consumer examples may use the host application's package manager. - Keep every project's
check,test, andbuildtasks meaning the same thing, andreadymeaningcheck,test, andbuild.wwwalone runsbuildbeforetest, because its test reads the build output. - Compose reusable validation gates in the affected project's
checktask so local and CI checks stay aligned. Keep workflow additions limited to environment provisioning and checks that require a distinct execution environment. - Root
tsconfig.base.jsonholds only the compiler options all four projects share. Eachtsconfig.jsonextendsit and keeps its ownjsx,lib,types,paths, and file globs. - Keep the root
deno.jsonca launcher for the four projects, withformatandformat:checktasks and formatting configuration limited to files directly in the root. CI must run the rootformat:checktask. Do not add aworkspacefield, project-specific lint configuration, or root copies of per-project tasks such ascheck,test, andready. - Before non-trivial changes, inspect the current code, instructions, Git base and diff, generated artifacts, and installed APIs. Prefer supported upstream contracts, narrow diffs that preserve original names and code structure where semantics allow, and removing one-use helpers over custom plumbing or speculative abstraction.
- Ask before writing or changing code outside the user's explicitly requested scope. Research, planning, and instruction updates do not authorize implementation or resuming previously paused implementation.
- Before running
deno task knip:fix, commit or back up untracked work because it can delete unused files that Git cannot restore. Then inspect the complete project diff before runningdeno task check:fix. - Reserve Knip entries for actual execution or externally discovered roots, and add reusable modules only when code uses them. Do not hide speculative modules or accidental exports with entries. Keep
includeEntryExportsenabled in the three applications, whose entry exports must also be used in-project, and off insdk, whose entry-point exports are the published npm surface. - Run
scripts/setup.shonce after pulling to install the OS-level tooling and the projects' frozen dependencies. Otherwise, use the smallest relevant project task or syntax/configuration check. Documentation and instruction changes need only source review andgit diff --check. - Do not automatically run
deno task check,deno task test, ordeno task ready.readyalready runs checks, tests, and builds. Run it once before creating a PR or when explicitly requested, without separatecheckortestruns unless diagnosing a failure. - Run JavaScript and TypeScript tests with Vitest through the project's Deno task, never
Deno.testordeno test. Thewebappand todos browser suites use Playwright through their owne2etasks, which stay out ofcheck,test,ready, and CI. - When coding or reviewing, remove low-value or redundant tests and unnecessary fixtures/mocks. Keep tests that protect durable behavior, security boundaries, or observed regressions. Prefer short, direct tests and code over verbose setup or abstractions unless the extra complexity catches a distinct, worthwhile failure. Do not retain tests merely to restate implementation details, trivial constants, or generated structure.
- Before final validation, turn durable, non-obvious user corrections into one concise, nonduplicative instruction in the closest
AGENTS.mdor skill. Skip one-off decisions and preferences.
Documentation
- Keep SDK/API consumer docs focused on setup, usage, behavior, and troubleshooting. Keep implementation policy in
AGENTS.md, contributor setup inSETUP.md, and system rationale inARCHITECTURE.md. When shortening a README, preserve useful reference sections, options tables, examples, and workflows. Prune details already covered by a linked reference when they are not critical to everyday development. Keep essential setup, safety guidance, and useful quick references in the README, and retain important content absent from linked docs. Link to the owning explanation, but preserve copy-pasteable common commands in files that already listed them. Do not add new command sections elsewhere. Include the working directory or usedeno task --cwd <project> <task>. - Preserve existing
AGENTS.mdand skill instructions unless removal is explicit or resolves a documented conflict. - Name planning documents with the
*.plan.mdsuffix so they are distinguishable from durable documentation. - Keep plans and PR descriptions concise and evidence-backed. Plans must still include motivation, authoritative references, affected files and API anchors, validation, and boundaries.
- Keep each Markdown paragraph and list item on one source line, with blank lines before lists. Apply these rules to instruction files too. Preserve code syntax, exact quoted output, and third-party license text.
- Avoid semicolons and em dashes in documentation and Markdown prose. Use periods or commas instead.
- Write
/docsconsumer prose in the house voice, which the posts at swiftace.org model. Open by naming the subject and what we are about to do, never by describing the page. Use "let's" and "we" through a procedure and "you" for the reader's own state and consequences. Give every command a lead-in that names its purpose, state a reason cause first in the same sentence, number sequential steps, label asides**NOTE**:or**TIP**:, and keep tables for enumerable reference data rather than explanation. - Comment only non-obvious code or configuration decisions, including a link to authoritative documentation or an issue.
- Keep code comments to at most two lines. Longer reasoning belongs in the nearest
AGENTS.mdor a linked issue.
Environment
- Keep Webapp environment files under
webapp. Commit reviewed non-secret environment files such as.env,.env.development,.env.test, and.env.example. Ignore*.localfiles and never commit credentials or deployment-specific values. - Keep the webapp's bootstrap environment variables and optional deployment overrides documented in
webapp/AGENTS.md. Other runtime settings live in its databaseconfigtable and are managed at/configure. Keep standalone tool loading local to the tool configuration, with shell, CI, and deployment variables taking precedence over file values. - Give every local worktree its own PostgreSQL database named exactly after its unique worktree folder. In Codex's nested layout, use the directory immediately above the repository checkout (
a3f4for.../worktrees/a3f4/astralbeam), not the shared checkout basename.copy-worktree-env.shmust select, drop, and recreate that database with thedb-resettask beforesetup.shruns so every worktree starts fresh. Keepdb-resetlimited to recreating that database without migrations, and never recreate shared Compose volumes. - On macOS, run application code natively with Deno and use Docker Compose or Podman Compose for PostgreSQL, PgBouncer, Valkey, and Mailpit. Use a devcontainer only when explicitly requested. Never install host PostgreSQL or Valkey from
scripts/setup.sh. Keep PgBouncer as the only loopback-published PostgreSQL endpoint so local application and CLI traffic exercise transaction pooling. PreservePOSTGRES_HOSTandPOSTGRES_PORTas its backend overrides andPGBOUNCER_HOST_PORTas its host-published port override. Usedocker compose exec postgresonly for explicit direct database administration. Invokescripts/codex-db.shonly throughINSTALL_EXTRA=codex-dbin Codex Cloud's Ubuntu environment, paired withSKIP_DOCKER_COMPOSE=trueto prevent a Compose start.
Webapp and SDK UI
webappandsdkeach own acomponents.jsonand their own shadcn-generated components, hooks, and utilities underwebapp/src/components/ui,webapp/src/hooks, andwebapp/src/lib, or the corresponding SDK paths undersdk/src/widget. Neither imports the other's.- Add components from the owning project with
deno task ui add <component>. Bothcomponents.jsonfiles use the phosphor icon library, but their styles diverge on purpose: the webapp usesbase-lyra/mist, while the SDK stays on the plainb0preset baseline (base-nova/neutral). - At the top of each registry-added UI file, record the repeatable command as
// Added with: deno task ui add <component>and every intentional local change. Omit nonessential automation flags such as--overwriteand-yfrom the recorded command. - Let Knip remove unreachable registry UI files in both projects. Ignore generated export-level noise rather than excluding the directory from unused-file discovery.
- Use
@phosphor-icons/reactthroughout Webapp and SDK UI. Replace other icon-library imports in registry source during integration and do not addlucide-reactas a dependency. - Keep the hand-authored portions of
webapp/src/styles.csstheme-agnostic. Concrete palette values belong only in its marked generated section. The theme blocks insdk/src/styles.cssare the chat widget's own palette, deliberately independent of the webapp's. Edit them directly and do not resynchronize them withbrand.json.
Theme and brand
- Keep the semantic theme compiler design-time under
webapp/scripts/theme. It must stay a pure function of its input, without filesystem, HTTP, DOM, environment, or mutable global-state work, and nothing underwebapp/srcmay import it. - Treat
webapp/src/theme/brand.jsonas the concrete theme source of truth and regenerate the marked theme section ofwebapp/src/styles.cssfromwebappwithdeno task generate:themeafter changing it. - Email clients cannot read the stylesheet's OKLCH tokens, so
webapp/src/emails/email-theme.tsinlines static sRGB values. Refresh them from the palettedeno task generate:themeprints. - Keep
webapp/src/theme/theme.schema.json, the compiler's schemas, and the independently publishedwww/src/brand/theme.schema.jsonsnapshot synchronized through explicit edits. Neither project may import the other. - Keep SVG logo masters and their generated PNG variants under
webapp/publicand regenerate the PNGs fromwebappwithdeno task generate:pngafter SVG changes.
Database
- Keep PostgreSQL and Drizzle code under
webapp/src/db. Use the.server.tssuffix for server-only modules and never import the runtime client into browser code. - Keep domain table and relation modules under
webapp/src/db/schema, re-export every module Drizzle Kit must discover fromwebapp/src/db/schema.server.ts, and keep generated migrations underwebapp/src/db/migrations. - Run database commands from
webappwithdeno task db <command>. - After schema changes, run
generate --name <description>, inspect the SQL, runcheck, and commit schema and migration files together. - Use PostgreSQL
uuidprimary and foreign keys with database-generateduuidv7()defaults,citextfor email identity, andtimestamp with time zonewithout forced precision for application instants. PostgreSQL 18 is the minimum supported server version. - Define tables with
snakeCase.table, keep TypeScript property names camel case, and omit redundant column-name arguments when Drizzle can derive the lower snake-case SQL name. - Keep required extension DDL such as
CREATE EXTENSION IF NOT EXISTS citextin the generated migration because a DrizzlecustomTypedoes not install its PostgreSQL extension. Regenerate an unmerged, unapplied migration when refining the same schema change, but never rewrite migration history that may have been applied by others. - Follow the applicable PostgreSQL Don't Do This guidance: keep identifiers lower snake case, use half-open timestamp ranges and
NOT EXISTSwhere null-aware exclusion is needed, retain unconstrainedtext/citext, and avoidtimetz,CURRENT_TIME,char(n), defaultvarchar(n),money,serial, rules, table inheritance, and trust authentication over TCP/IP. - Use
migratefor checked-in migrations. Reservepush --explainfor local prototypes. Use the providedDATABASE_URLand never commit credentials or*.localenvironment files.
Cursor Cloud
- For UI changes, verify the affected flow through browser computer use and attach current screenshot or video evidence. Distinguish local checks from hosted or deployed proof.