Manage your digital selves. Switch identity material with confidence.
Persona is a local-first, zero-knowledge manager for one person operating multiple digital selves. Each identity is a distinct key-and-credential context used in a different environment, such as work, personal browsing, infrastructure access, or automation.
The product focuses on identity-scoped credentials and developer workflows: passwords, API keys, TOTP, SSH keys, browser autofill, and active identity switching. Wallet material fits the same conceptual model, but is currently a deferred priority rather than part of the main product track.
- Identity-scoped vault: passwords, TOTP secrets, API keys, SSH keys, tags, and secure metadata
- Developer tooling: built-in SSH agent, CLI workflows, and automation-friendly credential access
- Browser assistance: autofill, suggestion, phishing resistance, and per-site identity defaults
- Passkeys (WebAuthn): ES256/P-256 keys sealed under the per-item key hierarchy, create/list/self-test from the CLI
- End-to-end encrypted sync: multi-device credential sync with server-sees-ciphertext-only, conflict adjudication UI, and group key rotation
- Self-host optional: Persona Server (Rust + Axum) for sync, accounts, backups, and a zero-knowledge pairing relay
- Import/export: JSON/YAML/CSV with optional gzip compression and passphrase encryption (Argon2id + AES-GCM)
- Audit log: critical operations and signing events (with digest)
- Local-first security: zero-knowledge storage, auto-lock, confirmation, and supply chain checks
The desktop vault after the 1Password-style sidebar redesign: items, categories, vaults, tags, and tools in one sidebar, with the item detail pane on the right.
persona/
├── core/ # Rust core library: models, crypto, storage, service layer
├── cli/ # Persona CLI: init/add/list/show/switch/export/import/ssh/...
├── agents/ssh-agent/ # Built-in SSH agent (UNIX socket; ed25519/RSA/ECDSA)
├── desktop/ # Tauri + React desktop client (sync, passkeys, conflict UI)
├── browser/ # Browser clients (Chromium extension, Safari extension)
├── mobile/ # Mobile clients (iOS, Android, HarmonyOS)
├── connect-server/ # Local automation endpoint (127.0.0.1 HTTP, scope token)
├── server/ # Optional sync/automation service (Rust + Axum + SQLite)
├── website/ # Marketing site (UmiJS)
└── docs/ # Documentation and roadmap
- Core library: Rust with sqlx + SQLite
- Cryptography: Argon2id key derivation and AES-256-GCM symmetric encryption (RustCrypto-family crates)
- Desktop: Tauri + React + TypeScript
- Server: Rust + Axum (optional)
- Wallet: rust-bitcoin (BTC) and alloy (EVM) with official test vectors as regression harnesses
Persona builds on established open-source foundations — Tauri, React, Axum, sqlx, rust-bitcoin, alloy — rather than replacing them; the product layer (identity model, policy engine, pairing protocol, vault hierarchy) is where this repo's own work lives.
- Zero-knowledge architecture – servers never see plaintext user data
- End-to-end encryption – AES-256-GCM plus Argon2id-based key derivation
- Local-first – all sensitive data is encrypted/decrypted on the local device
- Signed audit trail – SSH signatures are logged with sha256 digest and context metadata
- Policy controls – the SSH agent can enforce rate limits, interactive confirmations, and optional
known_hostsvalidation
- Rust 1.97+ (pinned via
rust-toolchain.tomlfor reproducible builds) - Node.js 18+
# Clone the repository
git clone git@github.com:cuihairu/persona.git
cd persona
# Build CLI and SSH agent
cargo build --workspace
# Optional: run local CI checks
make ci# Install workspace dependencies (desktop + browser extension + website)
pnpm install
# Run the desktop client in dev mode
pnpm --filter desktop run dev
# Build the browser extension bundle
pnpm --filter persona-chromium-extension run build
# Run the website in dev mode
pnpm --filter persona-website run dev# Initialize an unencrypted workspace
persona init --path ~/PersonaDemo --yes
# Initialize an encrypted workspace with a master password
persona init --path ~/PersonaSecure --yes --encrypted --master-password "your_password"
# Add / show / list identities
persona add
persona show <name>
persona list
# Switch the active identity (Workspace v2 persists the state)
persona switch <name>
# Run migrations to keep the schema up to date
persona migrate
# Credential management (passwords, API keys, etc.)
persona credential add --identity alice --name "GitHub" --credential-type password --prompt-secret
persona credential list --identity alice --format table
persona credential show --id <UUID> --reveal
persona credential remove --id <UUID>
# Item history (1Password-style): every create/update/delete is recorded with
# field-level diffs; encrypted payloads only ever show as "<encrypted>"
persona credential history --id <UUID>
# Attachments (1Password-style): files are encrypted with the owning item's
# key and stay decryptable across master-password rotation
persona credential attach --id <UUID> --file ~/Documents/recovery-codes.txt
persona credential attachments --id <UUID>
persona credential save-attachment --attachment-id <UUID> --output ~/Downloads/recovery-codes.txt
persona credential remove-attachment --attachment-id <UUID>
# Custom fields (1Password-style): typed fields (text/concealed/date) with
# optional sections; the whole table is sealed under the item's per-item key.
# set-fields replaces the entire table; --clear removes all fields
persona credential set-fields --id <UUID> --field concealed:Bank:PIN=999999 --field text::Recovery=abc123
persona credential fields --id <UUID> # concealed values masked
persona credential fields --id <UUID> --reveal # confirm, then print values
# Secure Note (1Password-style): the body is stored fully encrypted under the
# per-item key — unlike the plain notes column on other item types
persona credential add --identity alice --name "Recovery codes" --credential-type note --note "1111-2222
3333-4444"
# Identity / Software License (1Password standard categories): document numbers
# and license keys are sealed under the item's key; unspecified fields stay empty
persona credential add --identity alice --name "Passport (main)" --credential-type identity \
--first-name Alice --last-name Zhang --id-number 110101199001310011 --passport-number E12345678
persona credential add --identity alice --name "JetBrains All Products" --credential-type software-license \
--license-key AAAA-BBBB-CCCC-DDDD --version 2024.2 --seats 3 --valid-until 2027-05-01
# TOTP (two-factor authentication) workflows
persona totp setup --identity alice --qr ~/Downloads/github.png
persona totp code --id <UUID>
persona totp code --id <UUID> --watch
# Steam Guard (game token; shared_secret is the base64 from the Steam authenticator export)
persona totp setup-steam --identity alice --account alice_steam --secret <base64-shared-secret>
persona totp code --id <UUID> # game token credentials share the same code command
# Or import straight from a Steam Desktop Authenticator export (.maFile) —
# a single file or a whole directory; only verifier fields are stored, the
# Session/access_token credentials are listed and never imported
persona totp import-steam --identity alice --file ~/Downloads/maFiles/alice.maFile
persona totp import-steam --identity alice --file ~/Downloads/maFiles --yes
# Battle.net authenticator: export via a community tool (serial + restore code ->
# standard TOTP secret), then import like any TOTP with 8 digits
persona totp setup --identity alice --secret <base32-secret> --issuer Battle.net --digits 8
# Vendor-bound game tokens (Tencent Game Security Center, NetEase Da Shen,
# miHoYo security token, ...): recorded as vault entries only — their seeds live
# inside the vendor's app, so codes must be generated there
persona totp setup-game-token --identity alice --provider tencent_security --account qq_123456 --url https://gamesafe.qq.com
# Passkeys (WebAuthn, software authenticator): ES256/P-256 keys sealed under
# the per-item key hierarchy; credential IDs are unique across the vault
persona passkey create --identity alice --rp github.com --user alice@example.com
persona passkey list --identity alice
persona passkey show <UUID>
persona passkey self-test <UUID> # local register + assert round trip
persona passkey remove --id <UUID>
# Password generator with custom sets
persona password generate --length 32 --set lowercase --set uppercase --set digits --set symbols
persona password generate --pronounceable --length 18 --set lowercase --set uppercase
# Diceware-style passphrase from the EFF large wordlist (3-10 words, `-`-separated)
persona password generate --words 6
# TUI dashboard (ratatui + crossterm)
persona tui --identity alice # optional: preselect identity
q to quit, r to reload, ↑/↓ or j/k to navigate
# Connect local automation (secrets automation): read-only HTTP API on
# 127.0.0.1 for scripts/CI — token plaintext is shown exactly once
persona connect token create --label "my CI script"
persona connect serve
curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:$PORT/api/v1/connect/items
# Secrets automation, CLI direct read (refs are IDENTITY/ITEM/FIELD)
persona secrets resolve work/deploy/api_key # one value per line
persona secrets run --env GH_TOKEN=work/ci/api_key -- gh repo view
persona secrets k8s --name deploy --key password=work/deploy/password | kubectl apply -f -
persona secrets external # Terraform external provider: stdin JSON -> stdout JSON# Export to JSON with sensitive content (requires unlock)
persona export --include-sensitive --output backup.json
# Enable gzip compression and passphrase-based encryption
persona export --format yaml --compression 9 --encrypt --output backup.yaml
# Import (.json/.yaml/.csv); --decrypt prompts for the passphrase
persona import backup.enc --decrypt --mode merge --backupExport an unencrypted .1pux file from 1Password (Settings → Export),
then preview and import it:
persona import-1pux export.1pux --dry-run # show the plan, touch nothing
persona import-1pux export.1pux # confirm, then importEach 1Password vault becomes one identity (same-name identities are reused); Login items map to password credentials with TOTP secrets split into their own credentials, and API Credential / SSH Key items map to their persona equivalents. Unsupported categories, archived items, and attachments are reported and skipped — nothing is silently dropped or forced into a lossy shape.
# Generate an SSH key (ed25519) and store it in the vault
persona ssh generate --identity <name> --name "GitHub Key"
# Start the built-in agent and print the export command
persona ssh start-agent --print-export
export SSH_AUTH_SOCK=... # Copy to the current shell
# Provide the destination host and run a command
persona ssh run --host github.com -- ssh -T git@github.com
# Optional agent policies
export PERSONA_AGENT_REQUIRE_CONFIRM=1 # Prompt before every signature
export PERSONA_AGENT_MIN_INTERVAL_MS=1000 # Rate limit in milliseconds
export PERSONA_AGENT_ENFORCE_KNOWN_HOSTS=1 # Enforce known_hosts checks
export PERSONA_AGENT_CONFIRM_ON_UNKNOWN=1 # Ask before unknown hosts
# Status and shutdown
persona ssh agent-status
persona ssh stop-agent
# git commit signing (SSHSIG): install a copy of the binary named
# persona-ssh-sign, then point git at it
cp "$(command -v persona)" ~/.local/bin/persona-ssh-sign
git config gpg.format ssh
git config gpg.ssh.program ~/.local/bin/persona-ssh-sign
git config user.signingkey "persona:ssh:<credential-uuid>"
git commit -S # signed with the vault key
# Distribute a vault public key to a host's authorized_keys (idempotent;
# --dry-run previews, --list reads, --remove revokes)
persona ssh authorize --identity work --host deploy@prod-1.example.com- ONEPASSWORD_FEATURES – reference checklist for 1Password parity
- FEATURE_GAP_ANALYSIS – Persona vs. 1Password comparison
- PASSKEYS_DESIGN – passkeys (WebAuthn) design draft
- MONOREPO – monorepo rationale and tooling
- UNINSTALL – 卸载与数据保留(卸载不删数据,重装接续;显式 purge 步骤)
- ROADMAP – roadmap and detailed TODO items
- TODO – daily-maintained task list
- BRIDGE_PROTOCOL – browser extension native messaging protocol
- Brand assets – logos, wordmarks, colors, and guidelines
- Client Communication Architecture – unified IPC architecture
- Non-Interactive Mode Guide – CI/CD integration guide
- E2EE Sync Design – end-to-end encrypted sync design (phases 1–4 landed)
- Storage and Sync Guide – storage and sync modes, dual-device walkthrough
- Sync Group Mode – default sync mode: dynamic-password PAKE pairing, implementation status per batch
- Self-Host Server – self-hosting guide (deploy, env vars, API endpoints)
- SSH Agent Features – complete SSH agent documentation
- SSH Agent README – SSH agent quick start
- SSH Agent Testing – comprehensive testing guide
- Threat Model – security boundary and periodic review checklist
- Supply Chain Security – dependency security checks
Priority policy: the password-manager track targets 1Password parity first; wallet work stays experimental and deferred until that foundation is proven (wallet security requirements are higher and get a dedicated design pass).
- Monorepo, core library, workspace v2, audit logging, export/import (gzip + encryption)
- SSH agent with a full policy engine (known_hosts, rate limits, per-host/key rules, biometric gating)
- Browser extension + native messaging bridge (autofill MVP, domain policies, phishing resistance)
- CLI parity: CRUD, TOTP, password generator, TUI, non-interactive CI mode
- Wallet material (experimental): BTC/ETH/Solana derivation + signing on audited crates (rust-bitcoin/alloy)
- Passkeys (WebAuthn) storage + autofill
- Watchtower-class health checks (weak/reused/expired, breach checks)
- Desktop app data wiring and polished UI
- Optional sync/automation service with a local-first design (E2EE sync, accounts, backups, pairing relay)
- Sync group mode (default sync): dynamic-password PAKE pairing, instruction-stream sync, three relay forms (S1 protocol + relay done; desktop wiring and S2+ in progress)
- Wallet graduation: design doc, signing confirmations, PSBT, keystore JSON (after parity)
- Read
docs/CONTRIBUTING.mdfor Conventional Commits and PR expectations. - Fork the repo and create a feature branch (for example,
git checkout -b feat/cli-edit). - Follow Conventional Commits when writing PR/commit titles, e.g.
feat(cli): add credential filters. - Push your branch and open a Pull Request. Make sure
make lint-allandmake test-allboth pass.
This project is released under the MIT License. See LICENSE for details.
Security note: Persona is evolving quickly, and APIs/storage formats may change. Avoid using it with production secrets until the interfaces stabilize.
Manage your digital selves. Switch identity material with confidence.




