This file provides guidance to Claude Code (claude.ai/code) and also Gemini CLI (https://github.com/google-gemini/gemini-cli) when working with code in this repository.
- This is the source code of CoCalc in a Git repository
- It is a complex JavaScript/TypeScript SaaS application
- CoCalc is organized as a monorepository (multi-packages) in the subdirectory "./src/packages"
- The packages are managed as a pnpm workspace in "./src/packages/pnpm-workspace.yaml"
- Everything is written in TypeScript code
- Indentation: 2-spaces
- Run
prettier -w [filename]after modifying a file (ts, tsx, md, json, ...) to format it correctly. - All .js and .ts files are formatted by the tool prettier
- Add suitable types when you write code
- Follow DRY principles!
- TypeScript: prefer
var1 ?? var2for fallbacks. only usevar1 || var2in explicit or-chains or when necessary. - Variable name styles are
camelCasefor local andFOO_BARfor global variables. React Components and Classes areFooBar. If you edit older code not following these guidelines, adjust this rule to fit the file's style. - Some older code is JavaScript or CoffeeScript, which will be translated to TypeScript
- Use ES modules (import/export) syntax, not CommonJS (require)
- Organize the list of imports in such a way: installed npm packages are on top, newline, then are imports from @cocalc's code base. Sorted alphabetically.
- Colors: Always use the
COLORSdictionary from@cocalc/util/themefor all color values. Never hardcode colors like#f0f0f0orrgb(...). Import withimport { COLORS } from "@cocalc/util/theme";and use predefined constants likeCOLORS.GRAY_M,COLORS.GRAY_L,COLORS.GRAY_LL, etc. - CSS/Styling: Prefer SASS files over inline React
<style>tags or style objects for reusable styles. The SASS entry point issrc/packages/frontend/index.sass, which@uses partial files (e.g.@use 'frame-editors/llm/_ai-assistant' as ai-assistant). Color variables from_colors.sassare available ascolors.$COL_.... Use CSS class names (e.g.className="cc-my-component") in components instead of inline style objects when the styles are non-trivial or conditional. - Backend Logging: Use
getLoggerfrom@cocalc/project/loggerfor logging in backend code. Do NOT useconsole.log. Example:const L = getLogger("module:name").debug;
All commands below assume you are in the src/ directory (i.e., cd src first).
- Install all dependencies:
python3 workspaces.py install - Build everything for development:
pnpm build-dev- This runs install, builds every package in dependency order, compiles i18n, and bundles the frontend with rspack.
- Typecheck frontend (after making changes):
cd packages/frontend && npx tsc --noEmit- This requires step 2 to have completed at least once so that dependency packages (e.g.,
@cocalc/util) have theirdist/output.
- This requires step 2 to have completed at least once so that dependency packages (e.g.,
If you only changed frontend code and dependencies are already built, you can skip the full pnpm build-dev and just run:
cd packages/frontend && npx tsc --noEmit
If you changed a dependency package like util, rebuild it first:
cd packages/util && pnpm build
cd ../frontend && npx tsc --noEmit
Key files:
src/workspaces.py— monorepo orchestration script (install, build, clean, test)src/packages/pnpm-workspace.yaml— pnpm workspace definitionsrc/packages/frontend/tsconfig.json— frontend TypeScript config
pnpm build-dev- Build all packages for development (run fromsrc/)pnpm clean- Clean allnode_modulesanddistdirectoriespnpm test- Run full test suitepnpm depcheck- Check for dependency issuespython3 ./src/scripts/check_npm_packages.py- Check npm package consistency across packagesprettier -w [filename]to format the style of a file after editing it- After creating a file, run
git add [filename]to start tracking it
cd src/packages/[package] && pnpm build- Build and compile a specific package- For src/packages/next and src/packages/static, run
cd src/packages/[package] && pnpm build-dev
- For src/packages/next and src/packages/static, run
cd src/packages/[package] && pnpm test- Run all tests for a specific packagecd src/packages/[package] && pnpm test -- [path/to/file.test.ts]- Run a single test file (preferred — faster than running the full suite)- IMPORTANT: When modifying packages like
utilthat other packages depend on, you must runpnpm buildin the modified package before typechecking dependent packages - IMPORTANT: When modifying colors in
src/packages/util/theme.ts, runcd src/packages/frontend && pnpm update-color-schemeto regenerate the SASS color variables insrc/packages/frontend/_colors.sass
The src/workspaces.py script orchestrates operations across all packages in the monorepo. Run it from the src/ directory (or use python3 src/workspaces.py from the repo root). Use it instead of running raw pnpm commands when working across the workspace:
python3 workspaces.py install- Install dependencies for all packages (use after updating package.json files)python3 workspaces.py build- Build all packages that have changedpython3 workspaces.py clean- Delete dist and node_modules folderspython3 workspaces.py version-check- Check dependency version consistency across all packagespython3 workspaces.py test- Run tests for all packages
IMPORTANT: After updating dependencies in any package.json, run python3 workspaces.py version-check to ensure consistency, then python3 workspaces.py install to update the lockfile and install.
- Language: All code, code comments, commit messages, PR descriptions, documentation, and UI strings are written in English (US). Maintainers sometimes speak another language in conversation, but the codebase itself is 100% US English.
- IMPORTANT: In tests and code comments, use only generic names, email addresses, and company names. Do not include customer or real-world identifiers, except for
Sagemath, Inc.or when the developer explicitly says otherwise.
After finishing a batch of code edits, you MUST run these steps automatically — do not wait for the user to ask.
Frontend code (src/packages/frontend):
prettier -w [each edited file]cd src/packages/frontend && pnpm tsc --noEmit— fix any errors before continuingcd src/packages/static && pnpm build-dev— compile for testing- DO NOT run
pnpm buildinsrc/packages/frontend— it won't work for frontend dev.
Other packages:
prettier -w [each edited file]cd src/packages/[package] && pnpm build— build the modified package- If the package is a dependency (e.g.
util), build it before typechecking dependents.
Special cases:
- After editing colors in
src/packages/util/theme.ts: runcd src/packages/frontend && pnpm update-color-scheme - After updating
package.jsondeps: runpython3 src/workspaces.py version-checkthenpython3 src/workspaces.py install
For detailed architecture documentation, see src/docs/:
- System Overview — High-level architecture and data flow
- Frontend — React app, state management, client layer
- Conat — Messaging system: DKV, PubSub, request/response
- Hub & Server — Central server, API dispatch, database
- Next.js — SSR pages, REST API routes, conat bridge
- External API — Python client, HTTP endpoints, call flow
- Project Daemon — Per-project services and conat integration
CoCalc is organized as a monorepo with key packages:
- frontend - React/TypeScript frontend application using Redux-style stores and actions
- backend - Node.js backend services and utilities
- hub - Main server orchestrating the entire system
- database - PostgreSQL database layer with queries and schema
- util - Shared utilities and types used across packages
- comm - Communication layer including WebSocket types
- conat - Distributed messaging system (NATS-like pub/sub, DKV, request/response)
- sync - Real-time synchronization system for collaborative editing
- project - Project-level services and management
- static - Static assets and build configuration
- server - Server-side service implementations (LLM, purchases, conat API handlers)
- ai - AI/LLM integration utilities
- jupyter - Jupyter notebook kernel and execution support
- terminal - Terminal emulation and pty management
- compute - Compute server orchestration (on-prem and cloud)
- next - Next.js server components
- Redux-style State Management: Uses custom stores and actions pattern (see
src/packages/frontend/app-framework/actions-and-stores.ts) - TypeScript React Components: All frontend code is TypeScript with proper typing
- Modular Store System: Each feature has its own store/actions (AccountStore, BillingStore, etc.)
- WebSocket Communication: Real-time communication with backend via WebSocket messages
- Authentication Waiting: When frontend code needs to wait for user authentication, use
redux.getStore("account").async_wait({ until: () => store.get_account_id() != null, timeout: 0 })to wait indefinitely until authentication completes - Conat DKV Usage: For key-value storage with real-time sync, use
webapp_client.conat_client.dkv({ account_id, name: "store-name" })to get a distributed key-value store that syncs across sessions
- PostgreSQL Database: Primary data store with sophisticated querying system
- WebSocket Messaging: Real-time communication between frontend and backend
- Conat System: Distributed messaging (pub/sub, DKV, request/response)
- Event-Driven Architecture: Extensive use of EventEmitter patterns
- Microservice-like Packages: Each package handles specific functionality
- Database Access: Use
getPool()from@cocalc/database/poolfor direct database queries in hub/backend code. Example:const pool = getPool(); const { rows } = await pool.query('SELECT * FROM table WHERE id = $1', [id]); - Hub Migration Functions: Migration functions in hub should be designed to run once at startup, use batch processing with delays between batches to avoid database saturation
- WebSocket Messages: Primary communication method (see
src/packages/comm/websocket/types.ts) - Database Queries: Structured query system with typed interfaces
- Event Emitters: Inter-service communication within backend
- REST-like APIs: Some HTTP endpoints for specific operations
- API Schema: API endpoints in
src/packages/next/pages/api/v2/use Zod schemas insrc/packages/next/lib/api/schema/for validation. These schemas must be kept in harmony with the TypeScript types sent from frontend applications usingapiPost(insrc/packages/next/lib/api/post.ts) orapi(insrc/packages/frontend/client/api.ts). When adding new fields to API requests, both the frontend types and the API schema validation must be updated. - Conat Messaging: Frontend-to-hub communication via conat pub/sub — see Conat docs for the full message flow, subjects, and API registration pattern.
- TypeScript: Primary language for all new code
- React: Frontend framework
- PostgreSQL: Database
- Node.js: Backend runtime
- WebSockets: Real-time communication
- pnpm: Package manager and workspace management
- Jest: Testing framework
- SASS: CSS preprocessing
- Comprehensive schema in
src/packages/util/db-schema - Query abstractions in
src/packages/database/postgres/ - Type-safe database operations with TypeScript interfaces
- Jest: Primary testing framework
- ts-jest: TypeScript support for Jest
- jsdom: Browser environment simulation for frontend tests
- Test files use
.test.tsor.spec.tsextensions - Each package has its own jest.config.js
- Playwright MCP: For interactive browser testing of the frontend UI, see
src/packages/frontend/test/agent-playwright-testing.md— covers the dev server setup, build-test loop, UI layout, and testing patterns for the file explorer and flyout panels. Always ask the developer for current dev account credentials.
- Use absolute imports with
@cocalc/prefix for cross-package imports - Example:
import { cmp } from "@cocalc/util/misc" - Type imports:
import type { Foo } from "./bar" - Destructure imports when possible
- Follow the Verification Steps in the Development Commands section above after every batch of edits.
- Database must be running before starting hub
- Hub coordinates all services and should be restarted after changes
- Use
pnpm clean && pnpm build-devwhen switching branches or after major changes
- Prefer running single tests, and not the whole test suite, for performance
- Never modify a file when in the
masterormainbranch - All changes happen through feature branches, which are pushed as pull requests to GitHub
- When creating a new file, run
git add [filename]to track the file. - Commit message format (MANDATORY): The first line of a commit message must follow the pattern:
[package]/[region]: [1-line description]. The package is the subdirectory undersrc/packages/and the region is the feature area within that package. Examples:frontend/explorer: fix directory tree performance,util/misc: add string search helper,database/postgres: optimize query caching. Do NOT use conventional-commits prefixes likefix:,feat:,perf:,chore:— always use thepackage/region:format instead. - When pushing a new branch to Github, track it upstream. e.g.
git push --set-upstream origin feature-foofor branch "feature-foo". - Branch naming: New branches should follow the pattern
[some-key-words]-[issue-number]. e.g.fix-invite-email-signup-link-8757for issue #8757.
CoCalc uses react-intl for internationalization with SimpleLocalize as the translation platform.
- Library: Uses
react-intllibrary withdefineMessages()anddefineMessage() - Default Language: English uses
defaultMessagedirectly - no separate English translation files - Supported Languages: 19+ languages including German, Chinese, Spanish, French, Italian, Dutch, Russian, Japanese, Portuguese, Korean, Polish, Turkish, Hebrew, Hindi, Hungarian, Arabic, and Basque
- Translation Platform: SimpleLocalize with OpenAI GPT-4o for automatic translations
Translation IDs follow a hierarchical pattern: [directory].[subdir].[filename].[aspect].[label|title|tooltip|...]
Examples:
labels.account- for common UI labelsaccount.sign-out.button.title- for account sign-out dialogcommand.generic.force_build.label- for command labels
- TSX Components:
<FormattedMessage id="..." defaultMessage="..." /> - Data Structures:
defineMessage({id: "...", defaultMessage: "..."}) - Programmatic Use:
useIntl()hook +intl.formatMessage() - Non-React Contexts:
getIntl()function
For new translation keys:
- Add the translation to source code (e.g.,
src/packages/frontend/i18n/common.ts) - Run
pnpm i18n:extract- updatesextracted.jsonfrom source code - Run
pnpm i18n:upload- sends new strings to SimpleLocalize - New keys are automatically translated to all languages
- Run
pnpm i18n:download- fetches translations - Run
pnpm i18n:compile- compiles translation files
For editing existing translation keys:
Same flow as above, but before 3. i18n:upload, delete the key. Only new keys are auto-translated. pnpm i18n:delete [id].
src/packages/frontend/i18n/README.md- detailed documentationsrc/packages/frontend/i18n/common.ts- shared translation definitions (labels, menus, editor, jupyter, etc.)src/packages/frontend/i18n/extracted.json- auto-extracted messages from source codesrc/packages/frontend/i18n/trans/[locale].json- downloaded translations from SimpleLocalizesrc/packages/frontend/i18n/trans/[locale].compiled.json- compiled translation files for runtimesrc/packages/frontend/i18n/index.ts- exports and locale loading logic
- Ignore files covered by
.gitignore - Ignore everything in
node_modulesordistdirectories - Ignore all files not tracked by Git, unless they are newly created files
For architecture and development details, see src/python/cocalc-api/.
- Do what has been asked; nothing more, nothing less.
- Prefer editing an existing file to creating a new one, unless a new file is the cleaner long-term fit or the feature is expected to grow.
- NEVER proactively create documentation files (*.md) or README files. Only create documentation files if explicitly requested by the User.
- ALWAYS ask questions if something is unclear. Only proceed to the implementation step if you have no questions left.
- When modifying a file with a copyright banner at the top, make sure to fix/add the current year to indicate the copyright year.