This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Essential commands: (use npm, not yarn, for all package management and scripts)
npm install- Install dependencies (runstheia-patch,compute-references, and lernaafterInstallhooks)npm run build:browser- Builds all packages + bundles Browser example app (preferred during development)npm run compile- Compile TypeScript only (usestsc --buildwith project references)npm run lint- Run ESLint across all packagesnpm run lint:fix- Run ESLint with auto-fixnpm run test- Run all tests
Important: npm run compile only compiles TypeScript. Before UI testing, you must also run npm run build:browser to bundle the frontend — otherwise the running browser app won't include your latest changes. Bundling runs via theia build (in @theia/cli / application-manager), which defaults to esbuild when an esbuild.mjs config is present (as in the example apps) and falls back to webpack otherwise. The bundler choice is generated by BundlerGenerator in dev-packages/application-manager; esbuild.mjs / gen-esbuild.*.mjs vs webpack.config.js / gen-webpack.*.config.js files in each example app determine which is used.
Application commands:
npm run start:browser- Start browser example at localhost:3000npm run start:electron- Start electron applicationnpm run watch- Watch mode for development (browser + electron concurrently)
Package-specific:
npx lerna run compile --scope @theia/package-name- Build specific packagenpx lerna run test --scope @theia/package-name- Test specific packagenpx lerna run watch --scope @theia/package-name --include-filtered-dependencies --parallel- Watch package with dependencies
Running a single test file (after compile):
npx mocha ./packages/core/lib/browser/some-file.spec.js
Test infrastructure: Tests use Mocha + NYC (Istanbul) for coverage. Config at configs/mocharc.yml and configs/nyc.json. Each package's npm test runs via the theiaext test wrapper defined in dev-packages/private-ext-scripts, which executes nyc mocha --config ../../configs/mocharc.yml "./lib/**/*.*spec.js".
Monorepo Structure:
- Lerna-managed monorepo
/packages/- Runtime packages (core + extensions)/dev-packages/- Development tooling (application-manager, cli, eslint-plugin, ext-scripts)/examples/- Sample applications (browser, electron, browser-only, playwright)/configs/- Shared config files (tsconfig, eslint, mocha, nyc)
Platform-specific code organization (per package):
src/common/- Shared JavaScript APIs (runs everywhere)src/browser/- Browser/DOM APIs (InversifyJS DI container for frontend)src/node/- Node.js APIs (InversifyJS DI container for backend)src/electron-browser/- Electron renderer processsrc/electron-main/- Electron main process
Extension entry points are declared in each package's package.json under theiaExtensions:
"theiaExtensions": [{
"frontend": "lib/browser/editor-frontend-module",
"backend": "lib/node/editor-backend-module"
}]Extension System:
- Dependency Injection via InversifyJS (property injection preferred over constructor injection)
- Contribution Points pattern for extensibility (CommandContribution, MenuContribution, KeybindingContribution, FrontendApplicationContribution, etc.)
- Three extension types: Theia extensions (build-time), VS Code extensions (runtime), Theia plugins (runtime)
For more information also look at:
- @doc/coding-guidelines.md
- @doc/Testing.md
- @doc/Plugin-API.md (VS Code extension plugin API)
- @.prompts/project-info.prompttemplate (practical patterns for contributions, widgets, commands, preferences, plugin API, styling)
Read on demand (not auto-loaded) — consult when the task calls for it:
- doc/code-organization.md — platform import rules; consult when adding cross-platform imports.
- doc/vscode-usage.md — rules for exposing Monaco/VS Code internals from Theia packages.
- doc/api-management.md — API stability lifecycle.
- doc/api-testing.md — API integration testing (vs. unit tests in
Testing.md). - doc/pull-requests.md — PR / review checklist.
- doc/Developing.md — full build/setup details.
- doc/Migration.md — adopter-facing breaking-change notes.
- doc/runtime-policy.md / doc/Publishing.md — Node/Electron support and release process.
- doc/lockfile-maintenance.md — regenerating
package-lock.jsonacross the Node 22/24 CI matrix; consult before committing lockfile changes.
Code Style:
- 4 spaces indentation, single quotes,
undefinedovernull - PascalCase for types/enums, camelCase for functions/variables
- Arrow functions preferred, explicit return types required
- Property injection over constructor injection,
@postConstruct()for initialization
File Naming:
- kebab-case for files (e.g.,
document-provider.ts) - File name matches main exported type
- Platform folders follow strict dependency rules (browser cannot import node, etc.)
Architecture Patterns:
- Main-Ext pattern for plugin API (browser Main ↔ plugin host Ext, communicating via RPC)
- Services as classes with DI, avoid exported functions (functions can't be overridden)
ContributionProviderinstead of@multiInjectfor collecting multiple implementations- Use
bindRootContributionProvider(notbindContributionProvider) when binding contribution providers in top-level modules.bindContributionProviderretains a reference to whichever child container first resolves it, causing memory leaks. Only usebindContributionProviderwhen contributions are intentionally scoped to a child container (e.g. connection-scoped containers viaConnectionContainerModule). - URI strings for cross-platform file paths, never raw paths
- Localize user-facing strings with
nls.localize()ornls.localizeByDefault()
Testing:
- Unit tests:
*.spec.ts - UI tests:
*.ui-spec.ts - Slow tests:
*.slow-spec.ts - Test resources go in
test-resources/directory
- Node.js ≥22 (per
package.jsonengines) - TypeScript ~5.9.3 with strict settings (target ES2023, module CommonJS)
- React 18.2.0 for UI components
- Monaco Editor for code editing
Key Technologies:
- Express.js for backend HTTP server
- InversifyJS for dependency injection
- Lerna for monorepo management
- esbuild for application bundling (default, for performance); Webpack still supported as a legacy/opt-in bundler
- Lumino 2.x for widget system (tabs, panels, dock layout)
Key Config Files:
configs/base.tsconfig.json- TypeScript base config (all packages extend this)configs/base.eslintrc.json- ESLint parser/base rulesconfigs/build.eslintrc.json- ESLint build rules (packages extend this)configs/mocharc.yml- Mocha test runner configconfigs/nyc.json- Test coverage config
- Use Conventional Commits subjects, matching existing history:
type(scope): summary(e.g.fix(plugin-ext): ...,feat(ai-registry): ...,chore(deps): ...). - Use the templates in
.github/when opening issues or PRs. - Keep commit messages, PR descriptions, issues, and comments brief and concise — no padding, marketing language, or restating the diff.
- Security: never disclose vulnerabilities via a GitHub issue or PR — report them per
SECURITY.md. Such issues are deleted on sight.