# thoughtbot/Argo: functional JSON parsing for Swift

> Argo is a Swift library that turns JSON into typed models using applicative operators instead of hand-written validation. It is small, MIT-licensed, and its last push was on 2020-05-22, which matters more than any feature list.

**thoughtbot/Argo** — GitHub describes it as Functional JSON parsing library for Swift. The repository metadata lists Swift as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.

- Repository: https://github.com/thoughtbot/Argo
- Website: https://thoughtbot.com
- Stars: 3,468 · Forks: 193
- Language: Swift
- License: MIT
- Published: 2026-08-13 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/thoughtbot-argo

## The problem Argo solves for Swift model layers

Every app that talks to an HTTP API eventually writes the same code: pull a value out of a dictionary, check it is the type you expected, check it is not missing, and fail with something a human can read when it is not. Argo's README states the goal directly: it lets you extract models from JSON "in a way that's concise, type-safe, and easy to extend," and that you "won't need to write validation code to ensure that incoming data is of the right type." The Swift type system carries that burden instead, and failures come back as explicit states rather than as nil or a crash.

The audience is narrow and specific. This is a library for Swift application developers, mostly iOS, who are comfortable with functional idioms and who were writing Swift before Codable existed. The README's own compatibility table shows the era it targets: Swift 4.X maps to master, Swift 3.X to Argo 4.X, and everything older to a lower major version. If your project is on Swift 4 or earlier and you want decoding expressed as composition rather than as imperative unwrapping, Argo is aimed at you.

## How the Decodable protocol and applicative operators fit together

The mechanism has three parts. First, a type conforms to Decodable by implementing a static decode function that takes a JSON value and returns Decoded of that type. Second, the JSON value exposes subscript-like operators that pull a field out by key. Third, those pulled values are combined with applicative operators so that the constructor is applied only if every argument succeeded.

The README's User example shows all three at once. A single expression starts from a curried initializer and threads each field through with <^> and <*>. The operators carry meaning: <| parses a required field, <|? parses an optional one, and <|| parses an array. Nested objects are addressed by passing an array of keys, as in json <| ["company", "name"], so you do not write an intermediate struct just to reach into a sub-object.

The design consequence is that error reporting is structural. Because the whole expression is a single Decoded value, a missing required field or a type mismatch surfaces as a failure of that value rather than as a thrown exception partway through a decoding routine. That is the trade-off: you get composability and precise failure states, and you pay for it by accepting operator-heavy syntax that reads poorly to anyone who has not internalized the operators.

## Installing Argo with Carthage, CocoaPods or SwiftPM

The README documents three installation routes plus git submodules. Carthage is listed first. Add the dependency line to your Cartfile, run the update command, and then link the built frameworks into your app. The README adds a detail that trips people up: newer Argo versions require linking both Argo.framework and Runes.framework.

```bash
github "thoughtbot/Argo"
```

After adding that line, run carthage update. The README states you should then follow Carthage's own README for adding frameworks to an application, and warns against pointing at master because the project pushes master forward with new Swift releases.

CocoaPods is the second route. The Podfile needs the pod plus the frameworks opt-in, and the README specifies CocoaPods 0.36 or newer for pod install.

```ruby
use_frameworks!
pod 'Argo'
```

The repository also ships Package.swift and versioned manifests named Package@swift-3.1.swift, Package@swift-4.swift, Package@swift-4.2.swift and Package@swift-5.swift, which indicates Swift Package Manager support gated by toolchain version. The README does not give SwiftPM instructions; the manifests are the evidence, and you should read the one matching your toolchain before relying on it.

For a first real use, the README's usage example is the starting point. It requires an external module named Curry for the curry function and imports Runes, which the README notes is a dependency in newer versions.

```swift
import Argo
import Curry
import Runes

extension User: Decodable {
  static func decode(_ json: JSON) -> Decoded<User> {
    return curry(User.init)
      <^> json <| "id"
      <*> json <| "name"
      <*> json <|? "email"
  }
}
```

The reader should expect the decode call to return a Decoded<User> value, not a User. Whether that value carries a success or a failure is what you inspect next.

## Where Argo stops being the right tool

The most concrete limitation is age. The last push to the repository was on 2020-05-22, and the newest release is v5.0.0 from the same date, labelled "5.0: Swift Compatibility." Nothing in the repository's visible history indicates activity since then. A library whose newest release exists to track a Swift version that is now several major versions old is a library you adopt with the expectation of maintaining it yourself.

The second limitation is scope. Argo decodes. It does not encode, it does not generate code, and the README does not document rollback, migration tooling or a deprecation path toward Codable. If your model layer needs round-tripping or you want the compiler to synthesize conformance, Argo gives you none of that.

The third is the dependency surface. The README's own example imports Curry and Runes, and the installation notes require linking Runes.framework alongside Argo.framework for newer versions. That is two extra libraries to pin and audit for a decoding layer. If your project is small, or if you are starting fresh on a modern Swift toolchain, Codable plus a handful of CodingKeys does the same job with no third-party code at all.

## Argo against Codable in the Swift standard library

The real alternative is not another parsing library; it is Codable, which ships with Swift. The difference is in how the two express the same work.

Codable moves decoding into the type system at compile time. You declare conformance, the compiler synthesizes init(from:) where the property names and JSON keys line up, and you write CodingKeys or a custom initializer only where they do not. There is no operator vocabulary to learn and no separate JSON value type to pass around.

Argo keeps decoding in ordinary functions. decode(_:) is a static function you write, JSON is a value you inspect, and composition happens through operators. That buys flexibility Codable does not offer as directly: pulling a value from a nested path in one expression, mixing required and optional fields in a single chain, and producing a Decoded value whose failure case you can pattern-match rather than catch.

The trade-off is legibility and longevity. Codable's syntax is familiar to anyone who has written Swift in the last several years, and it is maintained by the Swift project. Argo's syntax requires knowing what <^>, <*>, <|, <|? and <|| do, and the library that defines them has not been pushed to since 2020-05-22. For a codebase already built on Runes and Curry, that vocabulary is probably already paid for. For a new one, it is a cost with no matching benefit.

## Licence and what upgrading costs

Argo is released under the MIT licence, and the README states the project is copyright (c) 2015 thoughtbot, inc., free software, redistributable under the terms in the LICENSE file. MIT is permissive: it allows commercial and closed-source use, and it requires that the copyright notice and licence text be preserved. That is the whole of the licence implication here; the LICENSE file at the repository root is the authoritative text and anything beyond reading it is a question for your own counsel.

The upgrade cost is the part worth thinking about before adoption. The README's compatibility table is a hard mapping, not a range. Swift 3.X corresponds to Argo 4.X, Swift 2.2 and 2.3 to 3.X, and so on down to 0.3.X for Swift 1.1. Moving your toolchain forward means moving your Argo major version, and each of those steps is a source-level change to your decode functions. The repository ships four versioned Package manifests, which suggests the project handled that churn by keeping parallel manifests rather than by maintaining a single one across toolchains.

There is also a warning in the README that is easy to skim past: the project is "aggressive about pushing master forward along with new versions of Swift" and recommends against pointing at master, using tagged releases instead. Combined with a last push of 2020-05-22, that advice now cuts the other way. Pinning to a release protects you from churn that is no longer happening, and it also means no fixes arrive unless you make them.

## Deciding whether to bring Argo into a codebase

The decision comes down to what you already have. If your project is on Swift 4.x, already depends on Runes and Curry, and has decode functions written in the operator style the README demonstrates, Argo is doing exactly what you asked of it and there is no migration emergency. If you are starting a project today, the same README that documents the library also documents its ceiling: a compatibility table that stops at Swift 4.X and a release whose stated purpose is Swift compatibility.

What to verify before you commit, concretely. Check the compatibility table against your toolchain. Read Package@swift-5.swift to see whether the manifest resolves under your SwiftPM version, since the README gives no SwiftPM instructions of its own. Confirm that your Cartfile or Podfile will pull Runes as well, because the README requires linking Runes.framework alongside Argo.framework for newer versions. And decide now whether you are prepared to vendor the source, because the last push was on 2020-05-22 and there is no signal in the repository that another release is coming.

## Conclusion

Adopt Argo if you maintain a Swift 4.x codebase that already depends on Runes and Curry and you want decode logic expressed as operator chains rather than Codable boilerplate. Do not adopt it for a new project on a current Swift toolchain, and do not adopt it if you need a library that receives fixes. Before committing, verify that the Swift version in the compatibility table matches your toolchain, that the Package@swift-5.swift manifest resolves under your SwiftPM version, and that you are willing to vendor the source if upstream stays quiet.

## FAQ

### What is thoughtbot/Argo used for?

It is a Swift library for extracting typed models from JSON or similar structures. It uses Swift's type system so you do not write validation code for field types or missing required fields, and it returns explicit failure states instead.

### Is thoughtbot/Argo a CI/CD tool?

No. thoughtbot/Argo is a functional JSON parsing library for Swift. CI/CD is the domain of the unrelated Argo project for Kubernetes, which this repository does not cover.

### What is the thoughtbot/Argo project?

It is an MIT-licensed Swift JSON parsing library from thoughtbot, inc. Its README says it is named after the Greek word for swift and after the ship of Jason, and that it was inspired by Aeson, the JSON parsing library in Haskell.

### Does thoughtbot/Argo work with Kubernetes?

No. This repository is a Swift library for decoding JSON into models and has nothing to do with Kubernetes. Searches for Argo and Kubernetes refer to a different project.

## Sources

- [Official documentation](https://thoughtbot.com)
- [Official README](https://github.com/thoughtbot/Argo#readme)
- [Project repository](https://github.com/thoughtbot/Argo)
- [Release notes](https://github.com/thoughtbot/Argo/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/thoughtbot-argo
