raycast

Activity

Stars and mentions · Last 30 days, Oct 7 – Nov 5

GitHub stars63
Mentions13
02468Oct 7Oct 21Nov 5
UTC days · repositories raycast owns2 repositories

Top repositories

raycast’s repositories ranked by pull request authors, as on trending.

Loading

Contributes to

Repositories outside raycast’s account where raycast opened or reviewed pull requests in the past 365 days.

Who noticed raycast

Everyone who starred or forked raycast’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

12posts
Nov 60 posts
  1. I submitted a side-project extension for review and an AI bot found 4 real security bugs in it I built a small Raycast extension - paste invoice JSON, get a formatted HTML/Markdown preview. Zero dependencies in the render logic, 7 unit tests passing, tsc clean. I was pretty confident in it before opening the PR to the official extensions repo. Within a few minutes, an automated reviewer (Greptile, which Raycast runs on every incoming PR) left 9 comments. Four were tagged P1/security. None of them were things my tests caught, because I'd only tested the happy path and a couple of "normal" edge cases - not actually hostile input. 1. Unescaped field reaching an HTML template // before export function computeTotals(data: InvoiceData) { const subtotal = data.items.reduce((acc, i) => acc + i.qty * i.rate, 0); const taxRate = data.tax_rate || 0; ... } tax_rate is typed as number, but nothing enforces that at runtime - it comes from JSON.parse on whatever the user pastes. Paste "tax_rate": "0\"><script>alert(1)</script>" and it reaches the HTML template unescaped, because I was escaping the fields I "knew" were strings and trusting the type annotation for the one I assumed was always a number. 2. Markdown injection as a tracking pixel The extension also renders a Markdown preview (notes field goes straight into a Raycast Detail view, which renders Markdown). A notes value like ![x](https://attacker.example/pixel) turns into an image markdown tag that fires a real HTTP request to whatever URL the attacker put there, the moment you preview the invoice. I was escaping HTML special characters everywhere, but Markdown has its own special-character set (` * _ { } [ ] ( ) # + . ! | < > - ``) and I hadn't touched it. 3. A crash from a null in an array {"items": [null]} passed my one type-level guard (Array.isArray(data.items) && data.items.length > 0) and then blew up inside computeTotals when it tried to read .qty off null. A single bad row in pasted JSON took down the whole preview instead of just that row. 4. Silent data loss on save // before const file = path.join(dir, `${(data.invoice_number || "invoice").replace(/[^a-z0-9-_]/gi, "_")}.html`); fs.writeFileSync(file, html, "utf8"); Two invoices with numbers like INV/001 and INV:001 both sanitize to the same filename. Saving the second one silently overwrote the first, no warning, no prompt. The fixes themselves were small - a sanitizeItems() pass that coerces and filters before anything touches the renderer, an escapeMarkdown() sibling to the HTML escaper, a collision check before writeFileSync, a try/catch around the save with a failure toast. Maybe 40 lines total. The gap wasn't skill, it was that every one of my own tests handed the function well-formed data. I was testing that the code did what I designed it to do, not what happens when someone hands it something I didn't design for. The honest takeaway for me: unit tests you write yourself tend to probe the shape of input you were already imagining. The useful adversarial cases - malformed JSON, type coercion through JSON.parse, markdown/HTML injection via a "just text" field - are exactly the ones that don't occur to you while you're writing the happy-path version, because if they occurred to you, you'd have handled them already. That's the actual value of someone (or something) else hitting your code with the specific intent of breaking it before real users do it by accident. The PR (raycast/extensions#32665) also caught a quieter non-security issue the second time around: after I fixed the four bugs above, the new test I added for the null-items case had its @ts-expect-error comment in the wrong spot, which silently made the type checker pass when it should have failed. Small reminder that regression tests for a bug need their own review too - a test that compiles for the wrong reason is worse than no test, because it looks green. Source (render logic + tests): kleogeos/freelance-invoice-preview

    1 comment
  2. Reddit · · r/raycastapp · u/chrismessina · raycast/extensions

    How Raycast's Review Loop Leaks Extensions (and how to fix it) preview.redd.it Soooo... I've been digging into what happens to PRs on raycast/extensions between "Open PR" and "Merged". I put my findings on one page. As an author of 18 original extensions and contributor to 23 others, I feel like I have earned knowledge of this loop. tl:dr; PRs to the Store more than doubled between 2024 and 2026, basically when coding agents went mainstream. PRs to existing extensions still merge quickly and reliably. New extensions are a different story. In 2024-Q1, 57% of new-extension submissions merged; in 2026-Q1, 37% did. In 2026-Q2, the stale bot closed 43% of them, up from 16%. Most of those weren't abandoned outright. In about 2 of 3, a maintainer had already replied, and most of those contributors had responded to earlier review comments (usually Greptile's). Then the next round of review came and the author ghosted. Another 1 in 6 submissions sat as drafts that were never marked ready, so they never entered the review queue at all. The page covers PR volume, outcomes, review wait times, what Greptile flags (about a quarter of its comments are mechanical things a local script could catch), likely duplicates, and download distribution across the Store. It also has a short list of extensions that were built and reviewed but died in the loop. Every number comes from GitHub's API for all 15,078 PRs opened since January 2024, plus the Store's public listing data. The scripts and data are in the repo if anyone wants to check my work or run it again: chrismessina/raycast-loop These aren't complaints but instead a set of observations with receipts. The queue has been managed heroically by u/pernielsentikaer, u/0xdhrv, and their lizard robot as volume doubled. My goal is to find the cheapest changes that would help the most contributors get through the process. And I'd love feedback, especially where I've misread how the process works internally. Five changes, ordered by cost-benefit: 1. Put Greptile's rules in the repo. Use a .greptile/ folder, and ship the deterministic rules as a local check, so contributors and their agents can fix those issues before the first push. 2. Replace the PR template checklist with checks. Let CI verify what a script can. Keep only what the contributor knows, such as whether they searched the Store and which platforms they tested on. Add a "needs Windows tester" label for PRs the author couldn't test on Windows. 3. Make the draft step impossible to miss. Add a raycastbot nudge on quiet drafts, a line in ray publish output, and no automatic Greptile reviews on drafts (#32497). 4. Steer duplicates before they're built. Show matching Store extensions when someone starts a new extension, and have a bot propose how to contribute to the existing one first. 5. Pause the stale clock while a PR waits on Raycast. Apply an `awaiting review` label when the contributor pushes after review, so slow review weeks don't close PRs whose authors did their part.

    6 points · 2 comments
  3. @Nomandsign Yes, everything runs locally using Apple's Vision and NaturalLanguage frameworks. You can check out the implementation here: OCR, face detection, and name detection: github.com/raycast/extensions/blob/d0a2e9870ac64d… Pattern matching and redaction: github.com/raycast/extensions/blob/d0a2e9870ac64d… Would love to hear what you've been experimenting with!

    3 likes · 15 views
  4. crt name sort subdomains by oldest, newest, or a to z and copy all subdomains grabs the whole list, one per line, even the ones hidden by your filter or past the first 100 rows extensions#32231

    5 likes · 67 views
  5. agent browser new manage sessions command. see your active browser sessions, open a url in one, copy its name, or close it (with a confirm) it never reads cookies or saved logins extensions#32232

    6 likes · 104 views
  6. @j3rah_ @RevenueCat @raycast extensions#32198 had to add it now ;)

    2 likes · 9 views
  7. making a raycast extension for fsearch. full disk search right in raycast. 100 results in 12ms. extensions#32162 t.co

    24 likes · 923 views

Achievements

Awards earned by the repositories raycast owns. Select an award to embed its badge.

No awards yet

Repositories earn awards by reaching the top three in a completed trending day or week.

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.