Skip to content

Getting started

This walkthrough takes you from a fresh checkout of Aero to a working extension sideloaded into the editor.

1. Install & run Aero

Aero is an Electron app. Clone it, install dependencies (the postinstall step rebuilds the native terminal module against Electron), then launch:

bash
git clone https://github.com/aeroide/aero
cd aero
npm install          # also rebuilds node-pty for Electron (postinstall)
npm start            # launch the editor
# npm run dev        # launch with DevTools detached

If the native terminal module fails to build, the editor still runs — the terminal just degrades gracefully. You don't need a terminal to author extensions.

Versions

The manifest's optional engines.aero field is a semver range checked against the running app version (e.g. ">=0.5.0"). Extensions install when the range matches. Check About Aero for your version.

2. Scaffold with aero-ext init

The aero-ext CLI scaffolds a ready-to-edit extension folder. Run it with npx (no global install needed):

bash
npx aero-ext init my-extension
cd my-extension

init asks for a publisher handle, machine name, display name, and which contribution types you want, then writes a starter tree:

my-extension/
├── aero.json            # manifest, pre-filled and schema-valid
├── themes/
│   └── my-theme.json    # if you chose themes
├── snippets/
│   └── javascript.json  # if you chose snippets
└── extension.js         # if you chose commands (sandboxed entry)

The generated aero.json already validates against aero-manifest.schema.json. Open it in Aero and edit away — see the manifest reference for every field.

Naming rules

name and publisher are kebab-case (^[a-z0-9][a-z0-9-]*$). Together they form your canonical id "<publisher>.<name>", which is globally unique in the marketplace and becomes the on-disk folder name.

3. Build the package

A .aero-ext file is just a ZIP with aero.json at its root. The CLI validates your manifest against the schema and zips the folder for you:

bash
npx aero-ext package
# → my-extension/aero-publisher.my-extension-1.0.0.aero-ext

package enforces the contract before it writes the archive:

  • aero.json must pass the JSON Schema.
  • Every path in contributes must be relative, forward-slash, and resolve inside the archive (no .., no absolute paths, no symlinks).
  • The archive must stay under 50 MB (the Storage bucket's hard limit).

4. Sideload it into Aero

To test before publishing, sideload the local .aero-ext. In the editor open the Extensions view in the activity rail and choose Install from file…, then pick your .aero-ext. Under the hood this calls the preload bridge:

api.ext.installLocal(aeroExtPath)  ->  { ok, id, version }

Aero unzips it into your home directory (never the workspace):

~/.aero/extensions/
├── installed.json
└── aero.my-extension/
    └── 1.0.0/            # your unpacked .aero-ext
        ├── aero.json
        └── themes/my-theme.json

The extension is enabled immediately. Declarative contributions (themes/snippets/keybindings) register from the manifest right away; command JS loads lazily on its activation event.

5. Try it

  • Theme: open the command palette and run your theme's apply command, or pick it from the theme list. Aero sets each --<token> CSS custom property on <html>, flips data-theme, and calls monaco.editor.setTheme(...).
  • Command: open the palette (Cmd/Ctrl+Shift+P) and search for your command title.
  • Keybinding: press your chord (e.g. cmd+k cmd+t).
  • Snippet: in a file of the target language, type your prefix and accept the completion.

6. Iterate

Edit files, re-package, and re-install. To manage installs, the Extensions view maps onto the preload surface:

ext.list()                  -> [{ id, version, enabled, manifest, dir, source }]
ext.setEnabled(id, enabled) -> { ok }     # enable/disable, no file changes
ext.uninstall(id)           -> { ok }     # removes the <id> folder + index entry

When you're happy, head to Publishing to push it to the marketplace.

Next steps

Lean, AI-ready, under your control.