Skip to content
Kosh Docs

Profiles

Keep separate, cryptographically isolated vaults for work, personal, and anything else.

A profile is a separate vault — its own file, its own master password, its own credentials.

Every Kosh command reads from and writes to the active profile only. Profiles never share keys, so a work profile and a personal profile stay cryptographically isolated from each other.


Each profile is a standalone encrypted SQLite file under ~/.kosh/profiles/. The profile name is simply the filename stem.

~/.kosh/
├── config.json # { "active_profile": "work" }
└── profiles/
├── default.db # vault + credentials, master password A
├── work.db # vault + credentials, master password B
└── personal.db # vault + credentials, master password C
  • ~/.kosh is created with 0700 permissions; config.json with 0600.
  • The active profile is recorded in ~/.kosh/config.json and persists across runs — once you switch, every later invocation uses that profile until you switch again.
  • The profile created on first use is called default.

Every line Kosh prints is prefixed with the active profile name:

(work) [✓] credential saved successfully
(work) [✗] incorrect master password
(work) [?] enter master password:

To list every profile you have:

Terminal window
kosh profile list
Profile Status
------- --------
> default active
work inactive
personal inactive

kosh profile list reads only filenames — it opens no vault and never asks for a master password. You can pass a substring to filter the list:

Terminal window
kosh profile list work

Terminal window
kosh profile create work

Kosh prompts you for the new profile’s master password twice, builds ~/.kosh/profiles/work.db, and then switches to it.

Three things worth knowing:

  • It switches to the new profile automatically. If you wanted to stay where you were, run kosh use <old-profile> afterwards.
  • You do not need kosh init afterwards. The vault is initialized as part of creation. kosh init is only needed for the very first profile.
  • The name is cleaned up first. Illegal characters are stripped and spaces become underscores, so the profile you get may not be named exactly what you typed — see Naming profiles.

If building the vault fails, Kosh removes the partially created profile file. The active profile is untouched, because Kosh only switches once the vault exists, so you are left where you started and free to retry the same name.


Terminal window
kosh use work # switch directly
kosh use # interactive picker

With no arguments, kosh use opens a picker: type to filter, / to navigate, enter to select, esc to cancel.

kosh use does not create profiles. Switching to a name that does not exist fails with profile does not exist — create it with kosh profile create first.

The name is matched ignoring case but is not cleaned up the way kosh profile create cleans it. kosh use My-Profile! will not find My_Profile — give it the name as kosh profile list shows it.

No master password is required to switch. The password is only requested when a command actually needs to open the vault.


Terminal window
kosh copy 42 personal

This takes credential 42 from the active profile, decrypts it with the active profile’s master password, and re-encrypts it for the personal profile using a fresh ephemeral keypair and nonce under that profile’s public key.

  • The original is left untouched — this is a copy, not a move.
  • The target profile’s vault must already be initialized.
  • Copying into the currently active profile is rejected.
  • Get the ID from kosh list and the profile names from kosh profile list.

If the target profile already holds a credential with the same (label, user) pair, Kosh shows a caution block and requires you to type overwrite <label> <user> in <target> before proceeding. The overwritten secret is unrecoverable.


Terminal window
kosh use default # you cannot delete the active profile
kosh profile delete work

Deleting a profile destroys the vault and every credential in it. Kosh gates it carefully:

  1. Refuses if the profile does not exist.
  2. Refuses to delete the active profile — switch away with kosh use first. This holds regardless of case: deleting WORK while work is active is still rejected.
  3. Prompts for that profile’s own master password and verifies it, to prove ownership.
  4. Prints a caution block.
  5. Requires you to type the exact phrase permanently delete <name> with credentials. Anything else cancels the operation.

Note that while Kosh is working on the target profile, the output prefix shows the target’s name rather than the active one — so the password prompt cannot be mistaken for a request for the wrong password:

(personal) [?] enter master password:
| /!\ CAUTION: DESTRUCTIVE ACTION
| This profile and every credential in it will be deleted PERMANENTLY.
| The operation is IRREVERSIBLE and the secrets are IRRECOVERABLE.

The vault file is then overwritten with cryptographically random bytes and synced to disk before it is unlinked — not simply removed from the directory.


Profile names may contain letters, digits, underscores and hyphens. Spaces are converted to underscores and anything else is removed, so pick a simple name and Kosh will keep it as-is.

kosh profile create does not take the name literally — it cleans it up first, and the cleaned name is the real one: it becomes the filename, the (prefix) on every output line, and the name every other command must be given afterwards.

In order:

  1. Accents are folded to ASCIIcafé becomes cafe.
  2. Surrounding whitespace is trimmed.
  3. Anything outside A–Z a–z 0–9 _ - space is deleted — not replaced, deleted.
  4. Runs of whitespace become a single underscore.
  5. Runs of underscores collapse to one; runs of hyphens collapse to one.
  6. Leading and trailing _ and - are stripped.
  7. Capped at 252 characters (the 255-character filename limit, less .db).

Case is preserved. MyProfile stays MyProfile — Kosh never lowercases your name. Lookup ignores case, but the stored spelling is whatever survived this process.

You type You get
work work
My_profile $100 My_profile_100
work-white-space work-white-space
--YourProfile__ YourProfile
work__main work_main
work main work_main
café cafe
a × 300 a × 252
"" rejectedinvalid profile name
$__## rejectedinvalid profile name
nul, lpt2, __lpt2 rejectedprofile name is reserved by the operating system
lpt23 lpt23 — only exact reserved names are rejected

These are rejected outright: con, prn, aux, nul, com1com9, lpt1lpt9.

They are Windows device names, and Kosh refuses them on Linux and macOS too, where the operating system would accept them. That is deliberate — it keeps a ~/.kosh/profiles directory portable between machines.

The check runs on the cleaned name, so __lpt2 is rejected as well: it cleans up to lpt2.


There is no kosh profile rename. Because a profile’s name is its filename stem, renaming the .db file does technically rename the profile — but this is an unsupported stopgap, not a feature, and it is not recommended.

A proper profile rename is not implemented yet. Until it is, the supported route is to create a new profile and copy the credentials across one ID at a time.


Every command that names a profile — kosh use, kosh profile create, kosh profile list, kosh profile delete and kosh copy — looks it up ignoring case:

Terminal window
kosh use WORK # all three find a profile
kosh use work # stored as "Work"
kosh use Work
  • Surrounding whitespace is ignored too — kosh use " work " works.
  • The match is still whole-name, not a prefix or substring. kosh use wor fails with profile does not exist.
  • Whichever spelling you type, Kosh switches to, opens or deletes the profile under the name it is stored as — and that is the name shown in kosh profile list and in the (profile) prefix.
  • kosh profile list <filter> also ignores case, so kosh profile list WORK matches work_main.

  • There is no profile rename and no profile export. If you are unhappy with the name a profile ended up with, the supported route is to create a new one and kosh copy the credentials across, one ID at a time — see Renaming a profile.
  • kosh copy accepts only a numeric credential ID and an exact profile name — there is no interactive credential or profile picker for it yet.
  • There is no bulk or multi-credential copy.
  • The picker in kosh use uses plain substring filtering, not the weighted fuzzy scorer that powers kosh search.