Confirm successful installation by checking the skill directory location:
.cursor/skills/ray-so-code-snippet
Restart Cursor to activate ray-so-code-snippet. Access via /ray-so-code-snippet in your agent's command palette.
β
Security Notice
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your environment. Always review source, verify the publisher, and test in isolation before production.
Generate beautiful code snippet images using ray.so and save them locally.
Requirements
The user MUST provide the code snippet, either directly or by pointing to a file/selection in context
MUST ask the user for ALL styling parameters before generating, presenting ALL available options
MUST use agent-browser for screenshot capture (check availability first)
Workflow
Step 1: Verify agent-browser Availability
Before proceeding, verify that agent-browser is available:
which agent-browser
If agent-browser is not found in the PATH, inform the user that this skill requires agent-browser and cannot proceed without it.
Step 2: Fetch Available Options
Fetch the current themes and languages from ray.so's GitHub repository using curl:
# Fetch and parse available themescurl-s"https://raw.githubusercontent.com/raycast/ray-so/main/app/(navigation)/(code)/store/themes.ts"|grep-oE'id:\s*"[^"]+"'|sed's/id:\s*"//;s/"//'|sort-u# Fetch and parse available languagescurl-s"https://raw.githubusercontent.com/raycast/ray-so/main/app/(navigation)/(code)/util/languages.ts"|grep-oE'^[[:space:]]*"?[a-zA-Z0-9+#-]+"?\s*:\s*\{'|sed's/[[:space:]]*"//g;s/".*//;s/:.*//'|sort-u
Step 3: Ask User for ALL Parameters
MUST use AskUserQuestion to ask for EVERY parameter, presenting ALL available options. Ask for parameters in this order:
3.1 Theme Selection
Present ALL available themes. In the question, list every theme fetched from step 2. Example:
Question: "Which theme would you like?"
Description: "Available themes: [list ALL themes from curl output]"
Options (pick 4 popular ones for quick select):
- breeze (default, purple gradient)
- midnight (cyan-blue)
- vercel (minimalist dark)
- sunset (warm orange)
Note: User can select "Other" to type any theme from the full list
3.2 Language Selection
Infer the language when possible. Skip this question if:
The user explicitly specified a language
The code comes from a file with a clear extension (e.g., .py β python, .js β javascript, .ts β typescript, .rs β rust, .go β go, etc.)
The syntax is unmistakably identifiable (e.g., def/import β python, func/package β go, fn/let mut β rust)
Only ask this question if the language cannot be confidently inferred:
Question: "Which language for syntax highlighting?"
Description: "Available languages: [list ALL languages from curl output]"
Options:
- auto (auto-detect)
- javascript
- python
- typescript
Note: User can select "Other" to type any language from the full list
3.3 Dark/Light Mode
Question: "Dark or light mode?"
Options:
- Dark mode (default)
- Light mode
3.4 Background
Question: "Show the gradient background?"
Options:
- Yes, show background (default)
- No, transparent/minimal background
3.5 Padding
Question: "How much padding around the code?"
Options:
- 16 (compact)
- 32 (small)
- 64 (medium, default)
- 128 (large)
3.6 Line Numbers
Question: "Show line numbers?"
Options:
- No (default)
- Yes
3.7 Title
Question: "Add a title above the code? (e.g., filename)"
Options:
- No title (default)
- Yes, add title
If yes, ask for the title text.
Note: Do NOT ask about output path/filename. Save to the current working directory with a sensible filename (e.g., rayso-snippet.png, or based on the title if provided like fibonacci.png). Only use a different path if the user explicitly specifies one in their original request.
Step 4: Build the ray.so URL
CRITICAL: ALL parameters must be in the URL hash (after #), NOT in the query string.
Build the URL using shell commands:
# 1. Base64 encode the codeCODE_BASE64=$(echo-n'YOUR_CODE_HERE'| base64)# 2. URL encode the base64 stringCODE_ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$CODE_BASE64'))")# 3. Build the URL with ALL parameters in the hash# Format: https://ray.so/#param1=value1¶m2=value2&code=ENCODED_CODE# Do NOT include width parameter - let ray.so auto-size to fit contentURL="https://ray.so/#theme=THEME&padding=PADDING&background=BACKGROUND&darkMode=DARKMODE&language=LANGUAGE&code=${CODE_ENCODED}"# Add optional parameters if needed:# If lineNumbers: add "&lineNumbers=true" before &code=# If title: add "&title=URL_ENCODED_TITLE" before &code=
URL Hash Parameters:
Parameter
Values
Default
theme
Any theme from list
breeze
padding
16, 32, 64, 128
64
background
true, false
true
darkMode
true, false
true
language
Any language from list, or "auto"
auto
lineNumbers
true, false
false
title
URL-encoded string
(none)
width
Number (pixels)
auto
code
Base64-encoded, then URL-encoded
(required)
Note on width: Do NOT include the width parameter unless you specifically need a fixed width. Without it, ray.so auto-sizes the frame to fit the code content, avoiding unnecessary empty space.
Example URL construction:
# For code: for i in range(23):\n print(i)# Theme: midnight, Padding: 64, Dark mode: true, Background: true, Language: python, Title: test.pyCODE='for i in range(23):
print(i)'CODE_BASE64=$(echo-n"$CODE"| base64)CODE_ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$CODE_BASE64'))")TITLE_ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('test.py'))")URL="https://ray.so/#theme=midnight&padding=64&background=true&darkMode=true&language=python&title=${TITLE_ENCODED}&code=${CODE_ENCODED}"echo"$URL"
Step 5: Capture High-Quality Image with agent-browser
MUST use agent-browser (verified in Step 1). This approach uses the html-to-image library (same as ray.so's internal export) with high pixelRatio for crisp, sharp text rendering.
IMPORTANT: Always use a unique session name with --session to avoid stale session issues.
# Generate unique session nameSESSION="rayso-$(date +%s)"# 1. Set viewportagent-browser --session$SESSIONset viewport 1400900# 2. Open the URLagent-browser --session$SESSIONopen"$URL"# 3. Wait for the page to fully renderagent-browser --session$SESSIONwait--load networkidle
agent-browser --session$SESSIONwait3000# 4. Load html-to-image library (same library ray.so uses internally)agent-browser --session$SESSIONeval'new Promise((r,e)=>{const s=document.createElement("script");s.src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html-to-image.js";s.onload=r;s.onerror=e;document.head.appendChild(s)})'# 5. Capture at 4x resolution using html-to-image (produces crisp text)agent-browser --session$SESSIONeval'htmlToImage.toPng(document.querySelector("#frame > div"),{pixelRatio:4,skipAutoScale:true})'> /tmp/rayso-dataurl-$SESSION.txt
# 6. Close the browseragent-browser --session$SESSION close
# 7. Convert data URL to PNG fileDATAURL=$(cat /tmp/rayso-dataurl-$SESSION.txt |tr-d'"'|tr-d'\n')echo"$DATAURL"|sed's/data:image\/png;base64,//'| base64 -d> /path/to/output.png
# 8. Clean up temp filerm /tmp/rayso-dataurl-$SESSION.txt
Critical notes:
Uses html-to-image library which is what ray.so uses for its own export feature
pixelRatio: 4 produces high-DPI images with crisp, sharp text (4x native resolution)
The data URL is captured directly from the library, not from a screenshot
No ImageMagick required - pure browser-based rendering at high resolution
Output is correctly sized with no extra whitespace
Step 6: Confirm Output and STOP
Report the saved file location to the user. The task is complete - do not perform any additional checks, explorations, or verifications after the screenshot is saved.
Complete Example
User: "Create a code snippet image of this Python function"
deffibonacci(n):if n <=1:return n
return fibonacci(n-1)+ fibonacci(n-2)
βΊAccess to product documentation and roadmap tools (Jira, Notion, etc.)
βΊUnderstanding of product management frameworks (RICE, Jobs-to-be-Done, etc.)
βΊStakeholder contact information and communication channels
Time Estimate
30-60 minutes to see productivity improvements
Steps
1Install product management skill
2Start with user story generation for known feature
3Progress to competitive analysis: research 2-3 competitors
4Use for roadmap prioritization: apply RICE/ICE scoring
5Draft stakeholder communications and refine based on feedback
6Build template library for recurring PM tasks
7Share effective prompts with product team
Common Pitfalls
β Not validating competitive researchβverify facts before sharing
β Accepting user stories without involving engineering team
β Over-relying on frameworks without qualitative judgment
β Not customizing outputs to company culture and communication style
β Skipping stakeholder validation of generated requirements
Best Practices
β Do
+Validate research and competitive analysis with real data
+Collaborate with engineering when generating technical requirements
+Customize frameworks and templates to your company context
+Use skill for first drafts, refine with stakeholder input
+Document successful prompt patterns for PM tasks
+Combine AI efficiency with human judgment and intuition
β Don't
βDon't publish competitive analysis without fact-checking
βDon't finalize user stories without engineering review
βDon't make prioritization decisions solely on AI scoring
βDon't skip customer validation of generated requirements
βDon't ignore company-specific context and culture
π‘ Pro Tips
β Provide context: company goals, constraints, customer feedback
β Ask for alternatives: 'Show 3 ways to prioritize this roadmap'
β Request stakeholder-specific formatting: 'Executive summary vs. engineering spec'
β Use skill for 70% generation + 30% customization to company needs
When to Use This
β Use when
Use for user story writing, competitive research, roadmap prioritization, stakeholder communication, and PRD drafting. Best for reducing repetitive documentation and research work.
β Avoid when
Avoid for strategic product vision (requires deep customer empathy), pricing decisions (needs market and financial expertise), or when face-to-face customer discovery is more valuable than speed.
Learning Path
1Basic: user stories, feature specs, status updates