anytype-swift: the official iOS client for a local-first workspace
Official Anytype client for iOS
At a glance
- What is it?
- This repository is the iOS application for Anytype, a workspace where documents, chats, tasks and databases all live on the device and sync peer to peer. What is interesting about it as a project is the build: the application is not self-contained, because the part that talks to the network and to the cryptography is a separate component written in another language, and the two are stitched together with generated protocol bindings and a set of make targets.
- Who is it for?
- anytype-swift fits an iOS developer who wants to work on the official client of a local-first application, or on an application that shares the same middleware. It does not fit somebody who wants a self-contained library.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the client is
This is the official client for iOS of a workspace application whose pitch is that your conversations, documents, notes, files and databases live together in one private application, that everything is end to end encrypted, that it works offline first, and that it is always yours.
The repository's topic tags are the vocabulary of that pitch, and they are the four ideas the whole product is built on: encryption from end to end, local first, offline first, and peer to peer. The last two are not the same thing, and a local-first application can still be offline-capable only by accident, whereas an offline-first one is designed so that the network is an optimisation rather than a dependency.
The screenshot gallery is a sequence rather than a set, and the order is the argument. The first one is captioned with a phrase about life without the cloud, and then come spaces, chats, pages, lists, and the organisation screen. So the story the screenshots tell is: here is the app with no network at all, and here is what you can build in it once the network is optional.
The distribution is the usual one for a company with a consumer product: a listing on the app store, a marketing site, and a link to the licence file.
And the licence badge is worth noticing, because it is not one of the standard open source licences. The project is under a source-available licence with a custom name, and the readme says so explicitly at the end. For a company that wants the code readable and the community welcome without handing the code to a competitor, that is a coherent position, and stating it plainly in the readme rather than burying it is the right thing to do.
The company behind it is described as a Swiss association rather than a corporation, which is the same choice made by several other European cooperatives in this space. The development branch is the default one, and the project publishes no tagged releases, which is normal for an application that is shipped through the app store rather than as a package.
The product model, in two named features
The feature list is a bit unusual for an application readme, because it leads with two features that have names and then lists the rest as capabilities.
The first named feature is chats, and its point is that you can create notes, documents or tasks directly from a chat window, start group conversations with colleagues or family, and plan ideas without leaving the conversation. The second is spaces, which are the organisational unit: projects, teams, family or personal areas, each holding documents, lists and databases, with clear boundaries so that secure notes stay separate from shared work.
So the product model is a workspace where a chat, a document, a task and a database row are all the same kind of thing, and the two features that get their own sections are the two that make that work in practice. A chat that can produce a document, and a space that can hold a conversation, are what turn a notes application into a workspace.
The rest of the list is the standard vocabulary of a block-based editor with structured data. You can create pages and notes from quick memos to long documents with media. You edit with blocks, so text, tasks and embeds share a page. You define custom content types, which is how you get entities like a curriculum vitae or a research record rather than only pages. You can publish to the web. You manage lists and tasks. You add properties, with some predefined ones such as tag, status and assignee, and you can create your own fields. You sort and filter, with custom views. You use templates, so that a block of text or a list of bullets can be reused. And you save bookmarks.
The property and type system is what makes the database part of the same application as the notes part. A page can have a type, a type can have properties, and a view is a query over the properties of the pages of that type. So the list view, the board view and the table view are not separate features bolted on; they are a consequence of the data model, which is why the feature list can be as short as it is.
Five promises, and what each one asks of the code
The section explaining why the application exists lists five things, and they are worth reading as a set of engineering constraints rather than as marketing.
The first is privacy by design, which the readme states as only you hold the key to your data. That is a specific claim with a specific consequence. If only the user holds the key, then the server cannot read the data, which means the server cannot index it, cannot search it, and cannot implement a recovery feature that requires reading. Those are real product limitations, and a design that takes the claim seriously gives them up.
The second is that it is yours forever, with everything stored on the device and always accessible. The storage claim is the one that matters, and it is what makes the sync story possible: if the data is on the device, syncing is a replication problem rather than a delegation problem, and the device is the source of truth rather than a cache of the server's.
The third is sync that picks up where you left off across devices, The fourth is offline first, which means the application is usable anywhere with no internet required. And the fifth is open code, with an invitation to explore and contribute at the organisation's repository.
That fifth one deserves a qualifier, because the licence is source-available rather than open source. That is a meaningful distinction in practice: you can read the code, you can build it, you can contribute to it, and the licence still carries its own terms. A reader who assumes the badge means an open source licence will be wrong, and the readme does not pretend otherwise.
The combination of local storage, end to end encryption and peer to peer sync is the design that makes the first four claims true at once, and it is also the design that makes the harder problems. Where two devices have edited the same object, somebody has to resolve the conflict, and with no server holding a canonical copy, that resolution has to happen on the clients. That is the hard part of the architecture, and it is why the middleware component exists at all.
Building it, and the middleware you cannot skip
The build section is where this project becomes interesting, because the application is not a self-contained Swift program.
The requirements are a specific version of the development tool and the package manager. And then there is the middleware, which is a separate repository written in another language, and which the readme says is required for a successful build. The client is the interface; the middleware is the part that does the cryptography, the network and the storage.
There are two ways to get it, and the first is the quick one. A prebuilt artefact is downloaded from a package registry, and to do that you need a personal access token with read access to packages, which the readme explains how to create, with a link to the documentation of the package registry. Then a make target asks for that token, runs a download script, and regenerates the bindings. A second target changes the token later, which is the step you need the day the token expires.
The second way is to build it yourself, and the readme gives the layout as a directory tree, because the build expects the two repositories to be siblings.
Parent Directory/
├── anytype-heart/
└── anytype-swift/That arrangement is not incidental. The local setup target deletes the middleware directory inside the dependencies, recreates it, and copies the built distribution into it, so the two repositories have to sit next to each other on disk.
So the make file has four related targets for the middleware: one to build the middleware in the sibling checkout, one to install the built copy into the dependencies directory, one that does both, and one that does the download instead. And the make file has a warning printed in bold at the top of the relevant targets, telling you that if you hit problems with the generated code you should run the environment setup target.
And there is a target for updating the middleware version, which either changes the version in a file at the root of the repository or takes it as an argument, with an example version in the readme. So the middleware version is pinned in a single place, and bumping it is one command.
Which is the whole build story in miniature: a Swift application that depends on a Go component, pinned in one file, fetched or built locally, and stitched together with generated code.
The code generation machinery
The make file's middle section is a description of the code generation pipeline, and it is the part of the repository that tells you how the two languages talk to each other.
The middleware generation target runs four steps. First a script in the protocol messages module, which is the standard code generator for the interface definitions. Then a tool with a configuration file, which is a source-to-source rewriter for the same module. Then a separate code generation binary of the project's own, invoked with a configuration file, a project directory and an output directory, which is how the Swift bindings are produced from the protocol definitions. And finally another tool with its own configuration for the services module.
Then there is a second generation target for the client itself, which runs a different rewriter against the core module and three shell scripts, one each for the assets, the localisation and the design system. And a comment in the make file notes that there is also code generation in the build phases of the main target and of the widget, so the generation happens in two places.
That duplication is worth a moment, because it is a common arrangement and a common source of confusion. Running the make target is what you do when the inputs change; the build phases are what guarantee that a developer who opens the project in the development environment gets the same generated files without having to know the make targets exist.
And the pipeline explains the shape of the repository. There is a directory for the protocol message definitions with their own scripts, a directory for the services, one for the assets, one for the localisation, one for the design system, and a directory of tools containing the code generation binary. Every one of those is a place where generated code lands, and the make file is the map of which generator writes into which place.
The localisation generator is worth singling out, because it explains the localisation configuration file at the root of the repository. The application is translated through a hosted translation service, the configuration says which languages and where the strings live, and the generator turns the downloaded translations into Swift source. A build step that depends on a translation platform is unusual, and it means the strings are maintained in a place where translators can work rather than in the code.
The repository, and the parts that are not code
The top level of the repository is an application project with several targets and a set of directories that are not source code at all.
There is the main application directory, and then three extensions: a notification service extension, a share extension, and a widget. The widget is the home screen one, and the share extension is what makes the application appear in the system share sheet, which is a detail that decides whether the application can receive a link or a photograph from another application. Those three targets are the difference between an application and an application that is part of the system.
Then there is the modules directory with the parts described above, a tools directory, a scripts directory, a distribution directory, and a build script for the local development environment. There is a file at the root that pins the middleware version, and a make file that drives the whole build. There are the usual governance files: a code of conduct and a contributing guide in the documentation directory, and a security address with a security guide.
And there are four files that tell you something about how the team works.
One is a configuration for the model context protocol, which means the project has decided how an assistant is expected to work in this repository. One is a document of design invariants, which is a list of rules about how the interface should look, written down so that a change that violates them is visibly a change. One is a directory of version control hooks and a pre-commit configuration, so the checks run before a commit rather than in a pipeline afterwards. And one is a file of instructions for coding assistants, which is the same convention this batch of projects keeps arriving at.
There are also two build toolchains, which is unusual. The Ruby dependency files exist for the release automation, which is the conventional choice for distributing an application to a mobile platform, and the Swift package manager handles the Swift side. The release directory is where the signing and upload configuration lives, and the localisation configuration sits at the root.
So the repository is a normal iOS application with an unusual dependency, and the unusual dependency is the interesting part: the app you install is a thin client over a component that is itself a product, and the build makes that explicit by requiring the two to be built together.
Editorial conclusion
anytype-swift fits an iOS developer who wants to work on the official client of a local-first application, or on an application that shares the same middleware. It does not fit somebody who wants a self-contained library. Verify first that you can obtain the middleware, either as a prebuilt artefact with a personal access token or by building it locally, since the client cannot be built without it, that the development environment matches the stated requirements, since the build depends on a specific toolchain version, and that the licence terms suit you, because the project is source-available rather than open source and the distinction is deliberate and stated in the readme.
Frequently asked questions
What is the anytype-swift repository?
It is the official iOS client of a local-first workspace application whose documents, chats, notes, files and databases are stored on the device, encrypted end to end, and synchronised peer to peer. The client is written in Swift and the application is published through the app store rather than as a tagged release.
Why does building the Anytype iOS client require a separate middleware repository?
Because the part of the system that handles the cryptography, the network and the storage lives in another component, written in another language, and the client is the interface on top of it. The build either downloads a prebuilt artefact of that component, which needs a personal access token with package read access, or builds it from a sibling checkout and copies the result into the dependencies directory.
How is the Anytype iOS client code generated?
Through four steps in the make file: a script that runs the standard generator for the interface definitions, a source-to-source rewriter, a project-specific code generation binary that produces the Swift bindings, and a further tool for the services module. There is a second target for the client's own modules, and the build phases of the main target and the widget also generate code so that a developer opening the project in the development environment gets the same files.
Is the Anytype iOS client open source?
It is source-available rather than open source, under a custom licence with its own name, and the readme says so and links the licence file. The code is readable and buildable and contributions are invited, but that licence carries its own terms, so the badge on the readme should not be read as an open source licence.
What does the Anytype iOS application do?
The two features with their own sections are chats, where you can create notes, documents or tasks from a conversation, and spaces, which organise projects, teams, family or personal areas into documents, lists and databases with clear boundaries. Beyond that it offers a block editor, custom content types, properties, custom views, templates, web publishing, and bookmarks.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/anyproto-anytype-swift)Was this useful?