Extensions
Browse, install, develop, and publish Athas extensions
Athas extensions add language tooling, snippets, themes, icons, keymaps, databases, integrations, skills, and managed AI agents without making the core editor carry every integration by default.
Install and uninstall extensions from Settings > Extensions in Athas. The public Extensions catalog shows the same marketplace entries from the website.
How Extensions Work
Each Athas extension ships an extension.json manifest. Athas reads the manifest to register languages, snippets, themes, icons, databases, integrations, agents, commands, and managed tools. Integration extensions can also ship a constrained JavaScript entrypoint.
The preferred shape is close to VS Code's manifest model: stable editor contributions live under contributes, while managed runtime tools live under capabilities. Existing legacy fields such as iconThemes and databaseProviders are still supported for compatibility, but new extension manifests should use icons and databases.
Athas does not run arbitrary VS Code extension code. It can reuse and normalize declarative assets such as languages, snippets, themes, icons, and tool metadata, but full VS Code extension-host API compatibility is a separate problem.
Start Here
- Clone the Athas repository.
git clone https://github.com/athasdev/athas.git
cd athas- Create a folder under
extensions/official/for Athas-maintained extensions, orextensions/community/<publisher>/for community-maintained extensions.
extensions/
official/
my-language/
extension.json
community/
acme/
my-language/
extension.json- Add an
extension.jsonmanifest.
{
"$schema": "https://athas.dev/schemas/extension.json",
"id": "athas.my_language",
"name": "My Language",
"displayName": "My Language",
"version": "1.0.0",
"description": "Language tooling for My Language.",
"publisher": "Athas",
"engines": {
"athas": ">=0.7.0"
},
"categories": ["Language"],
"contributes": {
"languages": [
{
"id": "my_language",
"extensions": [".mylang"],
"filenames": ["MyLangfile"],
"filenamePatterns": ["*.mylang.json"],
"aliases": ["My Language"]
}
]
},
"activationEvents": ["onLanguage:my_language"]
}- Add tooling under
capabilitiesonly when the extension owns it.
{
"capabilities": {
"lsp": {
"name": "my-language-server",
"runtime": "node",
"package": "my-language-server",
"args": ["--stdio"]
},
"formatter": {
"name": "my-language-format",
"runtime": "node",
"package": "my-language-tools",
"args": ["format", "--stdin-filepath", "${file}"]
}
}
}Supported managed runtimes are bun, node, python, go, rust, and binary.
Manifest Fields
Use contributes for editor-visible declarations:
{
"contributes": {
"languages": [],
"snippets": [],
"themes": [],
"icons": [],
"databases": [],
"integrations": [],
"agents": [],
"commands": [],
"keybindings": []
}
}Language contributions can match by extension, exact filename, or filename pattern:
{
"id": "jsonc",
"extensions": [".jsonc"],
"filenames": ["tsconfig.json", "jsconfig.json"],
"filenamePatterns": ["tsconfig.*.json", "jsconfig.*.json"]
}Use capabilities for managed tools that Athas installs and launches:
lsp: language server launched over stdioformatter: formatter commandlinter: linter commandgrammar: parser and highlight-query asset metadata
For JavaScript or TypeScript language servers, declare companion packages in packages when the server expects them next to the primary package. Athas installs those packages into managed tool storage and resolves the launch path again when the tool starts.
Marketplace Flow
The marketplace is registry-driven:
- You add or edit an extension folder under
extensions/official/orextensions/community/in athasdev/athas. - You run the extension preparation scripts.
- The scripts stage generated CDN output under
extensions/generated/cdn/. - You open a pull request with the extension source and feature tooling changes. Generated CDN output is disposable and ignored.
- CI validates the manifests and catalog files.
- After merge, the deploy workflow syncs generated extension manifests, packages, and catalog files to
https://athas.dev/extensions. - Athas reads
https://athas.dev/extensions/manifests.jsonand shows the extension in Settings > Extensions. The website catalog readsindex.jsonand shows it on Extensions.
There is no separate marketplace admin step in Athas right now. If the extension is in the monorepo extension source folder, generated into the CDN catalog, merged, and deployed, it appears in the marketplace.
Local Validation
Run these commands from the Athas repository root:
bun run extensions:package:databases -- --build # only needed after database sidecar changes
bun run extensions:prepare
bun run extensions:validateCommit the extension source and script changes:
git add extensions src/features/extensions
git commit -m "Add My Language extension"If you are testing against a local Athas app checkout, serve the extension marketplace directory and point Athas at it:
bun run extensions:prepare
bunx serve extensions/generated/cdn -l 3001
VITE_PARSER_CDN_URL=http://localhost:3001 bun run dev
VITE_PARSER_CDN_URL=http://localhost:3001 ATHAS_EXTENSIONS_CDN_URL=http://localhost:3001 bun run tauri devThen open Athas and go to Settings > Extensions. Local changes should appear from your local server instead of the production marketplace.
Installation Behavior
Language extensions usually install the runtime tools declared in capabilities. For example, a Node LSP is installed into Athas-managed tool storage when the user clicks Install.
Theme, icon, and integration extensions are packaged by src/extensions/tooling/package-extensions.ts; the script writes installation.downloadUrl, size, and checksum into the manifest and creates a tarball under generated CDN output. The packaging script reads both top-level contributions and their matching contributes fields.
Agent extensions declare an agents contribution or contributes.agents. The contribution describes the ACP command Athas should detect, how to launch it, and optional managed installation metadata. The app reads those contributions from manifests.json; agent names and install commands should not be hardcoded in Athas.
SQLite is built into Athas because it is the default local-file database path. Other database
providers, such as DuckDB, PostgreSQL, MySQL, MongoDB, and Redis, are normal marketplace extensions:
their manifests declare databases or contributes.databases, their sidecar binaries are packaged under the
extensions CDN, and users install or uninstall them from Settings > Extensions.
Integration Extensions
Integration extensions are executable marketplace packages, but they do not run in the editor process and cannot import Athas application code. Their single-file main entrypoint runs in an isolated module worker with direct browser networking disabled. All access to Athas goes through the extension API and the permissions declared in the manifest.
{
"id": "acme.incidents",
"name": "incidents",
"displayName": "Acme Incidents",
"description": "Inspect active incidents from Athas.",
"version": "1.0.0",
"publisher": "Acme",
"categories": ["Integration"],
"integrations": [
{
"id": "incidents",
"name": "Acme Incidents",
"kind": "observability"
}
],
"main": "main.js",
"permissions": {
"network": ["https://api.acme.example"],
"secrets": true,
"workspace": "read",
"openExternal": true
}
}Available permissions are:
network: HTTP origins the extension may call throughapi.httpsecrets: access to secure storage scoped to the extension IDworkspace: "read": the current root, repository, active file path, and Git remotesopenExternal: permission to open an HTTP or HTTPS link in the default browser
The public API registers namespaced commands and sidebar views. Views return serializable UI nodes, so extensions reuse Athas buttons, inputs, badges, lists, loading states, and error states instead of bringing their own React components, HTML, styles, or scripts.
const viewId = "acme.incidents.overview";
export async function activate(api) {
let incidents = [];
api.commands.register({
id: "acme.incidents.refresh",
title: "Refresh incidents",
async run() {
const response = await api.http.request({
url: "https://api.acme.example/incidents",
});
incidents = JSON.parse(response.body);
api.views.invalidate(viewId);
},
});
api.sidebar.registerView({
id: viewId,
title: "Incidents",
icon: "warning-circle",
render: () =>
api.ui.screen(
{ title: "Incidents" },
api.ui.list(
...incidents.map((incident) =>
api.ui.listItem({
title: incident.title,
badges: [{ label: incident.status, tone: "warning" }],
}),
),
),
),
});
}Use extensions/sdk/athas-extension-api.d.ts for the API types. extensions/official/gitlab and extensions/official/sentry are complete reference packages. Bundle dependencies into main.js; relative imports are not available from an installed entrypoint.
Categories
Language: language registration, LSP, formatter, linter, snippetsAgent: ACP-compatible command-line coding agentsIntegration: external services with constrained commands and structured UITheme: editor color themesIcon Theme: file iconsSnippets: reusable snippetsKeymaps: keyboard shortcut presetsFormatter: standalone formatter contributionLinter: standalone linter contributionOther: everything else
Publishing
Open a pull request against athasdev/athas with your changes under extensions/ and src/features/extensions/ when tooling changes are needed. CI validates manifests and generated registry files. Once merged and deployed, the extension appears in the public Extensions catalog and inside Athas under Settings > Extensions.