Re: MCP is dead, long live the CLI! Plus, a skill for your SwiftUI animations
Hi everyone,
The world of AI is moving at breakneck speed. The Model Context Protocol (MCP) - a protocol for AI agents to interact with tools and services - was introduced just a few months ago, and it already seems to be replaced by none other than the trusty CLI. Not surprising, given most coding agents embrace the CLI as their primary tool for interaction. The UNIX philosophy - “Everything is a file” - seems to be alive and well in the age of AI. Who would have thought?
AI is changing the way we build software in fundamental ways, and we’re all trying to figure out what this means for us as software engineers. In this issue, I’ve collected a couple of articles that look at this from different angles. While some people seem to think that IT IS OVER and AI WILL CHANGE EVERYTHING, I think it’s more nuanced than that.
Like most other technological revolutions before it, AI will change the way we build software, but it will not replace software engineers. Instead, we will work on a different level of abstraction. This issue contains a bunch of articles that discuss those new engineering practices in depth.
Now is the time to get a head start and get ahead of the curve.
And - as proof that architectural decisions still matter, I’m including some articles that discuss Swift and SwiftUI architecture on two different levels of abstraction: modularization and data flow architecture.
In not entirely unrelated news, I contributed to the Swift Asynchronous Algorithms package. If you’re interested in learning more about this, and why it matters, come to my talk “Don’t call us - we’ll call you” at DeepDishSwift in Chicago (April 12th -14th). If you’ve seen this talk before at SwiftLeeds last year, you should still come - I’ve promised Josh that I will put a pizza-themed spin on it, and it’s going to be a lot of fun 🍕
Let me know what you think about the topics in this issue - just hit reply, I read all of your emails!
When working with asynchronous sequences, there are often cases where only the latest result of the most recent transformation is of interest. A typical example is a search-as-you-type interface, where you want to cancel the previous search request when the user types a new character. Here is how that might look like when using AsyncSequences:
let searchQueries = userInputField.textChanges// Without flatMapLatest - all requests complete, wasting resourcesfor await query in searchQueries { let results = try await searchAPI(query) displayResults(results) // May display stale results}
To avoid wasting resources or - even worse - displaying stale results, you’d ideally want to cancel the previous request when a new one comes in. This is exactly what flatMapLatest does:
let searchResults = searchQueries.flatMapLatest { query in searchAPI(query)}for await result in searchResults { displayResults(result) // Only latest results displayed}
I’m pleased to say that this has landed in the latest release of the swift-async-algorithms package! It still has to go through the evolution process, but you can try it out in your projects today using Swift Package Manager:
In any non-trivial app, you will inevitably reach the point where your code becomes too complex to manage in a single target. Modularization is a key step in managing the complexity of growing Swift applications. In this post, Kyle shares his experience and best practices for using SPM to create a more maintainable and scalable codebase. It is part of an entire series of articles on the topic, and I encourage you to read the entire series. As a sneak peek, Preview Apps for Lightning-Fast Iteration is a great article that anyone building SwiftUI apps should read.
How can you give your coding agent the ability to analyze the animations in your app? Well, you need to give it eyes - and that’s exactly what this skill does. It achieves this by using a set of primitives that get added to your app for instrumentation, and the skill itself that uses a combination of XcodeBuildMCP and the Simulator to capture the animations and analyze them. Great work by Edward (who used to be a designer on the Xcode IDE)!
Firebase is a layer of opinionated APIs on top of Google Cloud Platform - this is how we achieve the great developer experience we all know and love. This also means that Firebase doesn’t expose all the underlying Google Cloud features directly to developers. Frank demonstrates how to use the underlying Google Cloud features to get more insights into the usage of your app. In this case, how to count document reads per user in Firestore - something that I hear people ask for every now and then. Roll up your sleeves and get ready to dive into the Cloud Logs explorer and Logs analytics! These are some really powerful tools that give you a lot of insights into what’s happening in your app.
It highlights a scary vulnerability: “public” Firebase API keys - which are normally safe to embed in client apps - could theoretically be hijacked to access Google’s Gemini API, potentially racking up massive cloud bills.
If you are building with Firebase, here is what you need to know and why you don’t need to panic:
You’re already protected by default: In 2024, the Firebase team proactively took measures to lock down all existing auto-generated API keys. They are now automatically restricted so they can only be used with Firebase services, preventing them from being abused for things like the Gemini API. Unless you modified your API key settings, you should still be safe.
New projects are safe from day one: All new Firebase API keys generated today are also restricted by default to authorized Firebase services. This means you cannot use them to access the Gemini API, for example.
Watch out for manual keys: If you go into the Google Cloud Console and manually create a new API key for your project, it will NOT be restricted by default. You MUST ensure you lock it down. Best practice is to apply both Application restrictions (e.g., tying it to your specific iOS Bundle ID) and API restrictions (limiting it strictly to the APIs your app actually calls).
API keys don’t protect your data - App Check does: Remember that restricting API keys only protects against quota abuse. To actually protect your database, storage, and backend resources from abusive traffic or unauthorized clients, you should implement Firebase App Check. App Check helps ensure that incoming traffic is actually coming from your legitimate, untampered iOS app (via DeviceCheck/App Attest).
Eric makes the case that CLIs are superior to MCPs along most dimensions: they’re composable, they don’t need a special protocol, they work for humans and machines alike, and they don’t need any complex processes that need to start up and stay running.
So - let’s all build good APIs, and then create useful CLIs. The models will figure out how to use them.
Will AI make software engineers obsolete, and will all our jobs be made redundant? Miguel argues that this won’t be the case - instead, engineers and product managers alike will have to have a deeper understanding of the systems and become architects rather than bricklayers.
AI-assisted coding makes us more productive, but it also has negative effects, the most important one being cognitive debt: no longer understanding the code base.
Another issue that isn’t talked about enough is that we’re drying out the seniority pipeline. If you don’t learn what’s good code and good architecture (by writing code and having it challenged in code reviews), how can you grow and become a senior engineer?
How to write good AGENTS.md files? In short: keep them short.
Phil explains why brevity and clarity are key when providing context to your AI agents, and how to structure your AGENTS.md files for maximum effectiveness.
When adding AGENTS.md files, it’s tempting to add an overview of the project, but counter to what you might expect, this doesn’t really help the agents find relevant files in fewer steps.
Google released Gemini 3.1 Flash-Lite just a couple of days ago. It’s a highly efficient model designed for high-volume tasks that require low latency. Here is Patrick Loeber with a list of use cases for it.
I’ve tried it for a couple of tasks, and can confirm it is fast! If you need a model for translating or summarising text, this is a great choice.
Check out Patrick’s article for all the other use cases.
And here is another way you can expose Apple’s foundation models locally. This means you can use them in any AI tool that supports OpenAI-compatible endpoints.
Keep in mind that the token window constraints still remain - using AFM to power coding agents probably is not going to be a good experience.
This is a fun conversation with Chris Lattner, the creator of LLVM and Swift about Mojo.
You would think that, being a language designer, Chris’ original plan was to build a new language, but as he explains in the interview, that wasn’t the case. In fact, he and his co-founder decided to focus on the platform primitives first. Check out the interview to find out why they ended up building a new language anyway.
Programming a GPU is completely different from programming a CPU. Here is a fun, interactive way to learn this skill using Mojo, a language created by Chris Lattner of Swift and LLVM fame.