Skip to content

Writing an extension

Extensions are ordinary folders — a package.json manifest and a src/ directory — and OpenRay builds them where they sit, so your checkout stays the only copy.

Create Extension

The quickest start is the Create Extension command in the launcher: name it, pick a template, and the folder is scaffolded, built, and already running — its command is in the launcher before the toast fades.

From a terminal, the same scaffold:

Terminal window
npx openray create my-extension # prompts for a template
cd my-extension && npm install
npm run dev # == openray develop

Both use the same templates (@openray/extension-template), named after Raycast’s:

Template What you get
Show List A static list with icons, subtitles, and accessories
Show Detail A single markdown view
Show List and Detail A list whose selection shows a detail pane
Show Typeahead Results A searchable list that loads results as you type
Submit Form Fields with a submit action
Show Grid A grid of items
Run Script Runs and shows a HUD, with no UI

Raycast’s AI template is deliberately absent, because that API is not implemented here and scaffolding it would hand you something that cannot run. There is no Menu Bar Extra template either, though that API itself does work.

openray develop asks the running app to build the folder and watch it. Its commands appear in the launcher immediately; every save rebuilds and hot-reloads whatever is on screen, and build errors stream to the terminal instead of vanishing into a log.

Settings → Add Extension → Choose Folder… does the same thing without a terminal.

The CLI never compiles anything itself — it drives the running app over a local socket. One build pipeline serves dev mode, installs, and packing, which is what keeps a dev build and a shipped build the same artifact. The socket is Unix only for now, so on Windows use the in-app folder picker; see the CLI reference for where the socket lives.

Write against @raycast/api (a dev dependency, for types only) or @openray/api. Both are mapped onto OpenRay’s own implementation at build time, and @openray/extras adds what Raycast has no equivalent for.

Because the API surface is Raycast-compatible, extensions from the raycast/extensions monorepo can be pointed at directly — see Installing extensions.