How to Build Custom Workflows with Raycast for macOS Productivity Automation

Raycast enables macOS productivity automation through JavaScript and TypeScript workflows that run in a sandboxed Node.js environment, allowing you to create custom commands that interact with system APIs, external AI services, and the clipboard.

The cyfyifanchen/one-person-company repository curates essential tools for solo entrepreneurs, highlighting Raycast in its productivity section as a "高效启动器、工作流自动化、丰富插件" (efficient launcher with workflow automation and rich plugins) according to the source documentation at README.md line 511. Learning how to build custom workflows with Raycast transforms your macOS experience from simple app launching to powerful automation that connects AI services, file systems, and daily utilities without leaving your keyboard.

Understanding Raycast Workflow Architecture

Raycast workflows are built on three core components that execute within a sandboxed Node.js runtime. Each workflow consists of a command definition that registers the tool with Raycast's UI, a script implementation that contains your automation logic using the @raycast/api package, and optional assets such as icons or configuration files.

The package.json file in your workflow directory defines the command schema, specifying the title, description, argument types, and entry point script. When you trigger the command via Raycast's hotkey or search interface, the sandboxed environment executes your JavaScript or TypeScript file, passing user arguments and providing access to macOS system features like the clipboard, Finder, and notification center through Raycast's API wrappers.

Building a Simple URL Opener Workflow

Start with a foundational workflow that reads from the clipboard and opens URLs in your default browser. This pattern demonstrates how to access system clipboard data and use Raycast's UI feedback components.

Create the directory raycast-workflows/open-url/ and add the following script.js:

// raycast-workflows/open-url/script.js
import { showToast, ToastStyle, open } from "@raycast/api";

export default async function main() {
  const url = (await Clipboard.readText()).trim();
  if (!url.startsWith("http")) {
    await showToast(ToastStyle.Failure, "Invalid URL", "Please provide a valid http(s) URL.");
    return;
  }
  await open(url);
  await showToast(ToastStyle.Success, "Opened", url);
}

Accompany this with a package.json that registers the command:

{
  "title": "Open URL",
  "description": "Open a URL from the clipboard or input",
  "author": "cyfyifanchen",
  "icon": "icon.png",
  "argument": {
    "type": "text",
    "placeholder": "Enter URL (optional, will use clipboard if empty)"
  },
  "script": "script.js"
}

This workflow validates input, provides error handling through toast notifications, and demonstrates the open API for launching browser URLs.

Integrating AI APIs into Raycast Workflows

Leverage the repository's focus on AI tools by building a workflow that summarizes clipboard content using a large language model. This example uses the DeepSeek API, though you can adapt it for Gemini, OpenAI, or other providers listed in the repository's AI section.

Create raycast-workflows/ai-summarize/script.js:

// raycast-workflows/ai-summarize/script.js
import { showToast, ToastStyle, Form, List, ActionPanel, Action, Clipboard } from "@raycast/api";

async function summarize(text) {
  const response = await fetch("https://api.deepseek.com/v1/chat/completions", {
    method: "POST",
    headers: { 
      "Content-Type": "application/json", 
      Authorization: "Bearer YOUR_API_KEY" 
    },
    body: JSON.stringify({
      model: "deepseek-chat",
      messages: [{ role: "user", content: `Summarize this in 2 sentences:\n${text}` }],
      temperature: 0.5,
    }),
  });
  const data = await response.json();
  return data.choices?.[0]?.message?.content ?? "No summary.";
}

export default function Command() {
  return (
    <Form
      actions={
        <ActionPanel>
          <Action.SubmitForm title="Summarize Clipboard" onSubmit={async () => {
            const text = await Clipboard.readText();
            const toast = await showToast(ToastStyle.Animated, "Summarizing…");
            const summary = await summarize(text);
            await showToast(ToastStyle.Success, "Summary", summary);
          }}/>
        </ActionPanel>
      }
    />
  );
}

The corresponding package.json:

{
  "title": "AI Summarizer",
  "description": "Summarize clipboard content with an LLM",
  "author": "cyfyifanchen",
  "icon": "icon.png",
  "script": "script.js"
}

This workflow demonstrates asynchronous API calls, Form UI components, and clipboard integration—essential patterns for AI-powered automation.

Automating File Operations with Node.js

For daily file management tasks, build a workflow that batch-renames files with date prefixes using Node.js native modules. This example uses getPreferenceValues() to store user configuration persistently.

Create raycast-workflows/date-rename/script.js:

// raycast-workflows/date-rename/script.js
import { showToast, ToastStyle, open, Clipboard, confirmAlert, getPreferenceValues } from "@raycast/api";
import { readdir, rename } from "fs/promises";
import { join } from "path";

export default async function main() {
  const { folderPath } = getPreferenceValues();
  const files = await readdir(folderPath);
  const date = new Date().toISOString().slice(0, 10);

  const confirm = await confirmAlert({
    title: "Rename Files",
    message: `Add prefix "${date}" to ${files.length} files in ${folderPath}?`,
  });
  if (!confirm) return;

  for (const f of files) {
    const oldPath = join(folderPath, f);
    const newPath = join(folderPath, `${date}-${f}`);
    await rename(oldPath, newPath);
  }
  await showToast(ToastStyle.Success, "Renamed", `${files.length} files`);
}

The package.json with preferences configuration:

{
  "title": "Date Prefix Renamer",
  "description": "Add today's date as a prefix to all files in a folder",
  "author": "cyfyifanchen",
  "icon": "icon.png",
  "script": "script.js",
  "preferences": [
    {
      "name": "folderPath",
      "type": "text",
      "default": "~/Desktop",
      "title": "Folder to process"
    }
  ]
}

This workflow demonstrates filesystem access, user preferences, and confirmation dialogs—critical for safe automation scripts.

Organizing Workflows in the Repository

To maintain these scripts as part of the one-person-company knowledge base, structure them under a dedicated directory at the repository root. Create a raycast-workflows/ folder containing subdirectories for each workflow (open-url/, ai-summarize/, date-rename/), each containing their respective script.js and package.json files.

This organization aligns with the repository's goal of "帮助您踩坑,精准找宝" (helping you avoid pitfalls and find treasures) by providing version-controlled, runnable automation examples. When committing these files, ensure you exclude sensitive API keys by adding raycast-workflows/*/script.js to .gitignore or using environment variables for authentication tokens.

Summary

  • Raycast workflows run in a sandboxed Node.js environment using JavaScript or TypeScript, defined by a package.json command schema and a script.js implementation file.
  • Basic automation requires only the @raycast/api imports for UI components like showToast and system integration methods like Clipboard.readText().
  • AI integration follows the repository's LLM focus by using standard fetch calls to APIs like DeepSeek, wrapped in Raycast's Form and Action components.
  • File system automation leverages Node.js native modules (fs/promises, path) combined with getPreferenceValues() for persistent user configuration.
  • Repository organization places workflows under raycast-workflows/ with individual subdirectories for each command, maintaining clean version control.

Frequently Asked Questions

What programming languages does Raycast support for custom workflows?

Raycast supports JavaScript and TypeScript for custom workflows. Scripts run inside a sandboxed Node.js environment that has the @raycast/api package pre-installed, giving you access to macOS system features and UI components without needing to configure a local Node.js installation.

How do I share my custom Raycast workflows with my team?

To share workflows, place your script.js and package.json files in a version-controlled directory such as raycast-workflows/ within your repository. Team members can copy these folders into their local Raycast scripts directory or use Raycast's built-in import/export functionality. Ensure you remove hardcoded API keys before committing by using environment variables or Raycast's preference system.

Can Raycast workflows access my file system and clipboard?

Yes, Raycast workflows have controlled access to macOS system features through the @raycast/api module. You can read from and write to the clipboard using Clipboard.readText() and Clipboard.copy(). For file system operations, you can import Node.js modules like fs/promises and path to read directories, rename files, and manipulate data directly from your scripts.

Are Raycast workflows secure since they run JavaScript?

Raycast workflows run in a sandboxed Node.js environment that limits access to your system compared to standard Node.js scripts. While they can access the clipboard, file system (with user permission), and network APIs, they cannot execute arbitrary shell commands or access sensitive system areas without explicit user action. Always review third-party scripts before installation and store API keys in Raycast's encrypted preferences rather than hardcoding them in your source files.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →