AppFlowy is a workspace in the mould of Notion: pages with a block editor, nested wikis, databases you can view as a grid, a kanban board or a calendar, and AI writing and chat built in. It is a native app for macOS, Windows, Linux, iOS and Android, written in Flutter with a Rust core, so it feels quicker than a web wrapper and works offline.
The difference from Notion is control. You can use it on one device with local data, sync through AppFlowy Cloud, or self-host the cloud server so your team's notes never touch someone else's infrastructure. The AI features can also be pointed at local models. It is AGPL-3.0, with about 77,800 stars and 380 contributors, and releases arrive regularly.
Honest limits: it does not match Notion feature for feature, especially in integrations and the template ecosystem, and self-hosting the sync server is a separate project with its own setup.
- Repository: github.com/AppFlowy-IO/AppFlowy
- Licence: AGPL-3.0 (GNU Affero General Public License v3.0)
- Language: Dart. Stars: 77.8K. Forks: 6,092. Last push: Oct 26, 2026.
- Scan: safe, Oct 26, 2026, commit 5cf3a36
Who it is for
Notion users who want their notes and project boards on their own devices or server, small teams that need a self-hosted wiki and task tracker, and anyone uneasy about a single company holding all their notes.
Getting started
1. Linux (Flathub); macOS and Windows installers are on the GitHub releases page
flatpak install flathub io.appflowy.AppFlowy2. Linux (Snap)
sudo snap install appflowyPhones get it from the App Store (iPhone) and Google Play (Android 10 or later). To keep sync on your own server, follow the self-hosting guide on appflowy.com.
Safety scan
We cloned AppFlowy-IO/AppFlowy at commit 5cf3a36 on Oct 26, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.
- No secrets, no committed binaries and no bare-IP URLs. The 3 pattern hits are rustup's installer in a Dockerfile and in the Linux developer setup script, and a comment in install.sh explaining how it guards against a truncated curl | bash.
- install.sh (403 lines) downloads a release tarball from GitHub and uses sudo to move it into /opt. The four install_dev_env scripts set up Flutter and Rust for contributors; the Linux one uses sudo for apt packages. Eleven Cargo build scripts generate code for the Rust core.
- 94 known advisories, all in frontend/rust-lib/Cargo.lock, which is the Rust core bundled into the app: 2 critical in older versions of the zip crate, and high-rated ones in openssl, diesel, lopdf, lz4_flex and others. The scanner does not count Dart, so the Flutter UI is missing from the line count and its pub dependencies were not checked.
- 11 workflows. ninja_i18n.yml uses pull_request_target to lint translations on pull requests; it checks out the base branch, not the pull request, but runs a third-party action from its main branch with permission to write pull request comments. None of the 35 third-party actions is pinned to a commit. Code of conduct and licence present; no security policy, Dependabot or CodeQL.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | None found. |
| Suspicious code | 3 pattern hits found and read; every one is listed under the raw findings. |
| Install-time code | 11 Cargo build scripts. 5 installer scripts (one fetches and runs a remote script; one can call sudo) |
| Committed binaries | None. |
| CI workflows | 11 workflows. 1 uses pull_request_target, none check out the pull request head. 35 of 35 third-party actions pinned to a tag rather than a commit. |
| Network hosts | 26 distinct hosts referenced from source; most often github.com, appflowy.io, docs.rs, www.appflowy.io. No URLs to bare IP addresses. |
| Known vulnerabilities | 94 advisories across 823 pinned packages: 2 critical, 17 high, 23 moderate, 13 low, 39 unrated. frontend/rust-lib/Cargo.lock: 823 packages, 94 advisories. |
| Project hygiene | Has licence file. Missing security policy, automated dependency updates, CodeQL, contributing guide. |
| OpenSSF Scorecard | Not scored: the project is not in Scorecard's weekly index. |
The raw findings
Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.
Pattern hits (3)
| Where | Rule | Match |
|---|---|---|
| frontend/scripts/docker-buildfiles/Dockerfile:23 | download-piped-to-shell | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y |
| frontend/scripts/install_dev_env/install_linux.sh:30 | download-piped-to-shell | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| install.sh:35 | download-piped-to-shell | # if a curl|bash cuts off the end of the script due to |
Installer scripts (5)
- frontend/scripts/install_dev_env/install_ios.sh, 101 lines; talks to github.com
- frontend/scripts/install_dev_env/install_linux.sh, 119 lines, uses sudo, fetches and runs a remote script; talks to github.com, sh.rustup.rs
- frontend/scripts/install_dev_env/install_macos.sh, 94 lines; talks to github.com
- frontend/scripts/install_dev_env/install_windows.sh, 113 lines; talks to github.com, win.rustup.rs
- install.sh, 403 lines, uses sudo; talks to github.com, unlicense.org
Worst known vulnerabilities (24 of 94)
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-4684-h2q9-2vcp | critical | zip@0.6.6 | ZipStreamReader::extract() and ZipArchive::extract() apply Unix permissions through symlinks without confining the targe… |
| GHSA-4684-h2q9-2vcp | critical | zip@2.2.0 | ZipStreamReader::extract() and ZipArchive::extract() apply Unix permissions through symlinks without confining the targe… |
| GHSA-h5x4-m2qf-r4f2 | high | diesel@2.2.10 | Diesel's SQLite backend has possible UTF-8 corruption |
| GHSA-6fj4-rcr3-r7rr | high | lopdf@0.36.0 | lopdf has a stack overflow via deeply nested PDF objects |
| GHSA-vvp9-7p8x-rfvv | high | lz4_flex@0.11.2 | lz4_flex's decompression can leak information from uninitialized memory or reused output buffer |
| GHSA-r8w9-5wcg-vfj7 | high | mio@0.8.9 | Mio's tokens for named pipes may be delivered after deregistration |
| GHSA-rvr2-r3pv-5m4p | high | oneshot@0.1.11 | oneshot has potential Use After Free when used asynchronously |
| GHSA-8c75-8mhr-p7r9 | high | openssl@0.10.62 | rust-openssl has incorrect bounds assertion in aes key wrap |
| GHSA-ghm9-cr32-g9qj | high | openssl@0.10.62 | rust-openssl: rustMdCtxRef::digest_final() writes past caller buffer with no length check |
| GHSA-hppc-g8h3-xhp3 | high | openssl@0.10.62 | rust-openssl: Unchecked callback length in PSK/cookie trampolines leaks adjacent memory to peer |
| GHSA-pqf5-4pqq-29f5 | high | openssl@0.10.62 | rust-openssl: Deriver::derive and PkeyCtxRef::derive can overflow short buffers on OpenSSL 1.1.1 |
| GHSA-xp3w-r5p5-63rr | high | openssl@0.10.62 | rust-openssl has undefined behavior in X509Ref::ocsp_responders for certificates with non-UTF-8 OCSP URLs |
| GHSA-4w2j-m93h-cj5j | high | quinn-proto@0.11.9 | Quinn: Remote memory exhaustion in quinn-proto from unbounded out-of-order stream reassembly |
| GHSA-6xvm-j4wr-6v98 | high | quinn-proto@0.11.9 | Quinn affected by unauthenticated remote DoS via panic in QUIC transport parameter parsing |
| GHSA-3g6h-r5qx-f6hq | high | quinn-proto@0.11.9 | Peer minimum ACK delay can panic quinn-proto when ACK_FREQUENCY transmission is enabled |
| GHSA-82j2-j2ch-gfr8 | high | rustls-webpki@0.102.8 | rustls-webpki: Denial of service via panic on malformed CRL BIT STRING |
| GHSA-vv5m-jxxh-4627 | high | zip@0.6.6 | Insecure Preservation of SUID/SGID Bits during ZIP Extraction Leading to Potential Privilege Escalation |
| GHSA-94vh-gphv-8pm8 | high | zip@2.2.0 | zip Incorrectly Canonicalizes Paths during Archive Extraction Leading to Arbitrary File Write |
| GHSA-vv5m-jxxh-4627 | high | zip@2.2.0 | Insecure Preservation of SUID/SGID Bits during ZIP Extraction Leading to Potential Privilege Escalation |
| GHSA-423w-p2w9-r7vq | moderate | aes-gcm@0.10.2 | AEADs/aes-gcm: Plaintext exposed in decrypt_in_place_detached even on tag verification failure |
| GHSA-434x-w66g-qw3r | moderate | bytes@1.9.0 | bytes has integer overflow in BytesMut::reserve |
| GHSA-ggxf-9f6j-w742 | moderate | diesel@2.2.10 | Diesel has possible use after free when deserializing a SQLite database via `SqliteConnection::deserialize_readonly_data… |
| GHSA-m9p2-fxp5-v3fp | moderate | diesel@2.2.10 | Diesel: Command injection in Diesel's implementation of `COPY FROM`/`COPY TO` |
| GHSA-q8x8-jrhj-fh9p | moderate | diesel@2.2.10 | Diesel: Possible unaligned data access for implementations of `SqliteAggregate` |
Workflows worth a look
- .github/workflows/ninja_i18n.yml: pull_request_target
By the numbers
| Stars | 77.8K |
|---|---|
| Forks | 6,092 |
| Contributors | 381 |
| Commits | 7,210 |
| Open issues | 939 |
| Open pull requests | 120 |
| Releases | 153 |
| Latest release | 0.14.11 |
| Licence | AGPL-3.0 |
| Main language | Dart |
| Project age | 5 years |
| Last push | Oct 26, 2026 |
| Tracked files | 4,597 |
| Lines of code | 202.4K |
| Checkout size | 40 MB |
Lines by language: Rust 106.7K, JSON 79.3K, TOML 3,266, YAML 3,126, Markdown 2,639, C++ 2,450.
Questions
Is AppFlowy free?
Yes. The app is free and open source under AGPL-3.0, and you can use it locally or self-host the sync server at no cost. AppFlowy also sells paid plans for its hosted cloud.
Can I self-host AppFlowy?
Yes. The desktop and mobile apps can sync to an AppFlowy Cloud server you run yourself, so your workspace data stays on your own infrastructure. The server is a separate project with its own step-by-step self-hosting guide on appflowy.com.
Does AppFlowy work offline?
Yes. It is a native app that keeps your data on the device and syncs when it can reach AppFlowy Cloud or your self-hosted server. Used without a cloud account, it stays entirely local.
This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.
