Passwords, IDs, certificates, contracts, finances and secret notes, locked in one encrypted vault on your own Mac. Offline. No account. No telemetry.
Everything you can't afford to lose. One encrypted vault.
| Secure | Argon2id and XChaCha20-Poly1305 from audited Rust crates. Your master password is never stored, and passwords never reach the UI layer. |
| Offline | No cloud, no account, no telemetry. It works the same with the Wi-Fi off, and there's no company in the loop to lose your data or lock you out of it. |
| Movable | One .okbak backup file holds your whole vault, already encrypted. Keep it on a hard drive or in your own cloud, and restore it on any Mac. |
| Handy | ⌘⇧Space from anywhere. Search, copy, done. Results rank by what you actually use. |
Your digital life is scattered. A passport scan in an old chat. A contract somewhere in Downloads.
The insurance policy in a cloud drive you haven't opened in years. Passwords in one app, finances in
a spreadsheet, the docker run line you rewrite from memory in your shell history.
And the day you need them tends to be a bad day: a dead laptop, a fresh install, no network, a service that has locked you out.
OwnKeep is the central repo for all of it. One encrypted vault for everything you can't afford to lose, and one hotkey for everything you reach for daily. It's the second brain that keeps what you need to get through the digital world, on hardware you own.
OwnKeep never uploads anything. You take a backup when you choose (Settings → System): one
.okbak file, encrypted before it's ever written, holding your vault and every stored file. Put it
on a hard drive, or in iCloud, Dropbox or any cloud you already trust. Nobody can open it without
your master password or recovery code. From v1.7, the Dashboard reminds you when your backup has
fallen behind, and you can change or turn off that reminder in Settings.
| When this happens | Here's what you do |
|---|---|
| Your Mac dies or is replaced | Install OwnKeep on the next one, choose Restore it on the first screen, and pick your backup. Everything comes back. (On v1.6, create a new vault first, then use Settings → System → Restore vault.) |
| You reinstall macOS | Take a backup first and store it off the machine. Restore it the same way afterwards. |
| The network goes down | Nothing. The vault is already on your disk, so it opens on a plane as it does at your desk. |
| You forget your master password | Your 12-word Emergency Kit unlocks the vault and has you set a new password on the spot. |
| Your laptop is stolen | A locked vault is unreadable without your master password or recovery code. Restore your backup on your next Mac. |
Two limits worth knowing, because a promise like this should come with its edges:
- A restore brings back what your last backup holds. OwnKeep reminds you, but it never backs up by itself, so take a new one after adding something you can't replace.
- Nobody can rescue a lost password and recovery code. If both are gone, the vault stays sealed, and that includes me. Print the Emergency Kit and keep it away from the backup.
A password manager should show its construction before it asks you for anything.
| Encryption | The vault is one file, vault.dat, sealed with XChaCha20-Poly1305 under a key derived from your master password by Argon2id (256 MiB, t=3, p=4). Fresh nonce on every write. Stored files are encrypted the same way in a vault.files folder beside it, and a backup rolls both into one .okbak file. |
| No custom crypto | The primitives come from the audited argon2 and chacha20poly1305 crates. Nothing here is hand-rolled. |
| Secrets never enter the WebView | Decrypted values stay in the Rust core. A copy goes straight from Rust to the pasteboard as concealed, so clipboard-history tools skip it, and it auto-clears. |
| Signed and notarized | Developer ID signature, hardened runtime, notarized and stapled by Apple — so Gatekeeper opens it without a warning. Verify it yourself before you open the DMG. |
| No third-party audit | Said here rather than waiting to be asked: no outside firm has reviewed this. Standard primitives, conventional parameters, a property-tested crypto core, and >95% coverage on both surfaces — none of which is an audit, and I won't call it one. |
The exact construction, the limitations, and five commands that check these claims are in
SECURITY.md. The design rationale behind it is
spec.md §4.
Save a snippet once with {{placeholder}} markers. When you pick it, OwnKeep prompts for the values
and copies the finished command — so a template with a placeholder in the middle works exactly as
well as one with a placeholder at the end.
Snippets are syntax-highlighted, grouped into categories you define, and searchable by full text —
not just by title. ⌥⌘1–⌥⌘9 copies the raw template instead if you'd rather fill it in yourself.
The bar is the home screen. Results rank by fuzzy match × frecency, so the things you actually
use surface first instead of whatever happens to match alphabetically. Scope prefixes narrow to one
module when you already know where you're going — n for notes, for example. Notes stay out of the
bar by default so a long body never drowns a login; turn searchability on per module in Settings.
Nothing needs the mouse: ⌥⇧1–⌥⇧9 runs a result's primary action — copy the password, fill in the
command — and Esc makes the bar disappear. It hides on blur too, so it never becomes another window
to manage.
Each module lives in the same encrypted vault, the same bar and the same Dashboard sidebar. Any of them switches off from Settings with its data preserved, so you only see what you use.
Lists and bookmarks are candidates for later. The module registry is what makes adding one a self-contained job rather than surgery on the core: one folder and one line in the registry.
![]() |
![]() |
Your master password is never stored and cannot be recovered. The recovery code from your Emergency Kit is the only other way in, and both always work.
Touch ID is a shortcut, never a replacement. Enrolling requires an already-unlocked vault, the key is device-local and excluded from every backup, and a fingerprint change invalidates it — so losing Touch ID can't lock you out of your own vault.
Download the latest .dmg — Universal
2, macOS 13+, about 12 MB.
Open the DMG, drag OwnKeep to Applications, launch it. macOS asks for Accessibility permission so the global hotkey works system-wide; OwnKeep then lives in the menu bar with no Dock icon.
Releases are signed with a Developer ID certificate, built with hardened runtime, and notarized by Apple — so Gatekeeper opens it without a warning. Confirm that yourself rather than taking my word for it:
spctl -a -vvv -t open --context context:primary-signature OwnKeep_1.4.0_universal.dmg
# accepted
# source=Notarized Developer IDPrefer to build it? See Development.
Stated plainly, because it should save some people a download:
- Not a sync service. Nothing leaves your Mac unless you put it somewhere yourself, and OwnKeep doesn't back up on its own schedule. Your backups are yours to take.
- Not a 1Password or KeePassXC replacement. No sync, no browser autofill, no TOTP generation, no import from other managers. If those are what you need, use KeePassXC or Bitwarden — genuinely good tools that OwnKeep isn't competing with.
- Not audited. No third-party review, as said above. SECURITY.md is blunt about this and about everything else OwnKeep doesn't do.
- Not cross-platform. macOS 13+ only. Touch ID, the concealed clipboard, and the menu-bar behavior are macOS-native.
- Not a team tool. One person, one Mac, one vault.
SECURITY.md carries the parts the summary at the top leaves out: the three-way envelope wrap, the Touch ID key's Keychain attributes, and the threat model — including what a compromised Mac defeats no matter how the vault is built. Read it before you put anything important in here.
Found a vulnerability? Report it privately — please don't open a public issue.
- What & why:
spec.md· Build order & status:plan.md - Contributing:
CONTRIBUTING.md· Releasing:RELEASING.md - Signing & Touch ID on macOS:
code-signing.md - Rules for humans & AI agents:
AGENTS.md,.cursor/rules/
Status: v1.6 shipping, with Files, drag to sort, pagination and change master password on top of the signed, notarized, Touch ID-enabled base. The encrypted vault core, every feature module, the command bar, Dashboard, backup/restore, scheduler and migration framework are all in place (see
plan.md).
Tauri 2 (Rust core) · React 18 + TypeScript (Vite) · Tailwind CSS + shadcn/ui + Lucide · Zustand ·
Vitest + React Testing Library (frontend) · cargo test (Rust). See spec.md §2.
- macOS 13+ (Apple Silicon or Intel)
- Node.js ≥ 20 and pnpm 10 (
corepack enableprovides pnpm) - Rust (stable) via rustup
- Rust coverage tool:
cargo install cargo-llvm-cov(needed forpnpm coverage:rust) - Xcode Command Line Tools:
xcode-select --install
pnpm installpnpm dev # Tauri dev: Rust core + Vite front-end with hot reload
pnpm dev:web # front-end only (Vite at http://localhost:1420), no Rust shellOn first launch, macOS will ask you to grant Accessibility permission so the global hotkey
(Cmd+Shift+Space) works system-wide. The app runs in the menu bar (no Dock icon); use the tray
icon's Search ... / Dashboard / Exit menu, or the hotkey to toggle the window. It hides on Esc or when it loses
focus.
Development builds use a separate vault (vault-dev.dat) and a separate Keychain service, so you
cannot damage a real vault while working on OwnKeep.
On first run you set a master password. It encrypts the whole vault and is never stored — so if you forget it, the only other way in is the recovery code shown once during onboarding as your Emergency Kit.
- The recovery code is a random 12-word phrase that unlocks the entire vault, so store it offline (printed, or in a separate password manager) and never beside the vault file.
- Unlocking with the recovery code forces you to set a new master password on the spot.
- You can regenerate the Emergency Kit anytime from Settings (this re-wraps the recovery key; the old code stops working).
The vault lives at ~/Library/Application Support/com.shaojiang.ownkeep/vault.dat
(vault-dev.dat in dev builds), with stored files in vault.files beside it, outside the app bundle — see spec.md §3.2 and §4.
OwnKeep is keyboard-first. Press ⌘H on either surface to open the in-app shortcut cheat
sheet (also reachable from the Help row in the Dashboard sidebar). The essentials:
| Where | Keys | Action |
|---|---|---|
| Anywhere | ⌘⇧Space |
Summon the command bar |
| Anywhere | ⌘⇧D |
Toggle the Dashboard window |
| Anywhere | ⌘H |
Show keyboard shortcuts |
| Anywhere | ⌘/ |
About OwnKeep |
| Command bar | ⌥⇧1–⌥⇧9 |
Run a result's primary action (e.g. copy password) |
| Command bar | ⌥⌘1–⌥⌘9 |
Copy a command's raw template |
| Command bar | Esc |
Hide the launcher |
| Dashboard | ⌥⇧1–⌥⇧9 / ↑ ↓ |
Switch modules in the sidebar |
Copy and clipboard actions confirm with a toast; secret copies note when the clipboard auto-clears.
Light / dark / system and the accent color are set in Settings → Appearance and apply live.
OwnKeep upgrades by manual replacement — download a new .dmg and drag the new app over the old
OwnKeep app. Your data is untouched because the vault lives outside the app bundle.
Backups are one .okbak file holding your vault and any stored files. Existing .dat backups remain restorable regardless of their filename prefix. If you are coming
from a build older than v1.2, regenerate the Emergency Kit once from Settings to move its recovery
wrap to the current OwnKeep derivation context; the reader still accepts the existing code until you
do.
v1.3 changes no data shape — it adds an empty notes slice on first open and nothing else, so
upgrading from v1.2 runs no migration and does not re-issue the Emergency Kit. One thing will
surprise your fingers: Notes takes ⌥⇧4, so Subscriptions moves to ⌥⇧5 and Finance to ⌥⇧6.
Modules are numbered by their position in the sidebar, so inserting one shifts everything below it.
When a new build introduces a data-shape change, opening your existing vault shows a migration
guide before anything is written: it summarizes added fields, shows renamed paths (old → new), and
lists removals in red as data loss. You then choose to:
- Accept & upgrade — writes an automatic pre-migration backup, applies the migration, and continues; or
- Reject — Back up & quit, Erase & start fresh (danger, irreversible), or Quit untouched.
Migrations are forward-only, so an older app refuses a migrated vault — to roll back, restore the
pre-migration backup with the older build. Full rules: spec.md §11.
pnpm test # Vitest (front-end unit tests)
pnpm coverage # Vitest with V8 coverage; fails below 95%
pnpm coverage:rust # cargo llvm-cov; fails below 95% Rust-core line coverage
pnpm coverage:all # front-end + Rust coverage gates
pnpm typecheck # tsc --noEmit
pnpm lint # ESLint
pnpm format # Prettier (write) · pnpm format:check to verify
pnpm check # typecheck + lint + format:check + test
cd src-tauri && cargo test # Rust core testsFrontend coverage measures first-party application code (src/**/*.{ts,tsx}) and intentionally
excludes bootstrap glue, type-only files, test setup, and copied shadcn/ui primitives. The Rust
coverage gate measures the testable core modules with cargo llvm-cov --fail-under-lines 95 and
excludes Tauri IPC/bootstrap glue (commands.rs, lib.rs, main.rs), which need later integration
coverage rather than unit coverage.
pnpm build # builds the front-end and bundles the macOS appOutput lands in src-tauri/target/release/bundle/ (.app and .dmg).
Release builds are signed with a Developer ID certificate, built with hardened runtime, and notarized
and stapled by Apple — which is also what makes Touch ID work, since the biometric Keychain item
needs the app's private application-identifier entitlement and a matching embedded provisioning
profile. A local pnpm build without the signing assets produces an ad-hoc signed bundle:
fine for development, but Gatekeeper will reject it and Touch ID enrollment will fail with
errSecMissingEntitlement.
The full procedure is in code-signing.md; the release checklist — including the
verification commands to run before uploading an artifact — is in RELEASING.md.
- Global hotkey does nothing — grant Accessibility: System Settings → Privacy & Security → Accessibility → enable OwnKeep (or your terminal, in dev). The app is designed to also work from the tray if the permission is denied.
- Window vanished — that's the launcher behavior (hide on blur/Esc). Press
Cmd+Shift+Spaceor use the tray's Search .... - Touch ID button doesn't appear — it needs a signed build and an already-unlocked vault to
enroll from Settings → System → Security. See
code-signing.md. Port 1420 is already in use— another Vite/OwnKeep dev server is running; stop it or free the port (the dev server uses a fixed port on purpose).- First
cargo/Tauri build is slow — the Rust core and Tauri dependencies compile from source the first time; subsequent builds are incremental.
ownkeep/
├── src/ # React + TypeScript front-end (UI only; no secrets)
├── src-tauri/ # Rust core (crypto, storage, concealed clipboard, scheduler)
├── docs/media/ # README screenshots
├── spec.md # product & technical spec
├── plan.md # phased development plan
└── AGENTS.md # AI-agent rules (also read by Codex, Claude, Cursor)
Issues and PRs are welcome — please read CONTRIBUTING.md first. OwnKeep is
spec-driven with a hard >95% coverage gate on both surfaces, and it has deliberate non-goals, so a
quick issue before you write code saves everyone an evening.
GPL-3.0-or-later. You can read it, build it, fork it, and run it however you like; if you distribute a modified version, it stays open under the same terms.













