Cascade is a powerful reasoning engine capable of deep, multi-step deliberation, equipped to both edit and explain. This is the definition of Windsurf's Cascade feature, and it can be toggled using Command
+ L
in the editor.
In the previous post, I provided a glimpse of how this agentic IDE works:
In this post, I will create a new feature for my app Whispering using Cascade and Groq's API for transcription. This way, people who still use Intel machines or prefer extremely fast transcription can utilize it instead of on-device.
Running macOS App via Windsurf
As I mentioned before, I am adamant that I want to run the project via xcodebuild
only in the chat window. I started with the prompt:
Run the project using xcodebuild and xcrun
And it provided me with the command to build the project:
xcodebuild -scheme Whispering -configuration Debug -destination platform=macOS
The build succeeded, it proceeded to launch the built app from the Debug directory:
$ xcrun launch-app /Users/rudrankriyam/Library/Developer/Xcode/DerivedData/Whispering-fxqsevpvezgelucnqetechkyhroh/Build/Products/Debug/Whispering.app
However, there was an error:
xcrun: error: sh -c '/Applications/Xcode-beta.app/Contents/Developer/usr/bin/xcodebuild -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -find launch-app 2> /dev/null' failed with exit code 17664: (null) (errno=No such file or directory)
xcrun: error: unable to find utility "launch-app", not a developer tool or in PATH
Unfortunately, it still insisted that it initiated the launch of the Whispering app. I copied the error from above, and here is the following response:
I apologize for the error. Let's try running the app directly using the open command instead, which is the standard way to launch macOS applications.
$ open /Users/rudrankriyam/Library/Developer/Xcode/DerivedData/Whispering-fxqsevpvezgelucnqetechkyhroh/Build/Products/Debug/Whispering.app
It looks like I got ahead of myself. I did not know that open
command is the standard way to launch macOS apps.
Windsurf 1:0 Rudrank.
The best part about accessing the terminal inside the chat itself is that you can provide it with the additional prompt:
Build the project using xcodebuild every time you make changes, and fix any issues or errors if there any.
Accessing External Documentation
As of writing this post, Windsurf cannot access the internet. It is one of the most requested features. Looking at their feature request page:
I will use my favorite service that I found this year, Firecrawl, which turns websites into LLM-ready data. I provided it with the documentation for transcription from Groq and gave Cascade the following prompt:
----
Update the @TranscriptionService.swift with methods for transcription with the given audio file. Use latest async/await Swift syntax and use a keychain library to fetch the API key.
It updated the TranscriptionService.swift
file to implement transcription using the Groq API. Then, it added the popular KeychainAccess
library for secure API key storage and updated the Package.swift
file:
swift package update
It added almost perfect code for the implementation:
// MARK: - Groq API Constants
private enum GroqAPI {
static let baseURL = "https://api.groq.com/openai/v1/audio/transcriptions"
static let keychainService = "com.whispering.apikeys"
static let keychainKey = "groq_api_key"
}
// MARK: - Transcription Models
enum TranscriptionModel: String {
case whisperLargeV3 = "whisper-large-v3"
case whisperLargeV3Turbo = "whisper-large-v3-turbo"
case distilWhisperLargeV3En = "distil-whisper-large-v3-en"
}
enum TranscriptionMode {
case offline
case online
}
// MARK: - Transcription Response
struct TranscriptionResponse: Decodable {
let text: String
}
@MainActor
class TranscriptionService: ObservableObject {
// MARK: - Published Properties
@Published var selectedTranscriptionModel: TranscriptionModel = .whisperLargeV3Turbo
@Published var transcriptionMode: TranscriptionMode = .offline
private let keychain = Keychain(service: GroqAPI.keychainService)
But, it ended up updating the method that is used for offline transcription. So, I had to ask it again:
Create another method. The current transcribe method is for offline.
So, as you know, it was my poor prompting skill in this case. Or Elden Ring fans like to call it a skill issue.
Updating the View to Add API Key
The next step is to create a UI in the Settings window that can hold the API key and also verify it.
I LOVE reading through how it follows the instructions. Here is a part of it:
- I'll help you create a settings window with UI elements to manage and verify the API key. First, let me check the existing codebase structure.
- Let me check what's in the Views directory since that's where we'll likely want to add our Settings view.
- I see there's already a
SettingsView.swift
file. Let me check its current contents to see how we can modify it to add the API key management functionality. - Let me also check the
TranscriptionService
to understand how the API key is currently being used. - Great! I see that the app is already using
KeychainAccess
for storing the API key securely. I'll now modify theSettingsView
to add API key management functionality. I'll add:- A section for API key management
- A secure text field for entering the API key
- A verify button to test the API key
- Proper error handling and success feedback
Then, it made the necessary changes.
The API key is now stored securely in the Keychain and can be verified against the Groq API. When verifying, we check the API response status code:
- 401: Invalid API key
- 200/400: Valid API key (400 is acceptable as we're not sending audio data)
- Other codes: Treated as verification failures
The UI provides clear feedback about the status of operations through color-coded messages (green for success, red for errors) and a loading indicator during verification.
After successfully building the project and adding the API key, it was verified successfully!
Toggle to Switch Between Offline
The next step is to add a toggle between API transcription and offline. I can start a new conversation by pressing Shift
+ Command
+ L
.
Cascade does some analysis and provides the following output:
I'll add a toggle in the menu bar to switch between API and offline transcription. I'll make the following changes:
Add a toggle in the ContentView
Ensure the TranscriptionService properly handles the mode switch
And with that, I have an API feature for those who want blazing-fast speed!
Moving Forward
While I can feel the friction of waiting for the flow of Cascade while it generates and analyses files, I hope it gets faster as Claude releases a faster model in the future.
One tip I got from Ronak is that if speed is the primary concern, explore switching the model from Sonnet to Cascade Base. It won't be as methodical of an agent, but it should be much faster!
Happy windsurfing!