The problem starts small. We already press ⌘+Space all day to open Spotlight for apps and files. It handles both well. But once the workday has things that repeat, like checking one particular status screen or flipping into a quiet mode before a call, Spotlight has nothing to offer. It only knows apps and files, not tasks.
Part 1What Raycast Actually Is
Raycast was built to answer exactly that gap. It looks like Spotlight: same search bar, same app and file lookup, but it lets you plug your own commands into that same bar. Spotlight answers "what do you want to open." Raycast answers "what do you want to run," which is a much wider question.
The most common answer when people look up spotlight alternative mac is that Raycast is a faster launcher, which is true but incomplete. The launcher part is the front door everyone walks through on day one. The real shift happens once you realize your own scripts can live in that same search bar. That is the point where it stops being "a nicer Spotlight" and starts doing work for you.
This post continues our "what is" series, following earlier posts on daemons and AI agents. Same approach here: start from a real problem, not a feature list.
Part 2How to Actually Use It, Easy to Hard
Level 1: opening apps and files (anyone can start here)
Same starting point as Spotlight, just faster and more forgiving of typos. Type part of an app or file name and it shows up. Nothing to configure, just swap the hotkey and go.
Level 2: clipboard history
Raycast remembers several past clipboard entries, not just the last one like the default Mac clipboard. Copy a tracking number in the morning, copy something else in the afternoon, and the morning one is still searchable and pasteable without digging through old chats to find it again.
The trade-off worth knowing on day one: everything ever copied is kept and searchable, so any password, card number, or token that passed through the clipboard is sitting in there too. History can be set to auto-clear after a set period, and genuinely sensitive values belong in a password manager rather than a clipboard left lying around.
Level 3: snippets
Type a short abbreviation and let it expand into a longer block of text. Good for anything typed word for word every day, like an email signature, a shipping address, or a stock reply to customers. Set it up once, works in any app that accepts typed text.
Level 4: script commands (write your own short shell script)
This is where it gets interesting. If a shell command already gets run repeatedly, it can be turned into a Raycast search command directly. Add a specially formatted comment block near the top of the script. Here is a real example from one of the buttons in daily use.
#!/bin/bash
# @raycast.schemaVersion 1
# @raycast.title Demo Mode
# @raycast.mode fullOutput
# @raycast.icon 🔇
# @raycast.packageName Demo
# @raycast.argument1 { "type": "text", "placeholder": "2h / off / blank=toggle", "optional": true }
# @raycast.description mute everything that could pop up mid client demo
That is enough for Raycast to recognize the file as a searchable command called "Demo Mode." Raycast's own docs cover this comment format in full, filed under raycast script commands. This is the moment anyone who can already write a basic script goes "oh, that's it?" because there is nothing new to learn, just a few comment lines on top of what already exists.
Part 3What We Actually Use It For
This part is not the next rung on the ladder from Parts 1-2, which anyone can follow step by step. It is behind-the-scenes territory. The three buttons below rely on internal scripts not shown here, so they cannot be copied directly. For a full script command you can actually copy and run yourself, see the runnable example at the end of the traps section below.
The three buttons in daily use
Demo Mode (🔇) Before a client demo, the worst thing is a random window or sound popping up on a shared screen. This button, pressed once, closes anything that could pop up mid-demo in one shot: leftover windows from background automation, notifications, and sound. Type demo on 2h and it goes quiet for two hours, then reverts on its own without needing to remember to turn it back off.
System Status Check Another button in daily use, a one-screen summary of the background system instead of checking each piece separately. Timed three times while writing this post, it came back in a little over three seconds each time (a personal impression that this feels much faster than the old way, though the old way was never actually timed for a fair comparison). What exactly it checks is internal detail not covered in this post.
Consult Bud (💬) Tied to a set of specialized AI assistants set up for different kinds of tasks. Pick one from a dropdown, type a question, hit send, then check back later for the answer. No need to switch to a chat app first. (What each assistant actually does, and how it works behind the scenes, is internal detail this post is not covering. The point worth sharing here is the button pattern, not the system behind it.)
Four traps hit while building these buttons
All four are what showed up on one machine, Raycast 1.104.24 on macOS 26.2, on 3 August 2026. They are not permanent facts about the product, and any of them could change with a release.
1. As tested on the version currently in use, Raycast does not follow symlinked script directories. (A symlink is a pointer to a real folder somewhere else, not a copy of it.) The instinct was to consolidate script folders into one by turning the real folder into a symlink pointing at a git repo. Every button vanished immediately, no error, no warning, the deeplink just fired into silence. Worse, reverting the symlink back to a real folder did not bring the buttons back right away either. Raycast had to be fully quit and reopened before it would re-index (rescan and rebuild its list of commands) and see them again. What actually works: two real folders, and copy files between them, never a symlink.
2. There is no way to check which folder Raycast is actually reading. Raycast's config file cannot be read directly. Checking it with the file command just returns "data," and the first 16 bytes do not match the signature a plain database file would start with either. What worked instead: insert a line into the script that writes a temporary marker file, fire the deeplink for that command, then poll for the marker to appear within a few seconds. If it shows up, Raycast really is reading that folder and running that script.
rm -f /tmp/probe # important: a leftover marker from a previous run will fake a pass
open "raycast://script-commands/my-script"
for i in $(seq 1 20); do
[ -f /tmp/probe ] && break
sleep 1
done
[ -f /tmp/probe ] && echo REGISTERED || echo NOT-REGISTERED
3. Firing a deeplink with an argument produced inconsistent behavior, and the exact cause is still unclear. The plan was a read-only status deeplink using ?arguments=status. That time, the script ran, but the argument (the value typed alongside the command) arrived empty, so it fell through to the script's default case, which happened to be toggle (flip between on and off). Pressing what was meant to be a status check instead flipped quiet mode on by accident.
While digging into why, a test script that echoes back whatever argument it receives got fired repeatedly with different encodings. The first assumption was that the value needed to be wrapped as a JSON array and urlencoded, like ?arguments=%5B%22hello%22%5D, before it would pass through. Retesting that carefully with controlled variables showed the opposite: a plain ?arguments=hello passed through to the script correctly, while the JSON-array-wrapped version arrived as a raw literal string, brackets and all, never decoded. So it is still not clear what actually caused the original failure. (One thing that differed between the original incident and the retest: a confirmation dialog for running a script triggered from outside Raycast showed up during retesting. Whether that is related is unknown.)
The lesson that holds regardless of the exact cause: if a command needs an argument, do not rely on a bare deeplink alone, bind a hotkey to the command inside Raycast instead so the argument field actually shows up for typing. More importantly, a script's default behavior should never be a state-changing action. Default to showing status, not changing it, so an accidental trigger never changes anything, no matter what causes it.
4. The folder Raycast actually runs from was not backed up anywhere. The live script folder Raycast reads is not a git repo and was never part of the backup routine. A one-time manual copy into a repo existed, but nothing kept it in sync, so the newest script written ended up living on exactly one disk with zero backups. The fix was making the backup script copy from the live folder Raycast actually uses into git, never the other direction, since the live folder is the one the system actually runs, which makes it the source of truth everything else should follow.
A full script command you can copy and run
The three buttons above rely on internal scripts not shown here, but the script command format is the same everywhere. Here is an example that needs nothing beyond what already ships with a Mac. Copy the whole file into Raycast's script command folder and it works. Actually run, it produces this.
#!/bin/bash
# @raycast.schemaVersion 1
# @raycast.title My IP
# @raycast.mode fullOutput
# @raycast.icon 🌐
# @raycast.packageName Utilities
# @raycast.description show which interface is carrying traffic and its local IP
IFACE=$(route get default 2>/dev/null | awk '/interface:/{print $2}')
LOCAL_IP=$(ipconfig getifaddr "${IFACE:-en0}" 2>/dev/null)
echo "Interface: ${IFACE:-not found}"
echo "Local IP: ${LOCAL_IP:-not found}"
Interface: en0
Local IP: 192.168.1.23
(The real numbers will differ per machine, the two lines above are just the output shape.)
This example deliberately stays on the machine and calls nothing outside it. The first line asks macOS directly which interface currently carries traffic, rather than guessing en0, which is wrong the moment a VPN or an extra adapter is in play. Adding the IP the outside world sees is easy enough, but that means firing a request at somebody else's server every single time the button is pressed, which is worth deciding on rather than inheriting.
Easy to extend without touching the structure, swap the echo lines for a disk check with df -h / instead, for example.
Before you go
Raycast starts out as a better Spotlight. What makes it a daily habit is not app-launching speed, it is moving repetitive work that used to mean opening a terminal or switching between several apps into one search bar. The question worth asking is not "can this replace Spotlight," because it already does. It is "what do I press over and over every day that is still not wired up yet."