Type a trigger like ?fix at the end of any text, in any app, and watch it get replaced with AI-enhanced content β instantly.
Note
SwiftSlate works everywhere β WhatsApp, Gmail, Twitter/X, Messages, Notes, Chrome, and every other app with a text field. No copy-pasting. No app switching. Just type and go.
- Quick Demo
- Features
- Built-in Commands
- Getting Started
- How It Works
- Custom Commands
- API Key Management
- App Screens
- Privacy & Security
- Tech Stack
- Building from Source
- Contributing
- License
π You type β "i dont no whats hapening ?fix"
β³ SwiftSlate β β β β β (processing...)
β
Result β "I don't know what's happening."
π You type β "hey can u send me that file ?formal"
β³ SwiftSlate β β β β β (processing...)
β
Result β "Could you please share the file at your earliest convenience?"
π You type β "Hello, how are you? ?translate:es"
β³ SwiftSlate β β β β β (processing...)
β
Result β "Hola, ΒΏcΓ³mo estΓ‘s?"
|
Integrates at the system level via Android's Accessibility Service. Works in any app β messaging, email, social media, notes, browsers, and more. Type, trigger, done. The AI response replaces your text directly in the same field β no copy-pasting, no app switching. A spinner ( Add multiple API keys for automatic round-robin rotation. If one key hits a rate limit, SwiftSlate seamlessly switches to the next. Pure black ( |
Ships with Google's Gemini API ( Create your own trigger β prompt pairs. Define API keys are encrypted with AES-256-GCM using the Android Keystore. Your keys never leave your device unencrypted. No analytics. No telemetry. No intermediary servers. Text is sent directly to the configured provider's API and only when a trigger is detected. |
SwiftSlate ships with 9 commands plus dynamic translation β ready to use out of the box:
| Trigger | Action | Example |
|---|---|---|
?fix |
Fix grammar, spelling & punctuation | i dont no whats hapening β I don't know what's happening. |
?improve |
Improve clarity and readability | The thing is not working good β The feature isn't functioning properly. |
?shorten |
Shorten while keeping meaning | I wanted to let you know that I will not be able to attend the meeting tomorrow β I can't attend tomorrow's meeting. |
?expand |
Expand with more detail | Meeting postponed β The meeting has been postponed to a later date. We will share the updated schedule soon. |
?formal |
Rewrite in professional tone | hey can u send me that file β Could you please share the file at your earliest convenience? |
?casual |
Rewrite in friendly tone | Please confirm your attendance at the event β Hey, you coming to the event? Let me know! |
?emoji |
Add relevant emojis | I love this new feature β I love this new feature! πβ€οΈβ¨ |
?reply |
Generate a contextual reply | Do you want to grab lunch tomorrow? β Sure, I'd love to! What time works for you? |
?undo |
Restore text from before the last replacement | Reverts to your original text before AI modified it |
?translate:XX |
Translate to any language | Hello, how are you? ?translate:es β Hola, ΒΏcΓ³mo estΓ‘s? |
π Supported language codes for translation
Use any standard language code with ?translate:XX:
| Code | Language | Code | Language | Code | Language |
|---|---|---|---|---|---|
es |
Spanish | fr |
French | de |
German |
ja |
Japanese | ko |
Korean | zh |
Chinese |
hi |
Hindi | ar |
Arabic | pt |
Portuguese |
it |
Italian | ru |
Russian | nl |
Dutch |
tr |
Turkish | pl |
Polish | sv |
Swedish |
β¦and many more. Any language code recognized by Google Translate works.
| Requirement | Details |
|---|---|
| Android Device | Android 6.0+ (API 23 or higher) |
| API Key | Free Gemini key at aistudio.google.com, or a key from any OpenAI-compatible provider |
Tip
The APK is only ~1.3 MB β lightweight with zero external dependencies for networking or JSON.
1. Download the latest APK from the Releases page
2. Install the APK on your device (allow installation from unknown sources if prompted)
3. Open SwiftSlate and follow the setup below
|
Step 1 π Add API Key Open the Keys tab, enter your API key. It's validated before saving. Add multiple keys for rotation. |
Step 2 βΏ Enable Service On the Dashboard, tap "Enable" β find "SwiftSlate Assistant" in Accessibility Settings β toggle it on. |
Step 3 βοΈ Start Typing! Open any app, type your text, add a trigger like |
flowchart TD
A["π You type: 'Hello wrld, how r u ?fix'"] --> B{"π Accessibility Service\ndetects trigger"}
B --> C["βοΈ Extracts text before trigger:\n'Hello wrld, how r u'"]
C --> D["π Selects next available\nAPI key (round-robin)"]
D --> E["π€ Sends text + prompt\nto AI provider"]
E --> F["β³ Shows inline spinner\nβ β β β"]
F --> G["β
Replaces text in-place:\n'Hello world, how are you?'"]
style A fill:#1a1a2e,stroke:#e94560,color:#fff
style B fill:#1a1a2e,stroke:#0f3460,color:#fff
style C fill:#1a1a2e,stroke:#0f3460,color:#fff
style D fill:#1a1a2e,stroke:#0f3460,color:#fff
style E fill:#1a1a2e,stroke:#0f3460,color:#fff
style F fill:#1a1a2e,stroke:#e94560,color:#fff
style G fill:#16213e,stroke:#00b894,color:#fff
π§ Technical deep-dive
- Event Listening β SwiftSlate registers an Accessibility Service that listens for
TYPE_VIEW_TEXT_CHANGEDevents across all apps - Fast Exit Optimization β For performance, it first checks if the last character of typed text matches any known trigger's last character before doing a full scan
- Longest Match β When a potential match is found, it searches for the longest matching trigger at the end of the text
- Text Extraction β The text before the trigger is extracted and paired with the command's prompt
- API Call β The text + prompt is sent to the configured AI provider using the next available key in the round-robin rotation
- Inline Spinner β While waiting for the response, a spinner animation (
β β β β) replaces the text to provide visual feedback - Text Replacement β The AI response replaces the original text using
ACTION_SET_TEXT - Fallback Strategy β If
ACTION_SET_TEXTfails (some apps don't support it), SwiftSlate falls back to a clipboard-based paste approach
Go beyond the built-ins β create your own trigger β prompt pairs in the Commands tab.
- Open the Commands screen
- Enter a Trigger (e.g.,
?poem) - Enter a Prompt β the instruction sent to the AI
- Tap "Add Command"
| Trigger | Prompt | Use Case |
|---|---|---|
?eli5 |
Explain this like I'm five years old and return ONLY the modified text. |
Simplify complex topics |
?bullet |
Convert this text into bullet points and return ONLY the modified text. |
Quick formatting |
?headline |
Rewrite this as a catchy headline and return ONLY the modified text. |
Social media posts |
?code |
Convert this description into pseudocode and return ONLY the modified text. |
Developer shorthand |
?tldr |
Summarize this text in one sentence and return ONLY the modified text. |
Quick summaries |
Important
Always include "return ONLY the modified text" in your prompt to ensure clean output without extra commentary from the AI.
SwiftSlate supports multiple API keys with intelligent rotation:
| Feature | Details |
|---|---|
| Round-Robin Rotation | Keys are used in turn to spread usage evenly across all configured keys |
| Rate-Limit Handling | If a key gets rate-limited (HTTP 429), SwiftSlate tracks the cooldown and skips it automatically |
| Invalid Key Detection | Keys returning 403 errors are marked invalid and excluded from rotation |
| Encrypted Storage | All keys encrypted with AES-256-GCM via Android Keystore before being saved locally |
Tip
Adding 2β3 API keys helps avoid rate limits during heavy use. Each API key has its own quota.
SwiftSlate has four screens accessible via the bottom navigation bar:
|
|
|
|
Note
SwiftSlate is built with privacy as a core architectural principle, not an afterthought.
| Concern | How SwiftSlate Handles It | |
|---|---|---|
| ποΈ | Text Monitoring | Only processes text when a trigger command is detected at the end. All other typing is completely ignored. |
| π‘ | Data Transmission | Text is sent only to the configured AI provider (Google Gemini or your custom endpoint). No other servers are ever contacted. |
| π | Key Storage | API keys are encrypted with AES-256-GCM using the Android Keystore system before being saved locally. |
| π | Analytics | None. Zero telemetry, zero tracking, zero crash reporting. |
| π | Open Source | The entire codebase is open for inspection under the MIT License. |
| π | Permissions | Only requires the Accessibility Service permission β nothing else. |
| Language | Kotlin 2.1 |
| UI | Jetpack Compose Β· Material 3 |
| Navigation | Navigation Compose |
| Async | Kotlin Coroutines |
| HTTP | HttpURLConnection (zero external dependencies) |
| JSON | org.json (Android built-in) |
| Storage | SharedPreferences (encrypted via Android Keystore) |
| Core Service | Android Accessibility Service |
| Build System | Gradle with Kotlin DSL |
| Java Target | JDK 17 |
| Min SDK | API 23 (Android 6.0) |
| Target SDK | API 36 |
Zero third-party dependencies for networking or JSON parsing β SwiftSlate uses only Android's built-in APIs.
- Android Studio (latest stable)
- JDK 17
- Android SDK with API level 36
# Clone the repository
git clone https://github.com/Musheer360/SwiftSlate.git
cd SwiftSlate
# Build debug APK
./gradlew assembleDebug
# Output: app/build/outputs/apk/debug/app-debug.apkπ¦ Signed release build
export KEYSTORE_FILE=/path/to/your/keystore.jks
export KEYSTORE_PASSWORD=your_keystore_password
export KEY_ALIAS=your_key_alias
export KEY_PASSWORD=your_key_password
./gradlew assembleReleaseContributions are welcome! Here's how to get involved:
# 1. Fork the repository, then:
git clone https://github.com/YOUR_USERNAME/SwiftSlate.git
cd SwiftSlate
# 2. Create a feature branch
git checkout -b feature/amazing-feature
# 3. Make your changes and commit
git commit -m "Add amazing feature"
# 4. Push and open a Pull Request
git push origin feature/amazing-feature- π§© New built-in commands
- π€ Additional AI provider integrations
- π¨ UI improvements and new themes
- π Localization / translations
- π Documentation improvements
This project is licensed under the MIT License β see the LICENSE file for details.
Made with β€οΈ by Musheer Alam
If SwiftSlate makes your typing life easier, consider giving it a β