Overview
SuperCmd provides a comprehensive compatibility layer that implements the entire Raycast API surface. This allows existing Raycast extensions to run without modification while enabling SuperCmd-specific enhancements.
The API shim lives in src/renderer/src/raycast-api/ and is split into focused runtime modules for maintainability. The index.tsx file serves as the integration surface that wires everything together.
Architecture
The Raycast API implementation follows a modular architecture:
raycast-api/
βββ index.tsx # Main export surface
βββ action-runtime*.tsx # Action & ActionPanel
βββ list-runtime*.tsx # List component
βββ form-runtime*.tsx # Form component
βββ grid-runtime*.tsx # Grid component
βββ detail-runtime.tsx # Detail component
βββ menubar-runtime*.tsx # MenuBarExtra
βββ icon-runtime*.tsx # Icon system
βββ hooks/ # @raycast/utils hooks
βββ oauth/ # OAuth implementation
Core Exports
Components
All major Raycast components are fully implemented:
import { List } from '@raycast/api' ;
export default function Command () {
return (
< List >
< List . Item
title = "Item 1"
accessories = { [
{ text: 'Badge' },
{ icon: Icon.Star }
]}
actions={
<ActionPanel>
<Action.OpenInBrowser url="https: //example.com" />
</ ActionPanel >
}
/>
</ List >
);
}
Features:
Filtering with onSearchTextChange
Pagination support
Accessories (text, icons, dates)
List.Item.Detail with Metadata
Sections with subtitles
Empty states
import { Form , ActionPanel , Action } from '@raycast/api' ;
export default function Command () {
return (
< Form
actions = {
<ActionPanel>
<Action. SubmitForm
title = "Submit"
onSubmit = {(values) => console.log(values)}
/>
</ActionPanel>
}
>
< Form . TextField id = "name" title = "Name" />
< Form . TextArea id = "bio" title = "Bio" />
< Form . Dropdown id = "role" title = "Role" >
< Form . Dropdown . Item value = "dev" title = "Developer" />
< Form . Dropdown . Item value = "designer" title = "Designer" />
</ Form . Dropdown >
< Form . DatePicker id = "date" title = "Start Date" />
< Form . Checkbox id = "agree" label = "I agree" />
</ Form >
);
}
All Field Types:
TextField (with validation)
TextArea (multi-line)
Dropdown (single/multi-select)
DatePicker (date, time, datetime)
Checkbox
FilePicker (files/directories)
Separator
Description (read-only text)
import { Grid } from '@raycast/api' ;
export default function Command () {
return (
< Grid columns = { 5 } fit = {Grid.Fit. Fill } >
< Grid . Item
content = "π¨"
title = "Art"
actions = { /* ... */ }
/>
< Grid . Section title = "Photos" >
< Grid . Item
content = {{ source : 'photo.jpg' }}
title = "Vacation"
/>
</ Grid . Section >
</ Grid >
);
}
Features:
Dynamic column count
Grid.Fit (Fill/Contain)
Sections with custom layouts
Aspect ratio control
Image and emoji content
import { Detail } from '@raycast/api' ;
export default function Command () {
return (
< Detail
markdown = "# Hello World \n\n Welcome to **SuperCmd**!"
metadata = {
<Detail.Metadata>
<Detail.Metadata. Label
title = "Status"
text = "Active"
/>
<Detail.Metadata. Link
title = "Website"
target = "https://example.com"
text = "Visit"
/>
<Detail.Metadata.TagList title = "Tags" >
<Detail.Metadata.TagList.Item text = "Important" color = "#FF0000" />
</Detail.Metadata.TagList>
<Detail.Metadata.Separator />
</Detail.Metadata>
}
/>
);
}
The useNavigation hook provides navigation stack control:
import { useNavigation } from '@raycast/api' ;
function MyComponent () {
const { push , pop } = useNavigation ();
return (
< Action
title = "Go to Details"
onAction = {() => push (< DetailView />)}
/>
);
}
Functions
Window Management
showToast
showHUD
confirmAlert
import { showToast , Toast } from '@raycast/api' ;
await showToast ({
style: Toast . Style . Success ,
title: 'Operation Complete' ,
message: 'Your data has been saved' ,
primaryAction: {
title: 'Undo' ,
onAction : () => console . log ( 'Undo' ),
},
});
Toast Styles:
Toast.Style.Success - Green checkmark
Toast.Style.Failure - Red error
Toast.Style.Animated - Loading spinner
import { showHUD } from '@raycast/api' ;
await showHUD ( 'Copied to clipboard' );
Shows a temporary heads-up display notification. import { confirmAlert , Alert } from '@raycast/api' ;
const confirmed = await confirmAlert ({
title: 'Delete Item' ,
message: 'This action cannot be undone' ,
primaryAction: {
title: 'Delete' ,
style: Alert . ActionStyle . Destructive ,
},
dismissAction: {
title: 'Cancel' ,
},
});
System Integration
import {
getApplications ,
getDefaultApplication ,
getFrontmostApplication ,
open ,
} from '@raycast/api' ;
// Get all installed applications
const apps = await getApplications ();
// Get default app for a file
const defaultApp = await getDefaultApplication ( 'document.pdf' );
// Get currently active app
const frontmost = await getFrontmostApplication ();
// Open URL in default browser
await open ( 'https://example.com' );
// Open URL in specific app
await open ( 'https://example.com' , 'Safari' );
import {
getSelectedFinderItems ,
showInFinder ,
trash ,
} from '@raycast/api' ;
// Get selected files in Finder
const files = await getSelectedFinderItems ();
// Show file in Finder
await showInFinder ( '/path/to/file.txt' );
// Move to trash
await trash ([ '/path/to/file.txt' ]);
Storage & State
LocalStorage
Persistent key-value storage scoped to each extension:
import { LocalStorage } from '@raycast/api' ;
// Store values (supports string, number, boolean)
await LocalStorage . setItem ( 'lastSearch' , 'raycast' );
await LocalStorage . setItem ( 'count' , 42 );
await LocalStorage . setItem ( 'enabled' , true );
// Retrieve values
const search = await LocalStorage . getItem ( 'lastSearch' ); // 'raycast'
const count = await LocalStorage . getItem ( 'count' ); // 42
// Get all items
const all = await LocalStorage . allItems ();
// Remove items
await LocalStorage . removeItem ( 'lastSearch' );
await LocalStorage . clear ();
SuperCmd uses a scoped prefix (sc-ext:{extensionName}:) to isolate storage between extensions. Legacy keys are automatically migrated.
LRU cache with size limits:
import { Cache } from '@raycast/api' ;
const cache = new Cache ({
capacity: 10 * 1024 * 1024 , // 10MB
namespace: 'my-cache' ,
});
// Store data
cache . set ( 'user:123' , JSON . stringify ( userData ));
// Retrieve data
const cached = cache . get ( 'user:123' );
// Subscribe to changes
const unsubscribe = cache . subscribe (( key , data ) => {
console . log ( `Cache updated: ${ key } ` );
});
Clipboard
Advanced clipboard operations with history support:
import { Clipboard } from '@raycast/api' ;
// Copy text
await Clipboard . copy ( 'Hello World' );
// Copy without showing toast
await Clipboard . copy ( 'Secret' , { concealed: true });
// Copy rich content
await Clipboard . copy ({
text: 'Plain text' ,
html: '<b>Rich HTML</b>' ,
});
// Copy files
await Clipboard . copy ({
file: '/path/to/image.png' ,
});
// Read clipboard
const text = await Clipboard . readText ();
const content = await Clipboard . read (); // { text, html, file }
// Paste to active app
await Clipboard . paste ( 'Text to paste' );
AI Integration
Full AI API with streaming support:
AI.ask()
Streaming
Available Models
import { AI } from '@raycast/api' ;
const answer = await AI . ask ( 'What is the capital of France?' , {
model: AI . Model . Anthropic_Claude_Sonnet ,
creativity: 'medium' ,
});
console . log ( answer ); // 'Paris'
import { AI } from '@raycast/api' ;
const stream = AI . ask ( 'Write a poem' );
stream . on ( 'data' , ( chunk ) => {
process . stdout . write ( chunk );
});
const fullText = await stream ;
AI . Model = {
OpenAI_GPT4o: 'openai-gpt-4o' ,
OpenAI_GPT4o_mini: 'openai-gpt-4o-mini' ,
OpenAI_o1: 'openai-o1' ,
Anthropic_Claude_Opus: 'anthropic-claude-opus' ,
Anthropic_Claude_Sonnet: 'anthropic-claude-sonnet' ,
Anthropic_Claude_Haiku: 'anthropic-claude-haiku' ,
Google_Gemini_2_5_Pro: 'gemini-gemini-2.5-pro' ,
Google_Gemini_2_5_Flash: 'gemini-gemini-2.5-flash' ,
};
@raycast/utils Hooks
Advanced utility hooks for common patterns:
useCachedPromise
useFetch
useAI
useSQL
useExec
import { useCachedPromise } from '@raycast/utils' ;
function SearchCommand () {
const { data , isLoading , revalidate } = useCachedPromise (
async ( query : string ) => {
const response = await fetch ( `/api/search?q= ${ query } ` );
return response . json ();
},
[ 'initial query' ],
{
keepPreviousData: true ,
}
);
return (
< List isLoading = { isLoading } >
{ data ?. map ( item => (
< List . Item key = {item. id } title = {item. title } />
))}
</ List >
);
}
import { useFetch } from '@raycast/utils' ;
const { data , isLoading } = useFetch ( 'https://api.example.com/data' , {
headers: { 'Authorization' : 'Bearer token' },
parseResponse : async ( response ) => {
const json = await response . json ();
return json . results ;
},
});
import { useAI } from '@raycast/utils' ;
const { data , isLoading } = useAI ( 'Summarize this text: ...' );
import { useSQL } from '@raycast/utils' ;
const { data , isLoading } = useSQL (
'/path/to/database.db' ,
'SELECT * FROM users WHERE name LIKE ?' ,
[ '%John%' ]
);
import { useExec } from '@raycast/utils' ;
const { data , isLoading } = useExec ( 'git' , [ 'status' ], {
cwd: '/path/to/repo' ,
});
Icon System
SuperCmd maps Raycast icon names to Phosphor icons:
import { Icon , Color , List } from '@raycast/api' ;
< List . Item
icon = {{ source : Icon . Star , tintColor : Color . Yellow }}
title = "Favorite"
/>
< List . Item
icon = {{ source : 'custom-icon.png' }} // Asset from extension
title = "Custom Icon"
/>
< List . Item
icon = "π" // Emoji
title = "Celebration"
/>
Icon Runtime
The icon system is split into focused modules:
icon-runtime-phosphor.tsx Raycast icon name β Phosphor icon mapping with 200+ icons
icon-runtime-assets.tsx Asset path normalization and sc-asset:// protocol handling
icon-runtime-render.tsx Actual rendering logic with tint color support
icon-runtime-config.ts Extension context injection for asset resolution
Environment Object
Provides extension context and system information:
import { environment , LaunchType } from '@raycast/api' ;
environment . extensionName ; // 'my-extension'
environment . commandName ; // 'search'
environment . commandMode ; // 'view' | 'no-view' | 'menu-bar'
environment . assetsPath ; // '/path/to/assets'
environment . supportPath ; // '/path/to/extension/data'
environment . raycastVersion ; // '1.80.0'
environment . appearance ; // 'dark' | 'light'
environment . launchType ; // LaunchType.UserInitiated
environment . isDevelopment ; // false
// Feature detection
if ( environment . canAccess ( AI )) {
// AI is available
}
OAuth Implementation
Full OAuth 2.0 support with PKCE:
import { OAuth } from '@raycast/api' ;
const client = new OAuth . PKCEClient ({
redirectMethod: OAuth . RedirectMethod . Web ,
providerName: 'GitHub' ,
providerIcon: 'github-logo.png' ,
description: 'Connect your GitHub account' ,
});
const authRequest = await client . authorizationRequest ({
endpoint: 'https://github.com/login/oauth/authorize' ,
clientId: 'your-client-id' ,
scope: 'repo user' ,
});
const { authorizationCode } = await client . authorize ( authRequest );
const tokens = await client . exchangeTokens ({
endpoint: 'https://github.com/login/oauth/access_token' ,
clientId: 'your-client-id' ,
codeVerifier: authRequest . codeVerifier ,
authorizationCode ,
});
await client . setTokens ( tokens );
OAuth Service Presets
Pre-configured services for popular providers:
import { OAuthService } from '@raycast/api' ;
const github = OAuthService . github ({
clientId: 'your-client-id' ,
scope: 'repo user' ,
});
const spotify = OAuthService . spotify ({
clientId: 'your-client-id' ,
scope: 'user-read-private' ,
});
const linear = OAuthService . linear ({
clientId: 'your-client-id' ,
scope: 'read write' ,
});
Implementation Status
SuperCmd implements 100% of the core Raycast API :
@raycast/api Components (100%)
β
List (with filtering, pagination, accessories, Detail)
β
Detail (with Metadata: Label, Link, TagList, Separator)
β
Form (all field types, validation, drafts)
β
Grid (sections, fit modes, aspect ratio)
β
ActionPanel (with Submenu)
β
Action (all action types)
β
MenuBarExtra (menu bar integration)
@raycast/api Functions (100%)
β
showToast, showHUD, confirmAlert
β
open, closeMainWindow, popToRoot
β
launchCommand, clearSearchBar
β
getApplications, getDefaultApplication, getFrontmostApplication
β
getSelectedText, getSelectedFinderItems
β
trash, showInFinder
β
openExtensionPreferences, openCommandPreferences
β
updateCommandMetadata
β
captureException
@raycast/utils Hooks (100%)
β
useFetch (with pagination)
β
useCachedPromise (with cursor pagination)
β
useCachedState
β
usePromise (with mutate/revalidate)
β
useForm (with validation)
β
useExec
β
useSQL
β
useStreamJSON
β
useAI
β
useFrecencySorting
β
useLocalStorage
Best Practices
Always import from @raycast/api, never from internal paths
Use TypeScript for better type safety and autocomplete
Handle loading and error states in async operations
Test extensions with different themes (dark/light)
Always wrap async operations in try/catch
Show user-friendly error messages with showToast
Use captureException() to log errors
Provide fallback UI for error states
See Also
Extension Runtime Learn how extensions are loaded and executed
Electron Architecture Understand the IPC bridge and process model
Raycast API Docs Official Raycast API documentation