Skip to content

Add inflow extension#26600

Closed
xiaochunjimmy wants to merge 4 commits intoraycast:mainfrom
xiaochunjimmy:ext/inflow
Closed

Add inflow extension#26600
xiaochunjimmy wants to merge 4 commits intoraycast:mainfrom
xiaochunjimmy:ext/inflow

Conversation

@xiaochunjimmy
Copy link
Copy Markdown

@xiaochunjimmy xiaochunjimmy commented Mar 24, 2026

Description

InFlow is a Raycast extension that lets you transform selected text with AI — instantly and in place.

Select text in any macOS app, run a command, and the result is automatically written back or shown in a panel. No app switching. No copy and paste.

This extension leverages Raycast’s text selection and AI APIs alongside List, Detail, and HUD interface components to deliver interactive operations and feedback.

Use it to:

  • Improve writing across emails, documents, chat, and notes
  • Fixing grammar, rewriting, simplifying, structuring, summarizing, and translating existing content
  • Executing one-off AI commands or asking questions about selected text
  • Performing system-level text processing without breaking your current workflow

Screencast

InFlow.Demo.mp4

Checklist

- Initial Publish
- Initial commit
@raycastbot raycastbot added the new extension Label for PRs with new extensions label Mar 24, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

Congratulations on your new Raycast extension! 🚀

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

Once the PR is approved and merged, the extension will be available on our Store.

@xiaochunjimmy
Copy link
Copy Markdown
Author

While developing this extension, I encountered an issue regarding command icons. The Raycast Store requires 512px PNGs, which unnecessarily increases the extension's file size and renders poorly in the List view, appearing jagged and grainy.

Local SVGs provide excellent rendering quality, but trigger an npm run lint error. While I understand the main extension logo must be a PNG, could individual command icons support the SVG format?

@xiaochunjimmy xiaochunjimmy marked this pull request as ready for review March 25, 2026 14:59
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 25, 2026

Greptile Summary

This PR introduces the InFlow extension, an AI-powered text transformation tool that reads selected text from any macOS app, runs it through a configurable AI provider (Raycast AI, OpenAI, DeepSeek, Qwen, GLM, OpenRouter, or a custom OpenAI-compatible endpoint), and either pastes the result back inline or shows it in a preview panel. The core architecture is well-thought-out, with clean separation between input detection, AI orchestration, streaming output, and clipboard-based paste-and-verify logic.

A few Raycast store requirements need to be addressed before merging:

  • Custom localization logic (src/inflow-settings.tsx:104–106, src/core/languages.ts): The extension uses Intl.DateTimeFormat().resolvedOptions().locale to auto-detect the user's language. Raycast only supports US English and prohibits locale-based detection; the initial language should fall back to a static default (e.g., "English (US)") or be set via a Raycast preference field.
  • Missing .prettierrc: All Raycast extensions must include a .prettierrc with printWidth: 120 and singleQuote: false. No such file exists in this extension.
  • Non-standard eslint.config.js: The config manually wires @raycast/eslint-plugin without defineConfig from eslint/config and uses ESLint v8 instead of v9. The recommended pattern is import { defineConfig } from "eslint/config"; export default defineConfig([...raycast]);.
  • Overly broad Applications category: Applications is reserved for extensions wrapping standalone macOS apps (e.g., CleanShot X); Productivity alone is the correct category for an AI writing assistant.
  • ENABLE_DEBUG = true in src/core/logger.ts: Safe due to the NODE_ENV === "development" guard, but should be set to false before shipping.

Confidence Score: 3/5

  • Not ready to merge — a custom localization rule violation and missing .prettierrc need to be resolved before store submission.
  • The core logic is solid and well-structured, but there are several Raycast store policy requirements that aren't met: locale-based language detection violates the no-custom-localization rule, the .prettierrc is missing, the ESLint config doesn't follow the standard Raycast pattern, and the category list includes the imprecise Applications entry. These are blocking or near-blocking for store acceptance.
  • extensions/inflow/src/inflow-settings.tsx (locale detection), extensions/inflow/src/core/languages.ts (locale mapping function), extensions/inflow/eslint.config.js (non-standard ESLint setup), and the missing extensions/inflow/.prettierrc.

Important Files Changed

Filename Overview
extensions/inflow/package.json Extension manifest with commands, preferences, and metadata. Missing .prettierrc config; Applications category is broader than necessary for an AI writing assistant.
extensions/inflow/eslint.config.js Uses a hand-crafted ESLint flat config via CommonJS require without defineConfig from eslint/config and references @raycast/eslint-plugin directly rather than the recommended @raycast/eslint-config preset.
extensions/inflow/src/inflow-settings.tsx Main settings UI with provider/model/language configuration. Uses Intl.DateTimeFormat().resolvedOptions().locale for language auto-detection, which violates the Raycast custom localization policy.
extensions/inflow/src/core/ai.ts Central AI orchestration layer: builds system/user prompts, dispatches to Raycast AI or custom providers, strips reasoning/thinking tags from responses. Well-structured with clear separation of concerns.
extensions/inflow/src/core/providers.ts OpenAI-compatible provider implementation with sophisticated reasoning-control retry logic and model-specific caching. Streaming and non-streaming paths both handled correctly.
extensions/inflow/src/core/output.ts Paste-and-verify output layer using AppleScript and Clipboard API to detect editable areas. Robust abort/signal support and clear fallback to "not_editable" on errors.
extensions/inflow/src/core/logger.ts Debug logger that tree-shakes to no-ops in production builds. ENABLE_DEBUG is set to true, which is fine because IS_DEV also requires NODE_ENV === "development", but the intent is clearer with false as the default.
extensions/inflow/src/core/settings.ts Settings persistence layer using Raycast's encrypted LocalStorage. Clean separation between stored format (per-provider configs) and flat pipeline-facing AppSettings.
extensions/inflow/CHANGELOG.md Changelog present with {PR_MERGE_DATE} placeholder correctly at the top entry and descending version order. Meets the changelog requirement.
extensions/inflow/src/core/languages.ts Language list and locale-to-language mapping. The getDefaultLanguageFromEnv function implements the same locale-detection logic that the inflow-settings.tsx calls via Intl.DateTimeFormat(), which violates the Raycast custom localization rule.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/inflow/src/inflow-settings.tsx
Line: 102-107

Comment:
**Custom localization logic using system locale**

`Intl.DateTimeFormat().resolvedOptions().locale` reads the OS locale to auto-detect a default language. Raycast only supports US English and discourages locale-based detection in favor of the preferences API. The same pattern appears in `src/core/languages.ts` via `getDefaultLanguageFromEnv`.

Instead of detecting the locale at runtime, consider using a static default (e.g., `"English (US)"`) or exposing this choice as a proper Raycast preference field so the user makes an explicit selection without locale sniffing.

```suggestion
      setDefaultLanguage(
        normalizeStoredLanguageValue(settings.defaultLanguage || "") ||
          "English (US)",
      );
```

**Rule Used:** What: Do not implement custom localization logic i... ([source](https://app.greptile.com/review/custom-context?memory=78677f74-64f7-483b-b90d-9c33e2e049da))

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/inflow/eslint.config.js
Line: 1-35

Comment:
**Non-standard ESLint configuration pattern**

The current config manually wires `@raycast/eslint-plugin` and doesn't use `defineConfig` from `eslint/config`, which is the required pattern for Raycast extensions. It also uses `@raycast/eslint-plugin` directly instead of the high-level `@raycast/eslint-config` preset.

The standard Raycast pattern is:
```javascript
import { defineConfig } from "eslint/config";
import raycast from "@raycast/eslint-config";

export default defineConfig([...raycast]);
```
Upgrading to ESLint v9 and adopting this pattern would align the extension with the rest of the Raycast ecosystem.

**Rule Used:** What: In ESLint v9+, `defineConfig` is exported fr... ([source](https://app.greptile.com/review/custom-context?memory=ded2e079-95d0-44a7-80b5-83bbe04916f5))

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/inflow/package.json
Line: 10-15

Comment:
**`Applications` category is too broad for this extension**

`Applications` is described as "End-user apps and utilities (e.g., CleanShot X)," which fits extensions that wrap a standalone macOS application. InFlow is an AI writing-assistant utility; `Productivity` already covers this well and is the more specific match. Consider removing `Applications` from the `categories` array.

```suggestion
  "categories": [
    "Productivity"
  ],
```

**Rule Used:** What: Assign at least one predefined category to e... ([source](https://app.greptile.com/review/custom-context?memory=f49debbf-b6f6-4c0d-9b35-e1927815992b))

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/inflow/src/core/logger.ts
Line: 3

Comment:
**Debug switch left enabled**

`ENABLE_DEBUG = true` is fine for local development, but it's easy to accidentally ship a build with this enabled. Because `IS_DEV` also requires `NODE_ENV === "development"`, logs are suppressed in production builds — so there is no runtime impact. However, the comment `// --- DEV SWITCH ---` implies this should be toggled off before merging. Setting it to `false` makes the intent explicit and prevents accidental dev noise if the build environment ever changes.

```suggestion
const ENABLE_DEBUG = false;
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/inflow/package.json
Line: 170-175

Comment:
**Missing `.prettierrc` configuration file**

All Raycast extensions must ship with a `.prettierrc` file that sets `printWidth: 120` and `singleQuote: false`. No `.prettierrc` is present in this extension. Without it, formatter output may diverge from the Raycast standard.

Add `extensions/inflow/.prettierrc` with:
```json
{
  "printWidth": 120,
  "singleQuote": false
}
```

**Rule Used:** What: All extensions must use the standard Raycast... ([source](https://app.greptile.com/review/custom-context?memory=7be27780-7fcb-4602-9122-17c47fdd52ee))

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Add inflow extension" | Re-trigger Greptile

Comment thread extensions/inflow/src/inflow-settings.tsx Outdated
Comment thread extensions/inflow/eslint.config.js Outdated
Comment thread extensions/inflow/package.json
Comment thread extensions/inflow/src/core/logger.ts Outdated
Comment thread extensions/inflow/package.json Outdated
xiaochunjimmy and others added 3 commits March 25, 2026 23:28
Avoid overly broad issue

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Setting the logger to false explicitly states the intent and prevents accidental development noise if the build environment changes.

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@raycastbot
Copy link
Copy Markdown
Collaborator

This pull request has been automatically marked as stale because it did not have any recent activity.

It will be closed if no further activity occurs in the next 7 days to keep our backlog clean 😊

@raycastbot raycastbot added the status: stalled Stalled due inactivity label Apr 9, 2026
@xiaochunjimmy
Copy link
Copy Markdown
Author

I am not sure what I need to do next? I always thought I was waiting for the reviewer's review.

@raycastbot raycastbot removed the status: stalled Stalled due inactivity label Apr 9, 2026
@0xdhrv 0xdhrv self-assigned this Apr 14, 2026
Copy link
Copy Markdown
Contributor

@0xdhrv 0xdhrv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution @xiaochunjimmy 🔥

At a high level, this functionality appears to overlap with what can already be achieved using Raycast’s existing AI commands ↗. The core workflow invoking AI to process, transform, or generate content based on user input is already well-supported through built-in AI features, including custom AI commands and prompt-based interactions.

In particular:

  • The primary actions can be replicated using existing AI commands without additional setup complexity.
  • Supporting this separately would duplicate functionality that is already actively maintained and improved within Raycast AI.

If there are specific features, constraints, or workflows that are not currently possible with AI commands (for example, deeper integrations, automation, or domain-specific enhancements), it would be great to highlight those. That context can help determine whether this should extend existing capabilities rather than introduce parallel functionality.

This would help avoid duplication and keep related functionality consolidated in one place. As mentioned in our extension guidelines here ↗

@0xdhrv 0xdhrv marked this pull request as draft April 14, 2026 05:13
@xiaochunjimmy
Copy link
Copy Markdown
Author

@0xdhrv Thank you for your patient explanation. I understand this, as Raycast is a commercial product, and we should actively maintain its ecosystem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new extension Label for PRs with new extensions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants