W↓
All docs
🔑
Sign Up/Sign In
developers.raycast.com/information/
Public Link
May 18, 2025, 5:12:26 AM - complete - 56.5 kB
Created by:
****ad@vlad.studio
Starting URLs:
https://developers.raycast.com/information/terminology
Crawl Prefixes:
https://developers.raycast.com/information/
## Page: https://developers.raycast.com/information/terminology 1. Information ## Terminology An explanation of various terms used in this documentation. Actions are accessible via the Action Panel in a command. They are little functionality to control something; for example, to add a label to the selected GitHub issue, copy the link to a Linear issue, or anything else. Actions can have assigned keyboard shortcuts. Action Panel is located on the bottom right and can be opened with `⌘` `K`. It contains all currently available actions and makes them easily discoverable. AI Extensions are simply regular extensions that have tools. Once an extension has some tools, a user can `@mention` the extension in Quick AI, or the AI Commands, or the AI Chat. When doing so, the AI will have the opportunity to call one or multiple tools of the extensions mentioned. Commands are a type of entry point for an extension. Commands are available in the root search of Raycast. They can be a simple script or lists, forms, and more complex UI. Extensions add functionality to Raycast. They consist of one or many commands and can be installed from the Store. Manifest is the `package.json` file of an extension. It's an npm package mixed with Raycast specific metadata. The latter is necessary to identify the package for Raycast and publish it to the Store. Tools are a type of entry point for an extension. As opposed to a command, they don’t show up in the root search and the user can’t directly interact with them. Instead, they are functionalities that the AI can use to interact with an extension. Last updated 2 months ago --- ## Page: https://developers.raycast.com/information/file-structure 1. Information ## File Structure Understand the file structure of an extension. An extension consists of at least an entry point file (e.g. `src/index.ts`) and a `package.json` manifest file. We add a few more support files when scaffolding an extension to streamline development with modern JavaScript tooling. The typical directory structure of a newly created extension looks like this: extension ├── .eslintrc.json ├── .prettierrc ├── assets │ └── icon.png ├── node_modules ├── package-lock.json ├── package.json ├── src │ ├── command.tsx └── tsconfig.json The directory contains all source files, assets, and a few support files. Let's go over each of them: Put all your source files into the `src` folder. We recommend using TypeScript as a programming language. Our API is fully typed, which helps you catch errors at compile time rather than runtime. `ts`, `tsx`, `js` and `jsx` are supported as file extensions. As a rule of thumb, use `tsx` or `jsx` for commands with a UI. An extension consists of at least an entry point file (e.g. `src/command.ts`) per command and a `package.json` manifest file holding metadata about the extension, its commands, and its tools. The format of the manifest file is very similar to that of npm packages. In addition to some of the standard properties, there are some additional properties, in particular, the `commands` properties which describes the entry points exposed by the extension. Each command has a property `name` that maps to its main entry point file in the `src` folder. For example, a command with the name `create` in the `package.json` file, maps to the file `src/create{.ts,.tsx,.js,.jsx}`. The optional `assets` folder can contain icons that will be packaged into the extension archive. All bundled assets can be referenced at runtime. Additionally, icons can be used in the `package.json` as extension or command icons. The directory contains a few more files that setup common JavaScript tooling: * **eslint.config.js** describes rules for ESLint, which you can run with `npm run lint`. It has recommendations for code style and best practices. Usually, you don't have to edit this file. * **.prettierrc** contains default rules for Prettier to format your code. We recommend to setup the VS Code extension to keep your code pretty automatically. * **node\_modules** contains all installed dependencies. You shouldn't make any manual changes to this folder. * **package-lock.json** is a file generated by npm to install your dependencies. You shouldn't make any manual changes to this file. * **package.json** is the manifest file containing metadata about your extension such as its title, the commands, and its dependencies. * **tsconfig.json** configures your project to use TypeScript. Most likely, you don't have to edit this file. Last updated 1 month ago --- ## Page: https://developers.raycast.com/information/manifest 1. Information ## Manifest The `package.json` manifest file is a superset of npm's `package.json` file. This way, you only need one file to configure your extension. This document covers only the Raycast specific fields. Refer to npm's documentation for everything else. Here is a typical manifest file: { "name": "my-extension", "title": "My Extension", "description": "My extension that can do a lot of things", "icon": "icon.png", "author": "thomas", "categories": ["Fun", "Communication"], "license": "MIT", "commands": [ { "name": "index", "title": "Send Love", "description": "A command to send love to each other", "mode": "view" } ] } All Raycast related properties for an extension. name\* A unique name for the extension. This is used in the Store link to your extension, so keep it short and URL compatible. title\* The title of the extension that is shown to the user in the Store as well as the preferences. Use this title to describe your extension well that users can find it in the Store. description\* The full description of the extension shown in the Store. icon\* A reference to an icon file in the assets folder. Use png format with a size of 512 x 512 pixels. To support light and dark theme, add two icons, one with `@dark` as suffix, e.g. `icon.png` and `[email protected]`. author \* Your Raycast Store handle (username) categories\* An array of categories that your extension belongs in. commands\* tools An array of tools that the AI can use to interact with this extension, see Tool properties. ai Additional information related to the AI capabilities of the extension, see AI properties. owner Used for extensions published under an organisation. When defined, the extension will be private (except when specifying `access`). access Either `"public"` or `"private"`. Public extensions are downloadable by anybody, while private extensions can only be downloaded by a member of a given organization. contributors An array of Raycast store handles (usernames) of people who have meaningfully contributed and are maintaining to this extension. pastContributors An array of Raycast store handles (usernames) of people who have meaningfully contributed to the extension's commands but do not maintain it anymore. keywords An array of keywords for which the extension can be searched for in the Store. preferences Extensions can contribute preferences that are shown in Raycast Preferences > Extensions. You can use preferences for configuration values and passwords or personal access tokens, see Preference properties. external An Array of package or file names that should be excluded from the build. The package will not be bundled, but the import is preserved and will be evaluated at runtime. All properties for a command. name\* A unique id for the command. The name directly maps to the entry point file for the command. So a command named "index" would map to `src/index.ts` (or any other supported TypeScript or JavaScript file extension such as `.tsx`, `.js`, `.jsx`). title\* The display name of the command, shown to the user in the Store, Preferences, and in Raycast's root search. subtitle The optional subtitle of the command in the root search. Usually, this is the service or domain that your command is associated with. You can dynamically update this property using `updateCommandMetadata`. description\* It helps users understand what the command does. It will be displayed in the Store and in Preferences. icon An optional reference to an icon file in the assets folder. Use png format with a size of at least 512 x 512 pixels. To support light and dark theme, add two icons, one with `@dark` as suffix, e.g. `icon.png` and `[email protected]`. If no icon is specified, the extension icon will be used. mode\* A value of `view` indicates that the command will show a main view when performed. `no-view` means that the command does not push a view to the main navigation stack in Raycast. The latter is handy for directly opening a URL or other API functionalities that don't require a user interface. `menu-bar` indicates that this command will return a Menu Bar Extra interval The value specifies that a `no-view` or `menu-bar` command should be launched in the background every X seconds (s), minutes (m), hours (h) or days (d). Examples: 90s, 1m, 12h, 1d. The minimum value is 1 minute (1m). keywords An optional array of keywords for which the command can be searched in Raycast. arguments An optional array of arguments that are requested from user when the command is called, see Argument properties. preferences Commands can optionally contribute preferences that are shown in Raycast Preferences > Extensions when selecting the command. You can use preferences for configuration values and passwords or personal access tokens, see Preference properties. Commands automatically "inherit" extension preferences and can also override entries with the same `name`. disabledByDefault Specify whether the command should be enabled by default or not. By default, all commands are enabled but there are some cases where you might want to include additional commands and let the user enable them if they need it. _Note that this flag is only used when installing a new extension or when there is a new command._ All properties for extension or command-specific preferences. Use the Preferences API to access their values. name\* A unique id for the preference. title\* The display name of the preference shown in Raycast preferences. For `"checkbox"`, `"textfield"` and `"password"`, it is shown as a section title above the respective input element. If you want to group multiple checkboxes into a single section, set the `title` of the first checkbox and leave the `title` of the other checkboxes empty. description\* It helps users understand what the preference does. It will be displayed as a tooltip when hovering over it. type\* The preference type. We currently support `"textfield"` and `"password"` (for secure entry), `"checkbox"`, `"dropdown"`, `"appPicker"`, `"file"`, and `"directory"`. required\* Indicates whether the value is required and must be entered by the user before the extension is usable. placeholder Text displayed in the preference's field when no value has been input. default The optional default value for the field. For textfields, this is a string value; for checkboxes a boolean; for dropdowns the value of an object in the data array; for appPickers an application name, bundle ID or path. Depending on the `type` of the Preference, some additional properties can be required: label\* The label of the checkbox. Shown next to the checkbox. data\* An array of objects with `title` and `value` properties, e.g.: `[{"title": "Item 1", "value": "1"}]` All properties for command arguments. Use the Arguments API to access their values. name\* A unique id for the argument. This value will be used to as the key in the object passed as top-level prop. type\* The argument type. We currently support `"text"`, `"password"` (for secure entry), and `"dropdown"`. When the type is `password`, entered text will be replaced with asterisks. Most common use case – passing passwords or secrets to commands. placeholder\* Placeholder for the argument's input field. required Indicates whether the value is required and must be entered by the user before the command is opened. Default value for this is `false`. Depending on the `type` of the Argument, some additional properties can be required: data\* An array of objects with `title` and `value` properties, e.g.: `[{"title": "Item 1", "value": "1"}]` All properties for a tool. name\* A unique id for the tool. The name directly maps to the entry point file for the tool. So a tool named "index" would map to `src/tools/index.ts` (or any other supported TypeScript file extension such as `.tsx`). title\* The display name of the tool, shown to the user in the Store and Preferences. description\* It helps users and the AI understand what the tool does. It will be displayed in the Store and in Preferences. icon An optional reference to an icon file in the assets folder. Use png format with a size of at least 512 x 512 pixels. To support light and dark theme, add two icons, one with `@dark` as suffix, e.g. `icon.png` and `[email protected]`. If no icon is specified, the extension icon will be used. All properties for the AI capabilities of the extension. Alternatively, this object can be written in a `ai.json` (or `ai.yaml`) file at the root of the extension. instructions A string containing additional instructions for the AI. It will be added as a system message whenever the extension is mentioned. It can for example be used to help the AI respond with a format that makes more sense for the extension: `Always format pull requests and issues as markdown links: [pull-request-title](https://github.com/:org/:repo/pull/:number) and [issue-title](https://github.com/:org/:repo/issues/:number)` evals Last updated 1 month ago --- ## Page: https://developers.raycast.com/information/lifecycle 1. Information ## Lifecycle A command is typically launched, runs for a while, and then is unloaded. When a command is launched in Raycast, the command code is executed right away. If the extension exports a default function, this function will automatically be called. If you return a React component in the exported default function, it will automatically be rendered as the root component. For commands that don't need a user interface (`mode` property set to "`no-view"` in the manifest), you can export an async function and perform API methods using async/await. import { Detail } from "@raycast/api"; // Returns the main React component for a view command export default function Command() { return <Detail markdown="# Hello" />; } import { showHUD } from "@raycast/api"; // Runs async. code in a no-view command export default async function Command() { await showHUD("Hello"); } There are different ways to launch a command: * The user searches for the command in the root search and executes it. * The user registers an alias for the command and presses it. * A user registers the command as a fallback command and executes it when there are no results in the root search. Depending on how the command was launched, different arguments will be passed to the exported default function. import { Detail, LaunchProps } from "@raycast/api"; // Access the different launch properties via the argument passed to the function export default function Command(props: LaunchProps) { return <Detail markdown={props.fallbackText || "# Hello"} />; } arguments\* Use these values to populate the initial state for your command. launchType\* The type of launch for the command (user initiated or background). draftValues When a user enters the command via a draft, this object will contain the user inputs that were saved as a draft. Use its values to populate the initial state for your Form. fallbackText When the command is launched as a fallback command, this string contains the text of the root search. `string` launchContext When the command is launched programmatically via `launchCommand`, this object contains the value passed to `context`. When the command is unloaded (typically by popping back to root search for view commands or after the script finishes for no-view commands), Raycast unloads the entire command from memory. Note that there are memory limits for commands, and if those limits are exceeded, the command gets terminated, and users will see an error message. Last updated 1 month ago --- ## Page: https://developers.raycast.com/information/lifecycle/arguments 1. Information 3. Lifecycle ## Arguments Raycast supports arguments for your commands so that users can enter values right from Root Search before opening the command.  Arguments are configured in the manifest per command. * **Maximum number of arguments:** 3 (if you have a use case that requires more, please let us know via feedback or in the Slack community) * The order of the arguments specified in the manifest is important and is reflected by the fields shown in Root Search. To provide a better UX, put the required arguments before the optional ones. Let's say we want a command with three arguments. Its `package.json` will look like this: { "name": "arguments", "title": "API Arguments", "description": "Example of Arguments usage in the API", "icon": "command-icon.png", "author": "raycast", "license": "MIT", "commands": [ { "name": "my-command", "title": "Arguments", "subtitle": "API Examples", "description": "Demonstrates usage of arguments", "mode": "view", "arguments": [ { "name": "title", "placeholder": "Title", "type": "text", "required": true }, { "name": "subtitle", "placeholder": "Secret Subtitle", "type": "password" }, { "name": "favoriteColor", "type": "dropdown", "placeholder": "Favorite Color", "required": true, "data": [ { "title": "Red", "value": "red" }, { "title": "Green", "value": "green" }, { "title": "Blue", "value": "blue" } ] } ] } ], "dependencies": { "@raycast/api": "1.38.0" }, "scripts": { "dev": "ray develop", "build": "ray build -e dist", "lint": "ray lint" } } The command itself will receive the arguments' values via the `arguments` prop: import { Form, LaunchProps } from "@raycast/api"; export default function Todoist(props: LaunchProps<{ arguments: Arguments.MyCommand }>) { const { title, subtitle } = props.arguments; console.log(`title: ${title}, subtitle: ${subtitle}`); return ( <Form> <Form.TextField id="title" title="Title" defaultValue={title} /> <Form.TextField id="subtitle" title="Subtitle" defaultValue={subtitle} /> </Form> ); } A command receives the values of its arguments via a top-level prop named `arguments`. It is an object with the arguments' `name` as keys and their values as the property's values. Depending on the `type` of the argument, the type of its value will be different. `text` `string` `password` `string` `dropdown` `string` Raycast provides a global TypeScript namespace called `Arguments` which contains the types of the arguments of all the commands of the extension. For example, if a command named `show-todos` accepts arguments, its `LaunchProps` can be described as `LaunchProps<{ arguments: Arguments.ShowTodos }>`. This will make sure that the types used in the command stay in sync with the manifest. Last updated 8 months ago --- ## Page: https://developers.raycast.com/information/lifecycle/background-refresh 1. Information 3. Lifecycle ## Background Refresh Commands of an extension can be configured to be automatically run in the background, without the user manually opening them. Background refresh can be useful for: * dynamically updating the subtitle of a command in Raycast root search * refreshing menu bar commands * other supporting functionality for your main commands This guide helps you understand when and how to use background refresh and learn about the constraints. Raycast supports scheduling commands with mode `no-view` and `menu-bar` at a configured interval. Add a new property `interval` to a command in the manifest Example: { "name": "unread-notifications", "title": "Show Unread Notifications", "description": "Shows the number of unread notifications in root search", "mode": "no-view", "interval": "10m" }, The interval specifies that the command should be launched in the background every X seconds (s), minutes (m), hours (h) or days (d). Examples: `10m`, `12h`, `1d`. The minimum value is 10 seconds (`10s`), which should be used cautiously, also see the section on best practices. Note that the actual scheduling is not exact and might vary within a tolerance level. macOS determines the best time for running the command in order to optimize energy consumption, and scheduling times can also vary when running on battery. To prevent overlapping background launches of the same command, commands are terminated after a timeout that is dynamically adjusted to the interval. The entry point of your command stays the same when launched from the background. For no-view commands, a command will run until the Promise of the main async function resolves. Menu bar commands render a React component and run until the `isLoading` property is set to `false`. You can use the global `environment.launchType` in your command to determine whether the command has been launched by the user (`LaunchType.UserInitiated`) or via background refresh (`LaunchType.Background`). import { environment, updateCommandMetadata } from "@raycast/api"; async function fetchUnreadNotificationCount() { return 10; } export default async function Command() { console.log("launchType", environment.launchType); const count = await fetchUnreadNotificationCount(); await updateCommandMetadata({ subtitle: `Unread Notifications: ${count}` }); } Raycast auto-terminates the command if it exceeds its maximum execution time. If your command saves some state that is shared with other commands, make sure to use defensive programming, i.e. add handling for errors and data races if the stored state is incomplete or inaccessible. For local commands under development, errors are shown as usual via the console. Two developer actions in root search help you to run and debug scheduled commands: * Run in Background: this immediately runs the command with `environment.launchType` set to `LaunchType.Background`. * Show Error: if the command could not be loaded or an uncaught runtime exception was thrown, the full error can be shown in the Raycast error overlay for development. This action is also shown to users of the installed Store command and provides actions to copy and report the error on the production error overlay.  When the background run leads to an error, users will also see a warning icon on the root search command and a tooltip with a hint to show the error via the Action Panel. The tooltip over the subtitle of a command shows the last run time. You can launch the built-in root search command "Extension Diagnostics" to see which of your commands run in background and when they last ran. For scheduled commands, Raycast automatically adds command preferences that give users the options to enable and disable background refresh. Preferences also show the last run time of the command.  When a user installs the command via the Store, background refresh is initially _disabled_ and is activated either when the user opens the command for the first time or enables background refresh in preferences. (This is to avoid automatically running commands in the background without the user being aware of it.) * Make sure the command is useful both when manually launched by the user or when launched in the background * Choose the interval value as high as possible - low values mean the command will run more often and consume more energy * If your command performs network requests, check the rate limits of the service and handle errors appropriately (e.g. automatically retry later) * Make sure the command finishes as quickly as possible; for menu bar commands, ensure `isLoading` is set to false as early as possible * Use defensive programming if state is shared between commands of an extension and handle potential data races and inaccessible data Last updated 9 months ago --- ## Page: https://developers.raycast.com/information/lifecycle/deeplinks 1. Information 3. Lifecycle ## Deeplinks Deeplinks are Raycast-specific URLs you can use to launch any command, as long as it's installed and enabled in Raycast. They adhere to the following format: raycast://extensions/<author-or-owner>/<extension-name>/<command-name> author-or-owner For store extensions, it's the value of the `owner` or the `author` field in the extension's manifest. For built-in extensions (such as `Calendar`), this is always `raycast`. `string` extension-name For store extensions, it's the value of the extension's `name` field in the extension's manifest. For built-in extensions (such as `Calendar`), this is the "slugified" extension name; in this case `calendar`. `string` command-name For store extensions, it's the value of the command's `name` field in the extension's manifest. For built-in commands (such as `My Schedule`), this is the "slugified" command name; in this case `my-schedule`. `string` To make fetching a command's Deeplink easier, each command in the Raycast root now has a `Copy Deeplink` action. Whenever a command is launched using a Deeplink, Raycast will ask you to confirm that you want to run the command. This is to ensure that you are aware of the command you are running.  launchType Runs the command in the background, skipping bringing Raycast to the front. Either `userInitiated` or `background` arguments If the command accepts arguments, they can be passed using this query parameter. URL-encoded JSON object. context If the command make use of LaunchContext, it can be passed using this query parameter. URL-encoded JSON object. fallbackText Some text to prefill the search bar or first text input of the command `string` Last updated 8 months ago --- ## Page: https://developers.raycast.com/information/best-practices 1. Information ## Best Practices Tips to guarantee a good user experience for your extensions. Network requests can fail, permissions to files can be missing… More generally, errors happen. By default, we handle every unhandled exception or unresolved Promise and show error screens. However, you should handle the "expected" error cases for your command. You should aim not to disrupt the user's flow just because something went wrong. For example, if a network request fails but you can read the cache, show the cache. A user might not need the fresh data straight away. In most cases, it's best to show a `Toast` with information about the error. Here is an example of how to show a toast for an error: import { Detail, showToast, Toast } from "@raycast/api"; import { useEffect, useState } from "react"; export default function Command() { const [error, setError] = useState<Error>(); useEffect(() => { setTimeout(() => { setError(new Error("Booom 💥")); }, 1000); }, []); useEffect(() => { if (error) { showToast({ style: Toast.Style.Failure, title: "Something went wrong", message: error.message, }); } }, [error]); return <Detail markdown="Example for proper error handling" />; } Ideally, your extension doesn't depend on any runtime dependencies. In reality, sometimes locally installed apps or CLIs are required to perform functionality. Here are a few tips to guarantee a good user experience: * If a command requires a runtime dependency to run (e.g. an app that needs to be installed by the user), show a helpful message. * If your extension is tightly coupled to an app, f.e. searching tabs in Safari or using AppleScript to control Spotify, checks don't always have to be strict because users most likely don't install the extension without having the dependency installed locally. * If only some functionality of your extension requires the runtime dependency, consider making this functionality only available if the dependency is installed. Typically, this is the best case for actions, e.g. to open a URL in the desktop app instead of the browser. When commands need to load big data sets, it's best to inform the user about this. To keep your command snappy, it's important to render a React component as quickly as possible. You can start with an empty list or a static form and then load the data to fill the view. To make the user aware of the loading process, you can use the `isLoading` prop on all top-level components, e.g. `<Detail>`, `<Form>`, `<Grid>`, or `<List>`. Here is an example to show the loading indicator in a list: import { List } from "@raycast/api"; import { useEffect, useState } from "react"; export default function Command() { const [items, setItems] = useState<string[]>(); useEffect(() => { setTimeout(() => { setItems(["Item 1", "Item 2", "Item 3"]); }, 1000); }, []); return ( <List isLoading={items === undefined}> {items?.map((item, index) => ( <List.Item key={index} title={item} /> ))} </List> ); } * * * Before submitting data, it is important to ensure all required form controls are filled out, in the correct format. In Raycast, validation can be fully controlled from the API. To keep the same behavior as we have natively, the proper way of usage is to validate a `value` in the `onBlur` callback, update the `error` of the item and keep track of updates with the `onChange` callback to drop the `error` value. The useForm utils hook nicely wraps this behaviour and is the recommended way to do deal with validations.  Keep in mind that if the Form has any errors, the `Action.SubmitForm` `onSubmit` callback won't be triggered. import { Action, ActionPanel, Form, showToast, Toast } from "@raycast/api"; import { useForm, FormValidation } from "@raycast/utils"; interface SignUpFormValues { name: string; password: string; } export default function Command() { const { handleSubmit, itemProps } = useForm<SignUpFormValues>({ onSubmit(values) { showToast({ style: Toast.Style.Success, title: "Yay!", message: `${values.name} account created`, }); }, validation: { name: FormValidation.Required, password: (value) => { if (value && value.length < 8) { return "Password must be at least 8 symbols"; } else if (!value) { return "The item is required"; } }, }, }); return ( <Form actions={ <ActionPanel> <Action.SubmitForm title="Submit" onSubmit={handleSubmit} /> </ActionPanel> } > <Form.TextField title="Full Name" placeholder="Tim Cook" {...itemProps.name} /> <Form.PasswordField title="New Password" {...itemProps.password} /> </Form> ); } import { Form } from "@raycast/api"; import { useState } from "react"; export default function Command() { const [nameError, setNameError] = useState<string | undefined>(); const [passwordError, setPasswordError] = useState<string | undefined>(); function dropNameErrorIfNeeded() { if (nameError && nameError.length > 0) { setNameError(undefined); } } function dropPasswordErrorIfNeeded() { if (passwordError && passwordError.length > 0) { setPasswordError(undefined); } } return ( <Form> <Form.TextField id="nameField" title="Full Name" placeholder="Tim Cook" error={nameError} onChange={dropNameErrorIfNeeded} onBlur={(event) => { if (event.target.value?.length == 0) { setNameError("The field should't be empty!"); } else { dropNameErrorIfNeeded(); } }} /> <Form.PasswordField id="password" title="New Password" error={passwordError} onChange={dropPasswordErrorIfNeeded} onBlur={(event) => { const value = event.target.value; if (value && value.length > 0) { if (!validatePassword(value)) { setPasswordError("Password should be at least 8 characters!"); } else { dropPasswordErrorIfNeeded(); } } else { setPasswordError("The field should't be empty!"); } }} /> <Form.TextArea id="bioTextArea" title="Add Bio" placeholder="Describe who you are" /> <Form.DatePicker id="birthDate" title="Date of Birth" /> </Form> ); } function validatePassword(value: string): boolean { return value.length >= 8; } Last updated 9 months ago --- ## Page: https://developers.raycast.com/information/developer-tools  GitHub 1. Information ## Developer Tools Raycast provides several tools to smoothen your experience when building extensions: * `Manage Extensions` Command _\- A Raycast command to manage your extensions, add new command, etc._ * CLI _\- A CLI to build, develop, and lint your extension_ * ESLint _\- An ESLint configuration helping you follow best practices as you build your extension_ * VS Code (community tool) _\- A VS Code extension to enhance your development experience_ PreviousBest PracticesNextManage Extensions Command Last updated 8 months ago --- ## Page: https://developers.raycast.com/information/developer-tools/manage-extensions-command  GitHub 1. Information 3. Developer Tools ## Manage Extensions Command A Raycast command to manage your extensions, add new commands or attachments, etc. Raycast provides a built-in command to manage your extensions.  For each extensions, there are a few actions to manage them. ## Add New Command One such action is the `Add New Command` action.  It will prompt you for the information about the new command before updating the manifest of the extension and creating the file for you based on the template you selected. PreviousDeveloper ToolsNextCLI Last updated 8 months ago --- ## Page: https://developers.raycast.com/information/developer-tools/cli 1. Information 3. Developer Tools ## CLI The Raycast CLI allows you to build, develop, and lint your extension. The CLI is part of the `@raycast/api` package and is automatically installed in your extension directory during setup. To get a list of the available CLI commands, run the following command inside your extension directory: npx ray help `npx ray build` creates an optimized production build of your extension for distribution. This command is used by our CI to publish your extension to the store. You can use `npx ray build -e dist` to validate that your extension builds properly. `npx ray develop` starts your extension in development mode. The mode includes the following: * Extension shows up at the top of the root search for quick access * Commands get automatically reloaded when you save your changes (you can toggle auto-reloading via Raycast Preferences > Advanced > "Auto-reload on save") * Error overlays include detailed stack traces for faster debugging * Log messages are displayed in the terminal * Status indicator is visible in the navigation title of the command to signal build errors * Imports the extension to Raycast if it wasn't before `npx ray lint` runs ESLint for all files in the `src` directory. `npx ray migrate` migrates your extension to the latest version of the `@raycast/api`. `npx ray publish` verifies, builds, and publishes an extension. If the extension is private (eg. has an `owner` and no public `access`), it will be published to the organization's private store. This command is only available to users that are part of that organization. Learn more about it here. Last updated 3 months ago --- ## Page: https://developers.raycast.com/information/developer-tools/eslint 1. Information 3. Developer Tools ## ESLint Raycast makes it easy to lint your extensions using the CLI's lint command (`ray lint`). Raycast provides by default an opinionated ESLint configuration that includes everything you need to lint your Raycast extensions. The default configuration is as simple as this: import { defineConfig } from "eslint/config"; import raycastConfig from "@raycast/eslint-config"; export default defineConfig([...raycastConfig]); It abstracts away the different ESLint dependencies used for Raycast extensions and includes different rule-sets. It also includes Raycast's own ESLint plugin rule-set that makes it easier for you to follow best practices when building extension. For example, there's a rule helping you follow the Title Case convention for `Action` components. You can check Raycast's ESLint plugin rules directly on the repository documentation. You're free to turn on/off rules or add new plugins as you see fit for your extensions. For example, you could add the rule `@raycast/prefer-placeholders` for your extension: import { defineConfig } from "eslint/config"; import raycastConfig from "@raycast/eslint-config"; export default defineConfig([ ...raycastConfig, { rules: { "@raycast/prefer-placeholders": "warn", }, }, ]); To keep the consistency of development experiences across extensions, we don't encourage adding too many personal ESLint preferences to an extension. Starting with version 1.48.8, the ESLint configuration is included automatically when creating a new extension using the `Create Extension` command. If your extension was created before this version, you can migrate following the steps outlined on the v1.48.8 page. Last updated 1 month ago --- ## Page: https://developers.raycast.com/information/developer-tools/vscode  GitHub 1. Information 3. Developer Tools ## VS Code (community tool) You can enhance your VS Code development experience by installing the Raycast extension in the marketplace. Here's a list of features provided by the extension: * IntelliSense for image assets * A tree view for easier navigation (commands and preferences) * VS Code commands for creating new commands and preferences * The possibility to attach a Node.js debugger * VS Code commands for `ray` operations like `build`, `dev`, `lint`, or `fix-lint` PreviousESLintNextTemplates Last updated 8 months ago --- ## Page: https://developers.raycast.com/information/developer-tools/templates 1. Information 3. Developer Tools ## Templates Learn about the templates provided by Raycast to help kickstart your extension. Raycast provides a variety of templates to kickstart your extension. Raycast provides 3 types of templates: * **Commands:** These are templates for commands. * **Tools:** These are templates for tools. You can select a different one for each tool that you add to your extension. * **Extension Boilerplates:** These are fully built extensions designed to be tweaked by organizations for internal use. Renders a simple Hello World from a markdown string.  Detail Template Render Renders a form that showcases all available form elements.  Submit Form Template Render Renders a grid of Icons available from Raycast. Defaults to a large grid, but provides a selection menu to change the size.  Grid Template Render See the API Reference for more information about customization. See here for information about Icons. Renders a list of options. When an option is selected, a Detail view is displayed.  List and Detail Template Render Adds a simple Menu Bar Extra with a menu.  Menu Bar Extra Template Render A example of a no-view command which shows a simple HUD. Renders a static list with each entry containing an icon, title, subtitle, and accessory.  List Template Render Renders a dynamic and searchable list of NPM packages. The command fetches new items as the search is updated by the user.  Typeahead Results Template Render Renders the output of an AI call in a Detail view.  AI Template Render A simple tool which asks for confirmation before executing.  Tool with Confirmation Template Render The Raycast Team has created high-quality templates to reinforce team experiences with the Raycast API. Run `npm init raycast-extension -t <template-name>` to get started with these extensions. All templates can be found on the templates page. Specific instructions about customizing the template can be found on the relevant template page. Simply customize the template as you see fit, then run `npm run publish` in the extension directory to allow your team to install the extension. Last updated 1 month ago --- ## Page: https://developers.raycast.com/information/security 1. Information ## Security Note that this is _not_ a guide on how to create secure Raycast extensions but rather an overview of security-related aspects on how extensions are built, distributed and run. Raycast itself runs outside of the App Store as "Developer ID Application", **signed** with the Raycast certificate and verified by Apple's **notarization service** before the app is distributed. Raycast provides various commands that interact with OS-level functionality, some of which prompt the user for granting **permissions** when required. The app is **automatically kept up-to-date** to minimize the risk of running heavily outdated versions and to ship hotfixes quickly. Raycast is a local-first application that stores user data in a local **encrypted database**, makes use of the system **Keychain** where secure data is stored, and generally connects to third-party APIs directly rather than proxying data through Raycast servers. All extensions are **open source** so the current source code can be inspected at all times. Before an extension gets merged into the **public repository**, members from Raycast and the community collaboratively **review** extensions, and follow our **store guidelines**. After the code review, the Continuous Integration system performs a set of **validations** to make sure that manifest conforms to the defined schema, required assets have the correct format, the author is valid, and no build and type errors are present. (More CI pipeline tooling for automated static security analysis is planned.) The built extension is then **archived and uploaded** to the Raycast Store, and eventually published for a registered user account. When an extension is installed or updated, the extension is downloaded from the store, unarchived to disk, and a record is updated in the local Raycast database. End-users install extensions through the built-in store or the web store. In order to run extensions, Raycast launches a **single child Node.js process** where extensions get loaded and unloaded as needed; inter-process communication with Raycast happens through standard file handles and a thin RPC protocol that only exposes a **defined set of APIs**, that is, an extension cannot just perform any Raycast operation. The **Node runtime is managed** by Raycast and automatically downloaded to the user's machine. We use an official version and **verify the Node binary** to ensure it has not been tampered with. An extension runs in its own **v8 isolate** (worker thread) and gets its own event loop, JavaScript engine and Node instance, and limited heap memory. That way, we ensure **isolation between extensions** when future Raycast versions may support background executions of multiple extensions running concurrently. Extensions are **not further sandboxed** as far as policies for file I/O, networking, or other features of the Node runtime are concerned; this might change in the future as we want to carefully balance user/developer experience and security needs. By default and similar to other macOS apps, accessing special directories such as the user Documents directory or performing screen recording first requires users to give **permissions** to Raycast (parent process) via the **macOS Security & Preferences** pane, otherwise programmatic access is not permitted. While extensions can access the file system and use their own methods of storing and accessing data, Raycast provides **APIs for securely storing data**: _password_ preferences can be used to ask users for values such as access tokens, and the local storage APIs provide methods for reading and writing data payloads. In both cases, the data is stored in the local encrypted database and can only be accessed by the corresponding extension. Both Raycast itself and extensions are **automatically updated** and we think of this as a security feature since countless exploits have happened due to outdated and vulnerable software. Our goal is that neither developers nor end-users need to worry about versions, and we **minimize the time from update to distribution** to end-users. Last updated 10 months ago --- ## Page: https://developers.raycast.com/information/versioning 1. Information ## Versioning Versioning your extensions is straightforward since we've designed the system in a way that **frees you from having to deal with versioning schemes and compatibility**. The model is similar to that of app stores where there's only one implicit _latest_ version that will be updated when the extension is published in the store. Extensions are automatically updated for end users. For **development**, this means that you do _not_ declare a version property in the manifest. If you wish to use API features that were added in a later version, you just update your `@raycast/api` npm dependency, start using the feature, and submit an extension update to the store. For **end-users** installing or updating your extension, Raycast automatically checks the compatibility between the API version that the extension actually uses and the user's current Raycast app version (which contains the API runtime and also manages the Node version). If there's a compatibility mismatch such as the user not having the required latest Raycast app version, we show a hint and prompt the user to update Raycast so that the next compatibility check succeeds. Optionally, you can provide a `changelog.md` file in your extension, and give detailed changes with every update. These changes can be viewed by the user on the extension details screen, under Version History, as well as on the raycast.com/store. You can learn more about Version History here, how to add it to your extension, and the required format for the best appearance. Generally, we follow an **API evolution** process, meaning that we stay backward-compatible and do not introduce breaking changes within the same major API version. We'll 1) add new functionality and 2) we'll mark certain API methods and components as _deprecated_ over time, which signals to you that you should stop using those features and migrate to the new recommended alternatives. At some point in the future, we may introduce a new breaking major release; however, at this time, you will be notified, and there will be a transition period for migrating extensions. Last updated 2 years ago