Project-specific context for AI agents working on the Eclipse Theia code base.
Theia has a modular architecture and consists of so-called "Theia extensions", which are technically node packages. Most features and generally the source code can be found under "/packages/" which hosts a list of Theia extensions for different sorts of features. Theia applications can be used in the browser or (via Electron) on the desktop, but generally have a front end (browser application) and a backend part (node application). Therefore, extensions can contribute to the front end and the backend. This is reflected in the folder structure of extensions:
- src/browser: Frontend part of an extensions
- src/node: Backend part of an extension.
- src/common: Common/shared components, interfaces and protocol information for front end back end communication
Theia uses dependency injection (via inversify) to wired components. If a class is contributed via dependency injection it needs to be bound in the corresponding frontend or backend module (which usually already exists in existing packages)
Widgets are views that are visible in the workbench of a Theia-based application.
Commands in Theia are actions that can be executed by users and programmatically. They are registered through the CommandRegistry and can be triggered via menus,
keybindings, or other UI elements such as toolbar items.
Commands are contributed via CommandContribution, see for example: packages/ai-chat-ui/src/browser/chat-view-widget-toolbar-contribution.tsx
Toolbars in Theia are UI components that provide quick access to commonly used commands. They can be added to various parts of the workbench including the main toolbar, and custom widget toolbars.
Toolbars are typically contributed through:
TabBarToolbarContribution: For adding toolbar items to tab barsToolbarContribution: For contributing to main application toolbars
ToolbarContributions are located in separate files. Browse the following file for an example: packages/ai-chat-ui/src/browser/chat-view-widget-toolbar-contribution.tsx
- Trailing white spaces and empty lines with white spaces are forbidden
- Use constants for values that never get reassigned
- The use of
nullis forbidden. Useundefinedinstead for representing absent or uninitialized values. - Use single quotes (
') for string literals instead of double quotes ("). - Use Theia's Event/Emitter/Disposable for handling event listener patterns
- For localization, use
nls.localizeByDefault(defaultValue)when the string exists in VS Code's language packs. ESLint will flagnls.localizewith a custom key if a matching default string is available. Only usenls.localize('theia/<package>/<id>', 'text')for strings that do not exist in VS Code translations.
When binding a ContributionProvider, prefer bindRootContributionProvider over bindContributionProvider.
bindRootContributionProvidershould be used in most cases. It walks to the root Inversify container before constructing the provider, which avoids a memory leak where the provider permanently retains a reference to a child container. Use this whenever contributions are bound in the main (root) container, which is the typical case for module-levelContainerModulebindings.bindContributionProvidershould only be used when some or all of the relevant contributions are scoped to a child container rather than the root container, such as connection-scoped containers (e.g., insideConnectionContainerModule.create(...)).
Both functions are exported from @theia/core/lib/common/contribution-provider.
When writing new tests, refer to the following files to see example tests and ensure consistency in style and methodology within the project:
- Backend Test Example:
packages/core/src/common/content-replacer.spec.ts - Frontend Test Example:
packages/ai-code-completion/src/browser/code-completion-postprocessor.spec.ts
Tests are located in the same directory as the components under test.
Use npm (not yarn) for all package management and script execution.
If you want to compile something, run the linter or tests, prefer to execute them for changed packages first, as they will run faster. Only build the full project once you are done for a final validation. There are usually pre-defined tasks for all these operations, prefer to use these instead of npm directly.
Important: Building a package only compiles TypeScript. Before any UI testing, you must also rebuild the browser example application (examples/browser),
which bundles the frontend. Bundling runs via theia build, which uses esbuild and the generated esbuild.mjs config of the application. Without this step, the running browser app will not include the latest code changes.
To start Theia as a browser app to show something to the user or for UI testing use the launch config "Start Theia Default (Browser backend, no debug)"
Before running or testing the application UI, you must build the application:
- Browser application:
npm run build:browser - Electron application:
npm run build:electron
These commands bundle the frontend and must be run after any code changes before launching the application via debug configurations.
Theia uses a preferences system for user/workspace settings. To add new preferences:
- Define a
PreferenceSchemawith property definitions (type, default, description) - Create a
PreferenceContributionsymbol and bind it - Use
PreferenceProxyfor type-safe access to preference values
Example: packages/workspace/src/common/workspace-trust-preferences.ts
To extend the plugin API (VS Code compatible API):
- Type definitions: Add to
packages/plugin/src/theia.d.ts - Plugin-side implementation:
packages/plugin-ext/src/plugin/(e.g.,workspace.ts) - Main-side implementation:
packages/plugin-ext/src/main/browser/(e.g.,workspace-main.ts) - RPC protocol: Define in
packages/plugin-ext/src/common/plugin-api-rpc.ts - Expose to plugins:
packages/plugin-ext/src/plugin/plugin-context.ts
Events flow: Main side service → workspace-main.ts → RPC → workspace.ts → plugin context
For APIs that are not yet stable, Theia follows VS Code's proposed API pattern:
- Define proposed types: Create
packages/plugin/src/theia.proposed.<feature>.d.ts - Enable via package.json: Extensions must declare
enabledApiProposalsin their package.json - Implementation: Same as stable APIs, but types come from the proposed file
Note: Some VS Code APIs that were previously "proposed" are now stable (e.g., workspace trust). Check VS Code's current API status before creating proposed API files.
Theia permits extensive color theming and makes extensive use of CSS variables. Styles are typically located either in an index.css file for an entire package or in a
module-level CSS file.
- Color variable contribution example:
packages/core/src/browser/common-frontend-contribution.ts - Package-level CSS example:
packages/ai-ide/src/browser/style/index.css - Module-specific CSS example:
packages/core/src/browser/style/tabs.css
The FileService in browser mode communicates with the backend via RPC and has restricted filesystem access:
- Accessible paths: Files within the current workspace directory or the Theia user config directory (e.g.,
~/.theia/) - Inaccessible paths: Arbitrary filesystem paths outside these boundaries (e.g.,
/tmp/,/etc/)
When implementing browser-side services that need to read files from user-configured directories:
- Use
FileServicefrom@theia/filesystem/lib/browser/file-service - Convert paths to URIs using
URI.fromFilePath(path) - Expect
fileService.exists()to returnfalsefor paths outside allowed boundaries - Document that users should configure paths within their workspace or config directory
Reference implementation: packages/ai-core/src/browser/skill-service.ts and packages/ai-core/src/browser/frontend-prompt-customization-service.ts
Reviews of pull requests follow the pull request rules:
- Check the PR against the review checklist
- Do not report personal preferences or style questions, see no nitpicking
- Report issues outside the scope of the PR as follow-ups. They need no fix in the PR and do not block the AI approval.