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.
How profiles are stored
Section titled “How profiles are stored”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~/.koshis created with0700permissions;config.jsonwith0600.- The active profile is recorded in
~/.kosh/config.jsonand 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.
Seeing which profile you are in
Section titled “Seeing which profile you are in”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:
kosh profile list Profile Status ------- --------> default active work inactive personal inactivekosh 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:
kosh profile list workCreating a profile
Section titled “Creating a profile”kosh profile create workKosh 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 initafterwards. The vault is initialized as part of creation.kosh initis 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.
Switching profiles
Section titled “Switching profiles”kosh use work # switch directlykosh use # interactive pickerWith 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.
Copying a credential between profiles
Section titled “Copying a credential between profiles”kosh copy 42 personalThis 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 listand the profile names fromkosh 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.
Deleting a profile
Section titled “Deleting a profile”kosh use default # you cannot delete the active profilekosh profile delete workDeleting a profile destroys the vault and every credential in it. Kosh gates it carefully:
- Refuses if the profile does not exist.
- Refuses to delete the active profile — switch away with
kosh usefirst. This holds regardless of case: deletingWORKwhileworkis active is still rejected. - Prompts for that profile’s own master password and verifies it, to prove ownership.
- Prints a caution block.
- 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.
Naming profiles
Section titled “Naming profiles”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.
What gets changed
Section titled “What gets changed”In order:
- Accents are folded to ASCII —
cafébecomescafe. - Surrounding whitespace is trimmed.
- Anything outside
A–Z a–z 0–9 _ - spaceis deleted — not replaced, deleted. - Runs of whitespace become a single underscore.
- Runs of underscores collapse to one; runs of hyphens collapse to one.
- Leading and trailing
_and-are stripped. - 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 |
"" |
rejected — invalid profile name |
$__## |
rejected — invalid profile name |
nul, lpt2, __lpt2 |
rejected — profile name is reserved by the operating system |
lpt23 |
lpt23 — only exact reserved names are rejected |
Reserved names
Section titled “Reserved names”These are rejected outright: con, prn, aux, nul, com1–com9, lpt1–lpt9.
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.
Renaming a profile
Section titled “Renaming a profile”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.
Names are matched without regard to case
Section titled “Names are matched without regard to case”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:
kosh use WORK # all three find a profilekosh 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 worfails withprofile 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 listand in the(profile)prefix. kosh profile list <filter>also ignores case, sokosh profile list WORKmatcheswork_main.
Current limitations
Section titled “Current limitations”- There is no
profile renameand noprofile export. If you are unhappy with the name a profile ended up with, the supported route is to create a new one andkosh copythe credentials across, one ID at a time — see Renaming a profile. kosh copyaccepts 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 useuses plain substring filtering, not the weighted fuzzy scorer that powerskosh search.