β€οΈ it? Then βοΈ it on GitHub or Tweet about it.
- Store Login/Password credentials
- Credit card Information
- Secure notes to store sensitive information
- One-click Strong Password Generation
- Time-based One Time Passwords support (TOTP)
- Google Drive Sync (optional)
- No data is leaving your computer:
- Your vault is a locally stored, encrypted SQLite database (SQLCipher); each entry's secrets are sealed in an extra application-level AEAD layer
- Secrets stay encrypted at rest and in memory, decrypted only when you reveal or copy them
- Ability to migrate from one computer to another using backup file or GDrive sync
- There's more to come...
Check the Latest Releases page for the most recent packaged app for MacOS, Windows or Linux.
Every release is built in GitHub Actions and ships with supply-chain evidence:
-
SLSA build provenance β each installer is attested with
actions/attest-build-provenance(keyless OIDC signing). You can prove an installer was built by this repo's workflow, from this source, with the GitHub CLI:gh attestation verify ./Swifty_1.0.0_amd64.AppImage --repo swiftyapp/swifty
(works for the
.dmg,.msi,-setup.exe,.deb,.rpmand.AppImageassets β point it at whichever you downloaded). -
CycloneDX SBOM β every release attaches
swifty-rust.cdx.json(the full Rust dependency graph) and, when available,swifty-js.cdx.json(the frontend). Feed them to any CycloneDX-aware scanner (e.g.grype sbom:./swifty-rust.cdx.json) to audit the exact dependencies a build shipped. -
Update signature β the auto-updater only installs updates signed with the project's minisign key (public key in
src-tauri/tauri.conf.json); the matching private key never leaves CI.
The Rust toolchain (rust-toolchain.toml) and the bun version are both pinned,
so builds are reproducible from a fixed toolchain.
Swifty is built with Tauri 2 (Rust backend + TypeScript/React/Vite frontend).
- Node.js 22 (what
.nvmrcand CI pin; 20.19 or newer also works β ESLint 10 requires^20.19.0 || ^22.13.0 || >=24) - Rust (stable toolchain)
- Platform build dependencies for Tauri β see the
Tauri prerequisites guide
(on Linux:
libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libgtk-3-dev)
git clone git@github.com:swiftyapp/swifty.git
cd swifty
npm install
npm run tauri:dev # run the app in development
npm run tauri:build # produce a signed, packaged build for the current OS
npm run build # build the frontend only (tsc + vite)
npm test # frontend unit tests (Vitest)
cd src-tauri && cargo test # backend testsDrive sync uses your own Google OAuth client β no credentials are bundled with the app. Desktop and iOS need one client each, because Google will not let a Desktop client redirect to a mobile app.
-
In the Google Cloud Console create an OAuth 2.0 Client ID of type Desktop app.
-
Enable the Google Drive API for the project.
-
The app requests the
https://www.googleapis.com/auth/drive.filescope and listens on the loopback redirect URIhttp://127.0.0.1:4567/auth/callback. -
Provide the credentials as environment/build variables when running or building:
export GOOGLE_OAUTH_CLIENT_ID=your-desktop-client-id.apps.googleusercontent.com export GOOGLE_OAUTH_CLIENT_SECRET=your-desktop-client-secret # optional
They are read at runtime (
std::env::var) and, if absent, fall back to the value baked in at compile time (option_env!). The build succeeds without them β sync simply reports "Google OAuth client not configured" until a client id is supplied.
An iOS client is a public client: it has no secret, PKCE is mandatory, and its redirect URI is its own client id reversed. So the one thing to configure is that URL scheme, and the client id is derived from it.
-
In the same project create a second OAuth 2.0 Client ID, of type iOS, with the bundle id from
src-tauri/tauri.conf.json(pro.getswifty.app). -
Take the client id it gives you β
123456-abcdef.apps.googleusercontent.comβ and reverse it into a scheme:com.googleusercontent.apps.123456-abcdef. (Google shows this as the "iOS URL scheme" on the credential page.) -
Replace the placeholder in
src-tauri/tauri.ios.conf.json:"plugins": { "deep-link": { "mobile": [{ "scheme": ["com.googleusercontent.apps.123456-abcdef"] }] } }
This is the committed source of truth for iOS, and it is safe to commit β an iOS client id is public by design. The Tauri CLI registers the scheme as
CFBundleURLTypesin the generatedInfo.plistduringtauri ios build(viatauri-plugin-deep-link's build script), and the app derives both the client id and the redirect URIcom.googleusercontent.apps.<id>:/oauth2redirectfrom it at runtime. Re-runbun run tauri ios initif the Xcode project is out of date. -
Add the redirect URI
com.googleusercontent.apps.123456-abcdef:/oauth2redirectto the client in the console.
GOOGLE_OAUTH_CLIENT_ID still overrides the scheme on iOS (the release workflow
sets it from a secret), and the redirect is then derived back from that id β but
the scheme in tauri.ios.conf.json is what actually registers the app with the
OS, so it has to be right either way. GOOGLE_OAUTH_CLIENT_SECRET is ignored on
iOS and must never be shipped in a mobile binary.
Release builds are signed for tauri-plugin-updater. The public key lives in
src-tauri/tauri.conf.json; the matching private key is never committed and
is provided to CI via the TAURI_SIGNING_PRIVATE_KEY (and
TAURI_SIGNING_PRIVATE_KEY_PASSWORD) secrets. Generate a keypair with
npm run tauri signer generate -- -w ~/.swifty/updater.key.
Swifty is offline-first: your vault is an encrypted SQLite database (SQLCipher)
on your own device, with each entry's secrets sealed in an additional
application-level AEAD layer, and there is no backend that holds your secrets.
See SECURITY.md for
how to report a vulnerability, and docs/threat-model.md
for what Swifty does and does not defend against.
This project exists thanks to all the people who contribute. [Contribute].
Become a financial contributor and help us sustain our community. [Contribute]
Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]
GNU/GPL Version 3

