# How to Build Custom Workflows with Raycast for macOS Productivity Automation

> Automate macOS tasks with custom Raycast workflows. Learn to build powerful commands using JavaScript and TypeScript for enhanced productivity.

- Repository: [Elliot Chen/one-person-company](https://github.com/cyfyifanchen/one-person-company)
- Tags: tutorial
- Published: 2026-02-28

---

**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`](https://github.com/cyfyifanchen/one-person-company/blob/main/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`](https://github.com/cyfyifanchen/one-person-company/blob/main/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`](https://github.com/cyfyifanchen/one-person-company/blob/main/script.js):

```javascript
// 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`](https://github.com/cyfyifanchen/one-person-company/blob/main/package.json) that registers the command:

```json
{
  "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`](https://github.com/cyfyifanchen/one-person-company/blob/main/raycast-workflows/ai-summarize/script.js):

```javascript
// 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`](https://github.com/cyfyifanchen/one-person-company/blob/main/package.json):

```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`](https://github.com/cyfyifanchen/one-person-company/blob/main/raycast-workflows/date-rename/script.js):

```javascript
// 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`](https://github.com/cyfyifanchen/one-person-company/blob/main/package.json) with preferences configuration:

```json
{
  "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`](https://github.com/cyfyifanchen/one-person-company/blob/main/script.js) and [`package.json`](https://github.com/cyfyifanchen/one-person-company/blob/main/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`](https://github.com/cyfyifanchen/one-person-company/blob/main/package.json) command schema and a [`script.js`](https://github.com/cyfyifanchen/one-person-company/blob/main/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`](https://github.com/cyfyifanchen/one-person-company/blob/main/script.js) and [`package.json`](https://github.com/cyfyifanchen/one-person-company/blob/main/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.