A native Bitwarden & Vaultwarden client for Windows - KeePass-style auto-type, SSH agent and passkeys.
VaultType gives Bitwarden a global auto-type hotkey - the feature power users miss from KeePass. Press a shortcut and it types your username, password and TOTP into any window: desktop applications and browsers. The same shortcut fills checkout and registration forms from the cards and identities in your vault, matching each form field by its label. Beyond auto-type, it can serve the SSH keys stored in your vault through the Windows OpenSSH agent, and act as a Windows 11 passkey provider (experimental).
VaultType is a native Bitwarden client: it speaks the Bitwarden server API directly and performs all cryptography in-process - no Bitwarden CLI, no browser extension, no helper processes. The entire app is a single hardened executable that is built to never persist your secrets.
Important
VaultType is an independent, unofficial project. It is not affiliated with, endorsed by, or sponsored by Bitwarden Inc. "Bitwarden" and "Vaultwarden" are trademarks of their respective owners. VaultType implements the Bitwarden client protocol and connects only to the server you configure - your self-hosted Vaultwarden/Bitwarden or the bitwarden.com cloud.
- Features
- Screenshots
- Security model
- Requirements
- Installation
- Configuration
- Usage
- Updates
- Auto-type sequences
- SSH agent
- Passkeys
- Languages
- Building from source
- Contributing
- Support
- License
- Global hotkey (default
Ctrl+Alt+A) opens a context-aware entry picker. - KeePass-style picker - logins for the active window/URL are listed first; if there are none, it says so instead of dumping the whole vault on you. Identities and cards always follow below, since they aren't tied to a site. Search the whole vault at any time.
- Auto-type the full sequence (username → Tab → password → Enter), or username / password / TOTP only - with per-entry custom sequences.
- Cards and identities - fill checkout and registration forms from your vault. VaultType matches the form's mandatory fields against the entry by their labels and fills what fits, in the order the page uses them - no blind tabbing, so nothing lands in the wrong box. Your own custom fields are matched by name, and a split street/house-number form is handled.
- Copy to clipboard (right-click) for every field of an entry, with the clipboard cleared automatically after a timeout.
- Learn associations - pick a non-suggested entry and VaultType offers to remember the current site or app for next time.
- Multiple accounts - keep several vaults side by side (say a personal Vaultwarden and a work Bitwarden cloud). Unlock as many as you like; the picker merges their entries and tags each with a coloured account badge. Locked accounts show up as chips you can unlock on the spot, without leaving the picker - the one you used most recently is offered first. Each vault keeps its own session and its own encryption key.
- Native vault client - VaultType talks to the Bitwarden/Vaultwarden API itself (PBKDF2 and Argon2id KDF, API-key login, two-factor via authenticator app, email, YubiKey or Duo). No Bitwarden CLI to download, verify or keep updated.
- SSH agent - serve the SSH keys stored in your vault over the standard Windows OpenSSH agent
pipe;
ssh/gitjust work, with an optional confirmation for every signature. - Passkey provider (experimental, packaged edition only) - register VaultType as a Windows 11 passkey provider and use the FIDO2 credentials in your vault for website sign-ins, gated behind Windows Hello.
- PIN unlock - unlock with a short PIN instead of the full master password, Bitwarden-style (wrong-PIN limit, optional "require master password after restart").
- Local TOTP generation (RFC 6238, plus Steam Guard) - no clipboard, no extra network calls.
- Real favicons served by your own server (
/icons), cached locally - no third-party icon service is contacted. - Auto-lock after inactivity (default 30 minutes); it also re-locks after the computer wakes from sleep or standby, since real time keeps counting.
- Master password reprompt - entries flagged in Bitwarden as "ask for master password" are re-confirmed before any action on them, including SSH keys and passkeys.
- Multilingual - ships in 11 languages, follows your Windows display language automatically.
- Clean dark interface, runs quietly in the system tray.
The picker is context-aware: logins for the active window or URL come first, with identities and cards in their own sections below, and you can search the whole vault at any time. Every window shares the same clean, dark interface.
VaultType is designed to make it as hard as possible to leak, intercept or scrape your master password or vault data.
- Everything happens in one process. Login, sync and all vault cryptography are implemented natively (PBKDF2-SHA256 / Argon2id key derivation, AES-256-CBC + HMAC verification, RSA key unwrapping). Your master password never crosses a process boundary, a command line or an environment block - there is no CLI child process anymore.
- Master password (and PIN) only ever exist as a
SecureString, marshalled into locked, non-paged memory (VirtualLock) for the moment of key derivation, then zeroed. They are discarded immediately after unlocking and are not kept for the session. - Vault secrets in RAM (passwords, TOTP seeds, SSH and passkey private keys) are stored AES-256-GCM encrypted under an ephemeral key held in locked memory. Plaintext exists only for the milliseconds needed to type or sign, inside a locked buffer that is then zeroed. Locking wipes the key, rendering any leftover ciphertext useless.
- Nothing decrypted touches the disk. Per account, only the key envelopes needed to unlock
(master-key-wrapped user key, DPAPI-sealed refresh token, optional PIN envelope) plus non-secret
metadata are stored under
%LOCALAPPDATA%\VaultType- a folder whose ACL is restricted to your user. Vault items themselves are re-fetched from the server on every unlock. - Windows are hidden from screen capture (
WDA_EXCLUDEFROMCAPTURE), legacy DLL/hook injection is blocked (ProcessExtensionPointDisablePolicy), and the app refuses to run under a debugger. - Auto-type aborts instantly if focus leaves the target window - no stray characters end up in the wrong place, and nothing is typed if focus cannot be restored to the target. Card and identity sequences also abort when a field cannot be located, instead of typing into whatever came next, and the caret is confirmed to sit in the intended field before the first keystroke goes out.
- Values are only ever typed, never written through the accessibility interface. That interface is used to find and focus a field; setting a value through it would require handing the secret over as an ordinary managed string, bypassing the locked-buffer handling above.
- No clipboard is used for typing. The optional copy actions are the only clipboard use, and they self-clear (only if the clipboard still holds what VaultType put there).
- PIN unlock is rate-limited: five wrong PINs destroy the PIN envelope and force the master password. With require master password after restart (the default) the envelope only ever lives in RAM.
- Minimal supply chain: a single Microsoft-published NuGet package (
System.Formats.Cbor). Argon2id and Ed25519 are implemented in VaultType itself instead of pulling third-party DLLs - which also means the app runs on WDAC-locked machines that only allow Microsoft-signed binaries. - The application opens no network connections except to your configured vault server (API + favicons, the latter can be disabled) and the Check for updates action (a version check against GitHub). That check runs when you ask for it; the daily background check is a setting you switch on, off by default.
Note
No user-space password manager - VaultType or KeePass - can fully defend against an attacker who already runs code as your Windows user (kernel keyloggers, memory scraping). These measures shrink the attack surface to brief, well-contained windows; they are not absolute.
- Windows 10 or 11 (x64) - the passkey provider additionally needs Windows 11 24H2
- A Bitwarden or self-hosted Vaultwarden account
That's it. Release builds are self-contained - the .NET runtime is baked into the single
.exe, and the Bitwarden client is built in, so there is nothing else to install or download.
(To build from source you need the
.NET 10 SDK instead.)
Pick one of three ways to install:
- Microsoft Store (recommended) - get VaultType from the Store. Store-signed (no SmartScreen warning), updates automatically, and it is the packaged edition - the only one that can act as a Windows passkey provider.
- Installer -
VaultType-<version>-Setup.exefrom the latest release. Installs VaultType into your user profile with a Start-menu shortcut and an uninstaller; no admin rights needed. You can delete the downloaded setup afterwards. - Portable -
VaultType-<version>-win-x64.zipfrom the latest release (containsVaultType.exeplus the license and third-party notices). A single self-contained file you run directly; keep it somewhere permanent (not your Downloads folder, where it's easy to delete by accident).
Then, either way:
- Run it. For the GitHub builds, Windows may show a SmartScreen warning because they aren't code-signed (there is currently no code-signing certificate for this project) - click More info -> Run anyway. The Store build is signed by the Store and starts without a warning.
- Sign in: pick Bitwarden.com (US), Bitwarden.eu (EU), Bitwarden (self-hosted) or Vaultwarden (self-hosted) and enter your details. If your account has two-factor authentication, choose the method (authenticator app, email, YubiKey, Duo) and enter the code. You can also pick how to unlock in the future: master password or a PIN.
- Optional: add more accounts any time via Add account in the tray menu or in Settings, and enable the SSH agent or passkey provider under Settings -> Integration.
Note
The Bitwarden cloud comes in two regions - US (bitwarden.com) and EU (bitwarden.eu);
pick the one your account was created in, they are separate. Signing in there uses a personal
API key by default: the cloud login is protected by a CAPTCHA that a desktop app cannot solve,
so an API key is the reliable way in (it also avoids the 2FA prompt). Create one in the Bitwarden
web vault under Account settings -> Security -> Keys -> View API key, then paste the client ID
and secret together with your account email (it salts the key derivation) - the master password
is still required, it protects your keys. Self-hosted Vaultwarden has no such CAPTCHA, so it
simply uses your email and master password.
Everything below is adjustable in the Settings window; the file itself lives in
%LOCALAPPDATA%\VaultType\config.json - no secrets are stored there:
| Key | Default | Description |
|---|---|---|
Accounts |
[] |
Your configured vaults (name, badge colour, server, email, unlock method) - managed in Settings, no secrets. Each account's session envelope lives in its own accounts\<id>\ folder |
Hotkey |
Ctrl+Alt+A |
Global hotkey |
Language |
auto |
UI language (auto follows Windows) |
IdleTimeoutMinutes |
30 |
Auto-lock after inactivity (0 = never) |
TypingDelayMs |
25 |
Delay between simulated keystrokes (apps that decode injected keystrokes asynchronously garble the text below roughly 15 ms) |
ClearFieldBeforeTyping |
true |
Select the field (Ctrl+A) before typing |
FillRequiredFieldsOnly |
true |
When filling from a card or identity, only fill fields the form marks as mandatory |
AutoTypeFieldName |
auto-type |
Name of the custom field holding a per-entry sequence |
FieldAliases |
{} |
Extra spellings for the field lookup, keyed by field group, e.g. {"CardCode": ["kartenprüfwert"]} |
DefaultUriMatch |
0 |
Fallback URL match for entries with no rule of their own (0 = base domain, 1 = host, 2 = exact URL) |
ShowIcons |
true |
Favicons from your own server (false = letter avatars, offline) |
ClipboardClearSeconds |
12 |
Clear the clipboard this long after a copy (0 = never) |
HonorMasterPasswordReprompt |
true |
Re-confirm entries flagged "ask for master password" in Bitwarden |
ExcludeFromScreenCapture |
true |
Hide windows from screenshots |
AntiDebugger |
true |
Exit if a debugger attaches |
SshAgentEnabled |
false |
Serve vault SSH keys on the OpenSSH agent pipe |
SshConfirmEachUse |
true |
Ask before every SSH signature |
SshDisabledKeys |
[] |
SSH keys switched off in the agent (managed in the key list) |
PasskeyProviderEnabled |
false |
Register as a Windows 11 passkey provider (experimental) |
PasskeyRequireHello |
true |
Gate passkey use behind Windows Hello |
EnableTrayClick |
true |
React to a left-click on the tray icon (needs a lightweight foreground hook); false = hotkey only |
TrayClickAction |
2 |
Tray left-click: 0 = menu, 1 = auto-type, 2 = settings |
Autostart |
true |
Start with Windows (per-user) |
Press the hotkey, unlock once, then in the picker:
| Input | Action |
|---|---|
↑ ↓ |
Move selection |
Enter |
Auto-type the entry's sequence |
Ctrl+U / Ctrl+P / Ctrl+T |
Type username / password / TOTP only (logins) |
| Right-click | Type or copy an individual field |
| Type | Search the whole vault |
Esc |
Cancel |
Cards and identities have too many fields to bind to shortcuts, so their individual fields live in
the right-click menu. Pressing Enter on them runs their default sequence just like on a login.
For desktop apps, add a URI like app://programname.exe to the entry - or simply let VaultType
offer to remember it the first time. Two more URI forms work for desktop apps: a plain
programname.exe also matches the executable name, and title:<text> matches whenever the
foreground window title contains <text> (case-insensitive) - handy for apps like PuTTY where
the window title carries the server or user name. An entry is offered as soon as any one of its
URIs matches.
With several accounts, the picker lists the entries of every unlocked vault together, each
tagged with its account badge. Any vault that is still locked appears as a chip at the bottom -
click it (or press Enter on an empty search) to unlock just that account and fold its entries in,
without closing the picker.
If no vault is open, the hotkey goes straight to the unlock dialog instead of showing an empty picker, with the vault you used most recently preselected. Its account row switches to another vault if you want a different one.
The tray menu shows each account with its state (entry count, or a lock you can click to unlock), and offers Auto-type, Sync, Lock per account or Lock all, Check for updates, Settings and Exit. The check reports back in a window rather than a notification, so it works just as well with notifications switched off for the app.
The installer and portable editions check GitHub for a newer release when you ask them to - from the tray menu or from Settings. Switch Check for updates automatically on under Settings > General and VaultType additionally looks once a day in the background; it is off by default, and never runs in the Store edition, which the Microsoft Store keeps current by itself.
Once a newer release is known, the tray icon carries a red dot, the tray menu names the version instead of offering another check, and the Settings updates row links straight to the download. Those stay put until you have installed it, so the news does not depend on catching a notification. The version is announced once as a notification too - only once per release, and only if you enabled the background check.
Pressing Enter on an entry runs its default sequence, which depends on the entry type:
| Entry type | Default sequence |
|---|---|
| Login | {USERNAME}{TAB}{PASSWORD}{ENTER} |
| Card | fills the mandatory card fields the form asks for |
| Identity | fills the mandatory identity fields the form asks for |
Cards and identities have no fixed sequence. VaultType reads which fields the form actually exposes, then fills every one of them the entry has a value for, in the order they appear on the page - see field lookup. One checkout wants number, expiry and code; the next also asks for the cardholder. One order form has a single name box; the next has separate first and last name fields plus a full address block. A fixed list of keystrokes cannot serve both.
Nothing is guessed: a field whose label VaultType doesn't recognise is skipped rather than filled with whatever came next, and if no field matches the entry at all, it says so instead of leaving an empty form behind.
Card and identity sequences also deliberately do not end with Enter: on a login form Enter submits, which is what you want, but in the middle of a checkout it would send a half-filled order.
You can override the default per entry: add a custom text field named auto-type to the
Bitwarden entry and set its value to your own sequence. The selected row in the picker previews the
sequence it will run, so you can see what will happen before pressing Enter. Ctrl+U / Ctrl+P /
Ctrl+T always type a single field, regardless of the custom sequence.
Supported placeholders (case-insensitive):
| Placeholder | Types |
|---|---|
{USERNAME} / {USER} / {LOGIN} |
the username (on an identity: its own username field) |
{PASSWORD} / {PASS} |
the password |
{TOTP} / {OTP} |
the current TOTP code |
{FIELD "..."} |
moves the caret to a named field first - see field lookup |
{TAB} {ENTER} {SPACE} |
those keys |
{CLEARFIELD} |
selects the field first (Ctrl+A) |
{DELAY 200} |
waits 200 ms (also {WAIT} / {SLEEP}) |
| any other text | typed literally |
Card placeholders:
| Placeholder | Types |
|---|---|
{CARDNUMBER} / {CARDNUM} |
the card number |
{CARDCODE} / {CVV} / {CVC} |
the security code |
{CARDHOLDER} / {CARDNAME} |
the cardholder name |
{CARDBRAND} |
the brand (Visa, Mastercard, …) |
{CARDEXPMONTH} / {EXPMONTH} |
expiry month, padded to two digits (01) |
{CARDEXPMONTHRAW} |
expiry month exactly as stored (1) |
{CARDEXPYEAR} / {EXPYEAR} |
expiry year in full (2029) |
{CARDEXPYEAR2} / {EXPYEAR2} |
expiry year, two digits (29) |
{CARDEXP} / {CARDEXPIRY} |
month and year combined (07/29) |
Identity placeholders: {TITLE} {FIRSTNAME} {MIDDLENAME} {LASTNAME} {FULLNAME}
{COMPANY} {EMAIL} {PHONE} {ADDRESS1} {ADDRESS2} {ADDRESS3} {CITY} {STATE}
{POSTALCODE} / {ZIP} {COUNTRY} {SSN} {PASSPORT} {LICENSE}
Example for a two-step login where the username comes first and the password field only appears a moment later (the way PayPal and some others do it):
{USERNAME}{ENTER}{DELAY 1500}{PASSWORD}{ENTER}
Example for a checkout that wants the security code before the expiry date:
{FIELD "card number"}{CARDNUMBER}{FIELD "CVV"}{CARDCODE}{FIELD "expiry"}{CARDEXP}
The field name (auto-type) can be changed via AutoTypeFieldName in config.json.
Payment and registration forms differ far too much for a fixed chain of tabs to be safe - one shop asks for number, expiry, code; the next swaps the last two; a third puts month and year in one box. So instead of tabbing blindly, VaultType matches the form against the entry: it reads the labels of the form's input fields, works out which of them it recognises, and fills those the entry has a value for. Fields it doesn't recognise are left alone.
Only mandatory fields are filled by default. A field counts as mandatory when the form marks it as required or puts an asterisk in its label. Optional extras - a second phone number, a delivery note - stay empty. Turn Settings → Auto-Type → Only mandatory fields off to fill every recognised field instead. Forms that mark nothing at all (some only validate in JavaScript) are filled completely either way, since otherwise nothing would happen on them.
Two pairs are treated as alternatives, so nothing gets filled twice: a combined name box rules out
separate first/last name fields (and vice versa), as does a combined MM/YY box against separate
month and year fields.
Street and house number are stored as one line by Bitwarden. If the form has a separate house number field, the line is split - "Beispielweg 12a" becomes street Beispielweg and number 12a. Numbers at the front ("12 Main Street") are handled too. If no number can be identified, the whole line goes into the street field and the number field is left for you, rather than splitting at a guess.
Your own custom fields work too. Any text or hidden field you add to a card or identity in Bitwarden is matched against the form by its name. Call a field Date of birth in the vault and it fills the form's Date of birth box - no configuration needed, the name is the link. This is how you cover anything the builtin groups don't. The field holding your auto-type sequence is excluded.
{FIELD "..."} does the same thing explicitly. You name the concept, not the form's wording -
VaultType knows the common spellings and searches for all of them, so these are equivalent:
{FIELD "CVV"} {FIELD "Prüfziffer"} {FIELD "security code"} {FIELD "CVC"}
Both the visible label and the form's internal field identifier are matched, which makes the lookup work on foreign-language forms too. Searching starts at the field the caret is currently in, so clicking into the right section of a long form before pressing the hotkey picks that section.
A term VaultType doesn't recognise is searched for literally, and unusual wording can be taught
through FieldAliases in config.json:
"FieldAliases": {
"CardCode": ["kartenprüfwert", "kk-prüfnummer"],
"PostalCode": ["postnummer"]
}Group names are CardNumber, CardHolder, CardExpMonth, CardExpYear, CardExpiry,
CardCode, Title, FirstName, MiddleName, LastName, FullName, Company, Email,
Phone, Username, Address1, Address2, Address3, StreetName, HouseNumber, City,
State, PostalCode, Country, Ssn, Passport and License.
Note
The lookup reads the target window's field structure through the Windows accessibility interface - the same mechanism already used to read a browser's address bar. Applications that expose nothing there (some Qt and Java programs) can't be filled this way; VaultType says so instead of guessing. Nothing is ever written through that interface: values are always typed as keystrokes, so secrets keep going through the same locked-memory path as before.
Bitwarden vaults can store SSH keys as their own item type. Enable the agent under
Settings -> Integration -> SSH agent and VaultType serves those keys on the standard Windows
OpenSSH agent pipe (\\.\pipe\openssh-ssh-agent) - ssh, git and every other OpenSSH-aware
tool pick them up automatically, no key files on disk.

Manage keys - every SSH key across your vaults, with fingerprint, copy-public-key button and a per-key agent toggle.
- Ed25519 and RSA keys are supported (rsa-sha2-256/512 signatures).
- Confirm each use (on by default) pops a dialog before every signature, naming the requesting key - nothing signs silently.
- Locked vaults still advertise their keys: a signature request for a key in a locked vault brings up the unlock window first, then signs. You don't have to pre-unlock before pushing.
- Manage keys opens a list of every SSH key across your vaults, with its fingerprint, a copy-public-key button, and a per-key toggle to keep individual keys out of the agent.
Note
The built-in Windows OpenSSH Authentication Agent service uses the same pipe. If it is
running, VaultType cannot bind and will tell you - stop it once with
Stop-Service ssh-agent (and set it to Disabled so it stays off).
VaultType can register as a Windows 11 passkey provider: passkeys stored in your vault then show up in the native Windows passkey dialog, and websites can create new passkeys directly into your vault. Use is gated behind Windows Hello by default (or an explicit confirmation dialog without it), and passkeys in locked vaults trigger the unlock window first - just like the SSH agent.
Important
Passkeys only work in the packaged edition -
install VaultType from the Microsoft Store.
Windows activates passkey providers exclusively for apps with a package identity (MSIX), which
the installer and portable builds from GitHub do not have - in those builds the toggle under
Settings -> Integration is greyed out with a note saying exactly that. Alternatively you can
build the MSIX package yourself (packaging/msix/build-msix.ps1). Windows 11 24H2 or later is
required either way.
VaultType is available in: English, Deutsch, Español, Français, Italiano, 日本語, Nederlands, Polski, Português (Brasil), Русский, 简体中文. By default the interface follows your Windows display language (falling back to English), or you can pick a language explicitly under Settings -> General -> Language. Changing the language restarts VaultType so the new strings take effect.
Needs the .NET 10 SDK.
dotnet publish src/VaultType/VaultType.csproj -c Release -o distThat gives you a normal framework-dependent dist/VaultType.exe. To reproduce the self-contained
single-file build the release workflow ships:
dotnet publish src/VaultType/VaultType.csproj -c Release -r win-x64 --self-contained true `
-p:PublishSingleFile=true -p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=trueTo try the passkey provider, build and install the dev-signed MSIX
package with packaging/msix/build-msix.ps1 (needs the Windows SDK).
Issues and pull requests are welcome. Please keep changes focused and describe the motivation.
Commit messages follow Conventional Commits (feat:,
fix:, perf:, ...) - the release changelog is generated from them.
Translations can be added as a single JSON file under Localization/.
If VaultType is useful to you, you can support development on Ko-fi:
Apache License 2.0 with the Commons Clause (you may use, modify and share it freely, but not sell it). See LICENSE.
Bundled third-party components (fonts, icon geometries, one Microsoft NuGet package, the .NET runtime in self-contained builds) are listed with their licenses in THIRD-PARTY-NOTICES.md. VaultType collects no data - see the privacy policy.





