Appearance
geslar:// reference syntax
geslar://<vault>/<item>[/<field>]Resolution happens entirely inside the CLI process, after decrypting locally — the server never learns which vault, item, or field a reference asked for.
<vault>
Resolved in this order, case-insensitively:
| Want… | First segment |
|---|---|
| your personal vault | personal |
| your family org's default vault | family |
| your business/enterprise org's default vault | company (or work) |
| a specific org's default vault (you belong to more than one) | that org's name, e.g. Acme |
| a specific non-default vault | that vault's own name |
personal— canonical, use this in scripts/docs/CI.Osobno(Croatian for "personal") is a legacy alias kept working for backward compatibility.family— resolves to the default vault of your family-type org. Only deterministic if you belong to exactly one; if you belong to 2+, resolution fails with the org names listed and a suggestion to address one by its exact name instead.company/work— same idea, for a business or enterprise org (both count as "business" for this purpose). Same exactly-one-org rule.- An org's own default vault is never addressed by its stored placeholder name ("Obiteljska škrinja"/"Opća škrinja" server-side) — that name is never shown or matched anywhere, in
listor here. Address it by the org's name instead.
Token collisions are always an error, never a silent guess. If you have an actual vault or org literally named personal/family/company/work (e.g. a vault genuinely named "Personal"), the reference is ambiguous and resolution fails with a "rename one" error rather than silently picking one — same behavior as any other two vaults sharing a name.
Cross-org disambiguation via an org: qualifier is reserved syntax but not implemented in v1 — using it fails with a clear "not implemented" error rather than being silently ignored.
<item>
The item's display name, matched case-insensitively. Duplicate names within a vault are an error listing the colliding item ids — use the id: qualifier to disambiguate:
geslar://Work/id:0192f3ab-cdef-4444-8888-000000000001/passwordA literal / inside a vault or item name must be percent-encoded as %2F.
<field>
One of: username, password (default if omitted), totp (computes the current 6-digit code), url, notes, or any custom field's label (matched case-insensitively).
Examples
geslar://personal/GitHub/password
geslar://personal/GitHub/username
geslar://Work/AWS%20Prod/totp
geslar://Work/id:0192f3ab-cdef-4444-8888-000000000001/password
geslar://personal/Bank/PINErrors
Every resolution failure — unknown vault, unknown item, ambiguous name, empty field, malformed reference — produces a message with a "did you mean" suggestion where applicable, and never includes a resolved secret value, even incidentally (e.g. when reporting an unrelated failure for an item that also has a real value elsewhere).
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | General error |
2 | Auth — not signed in, or the session expired |
3 | Entitlement — plan doesn't include this feature (or, transiently, the server hasn't caught up — see the error text, which tells the two cases apart) |
4 | Reference unresolvable — nothing ran/was written |
5 | Grant denied or missing (device-flow approval denied; also read under an agent profile with no read capability — see Agent profiles) |
6 | Vault locked — no active geslar unlock grant and no TTY to prompt in |
126/127 | run: the child command exists but isn't executable / doesn't exist (shell convention) |
128+N | run: the child was terminated by signal N (e.g. 130 = SIGINT, shell convention) |
Agent profiles
Available since CLI v0.2.0.
Full model: spec-access-core.md (REV 1.2). Server side shipped in geslar-api #101; this section covers the CLI surface only.
An agent profile is a named, scoped machine credential — its own bearer token (gslr_agent_...), explicitly granted to one or more vaults by name, with capabilities that default to run+inject (never read, unless you opt in). Scope and expiry are fixed at creation — there is no "edit"; create a new profile instead.
Create
geslar agent create <name> --vault <name> [--vault <name>...] [--allow-read] [--expires 90d|never] [--show-token]- Requires an interactive terminal (TTY) — this is a human action, not scriptable. You'll be prompted for a fresh TOTP code (no-echo); recovery codes are not accepted.
--vault <name>is repeatable — pass it once per vault to grant (matches the samepersonal/family/company/work/vault-name address space asgeslar://references).--allow-readopts the profile into thereadcapability (default profiles getrun+injectonly — they can use a secret but never print it). You'll get an extra explicit confirmation prompt explaining what this means, since it's a step up from the default.--expires 90d(default if omitted) or--expires never(explicit opt-out — no expiry).- The plaintext token is shown only with
--show-token, and only once — it's not retrievable again afterward. It's always saved locally regardless (OS keychain / DPAPI / libsecret, under its ownagent-tokennamespace, separate from your own signin session).
List / revoke
geslar agent list
geslar agent revoke <name>revoke calls the server (deactivates the profile and its grants) and deletes the locally stored token — the profile stops working immediately either way, even if only one of the two succeeds.
Using a profile
GESLAR_AGENT=<name> geslar run --env-file .env -- your-command
geslar --agent <name> read geslar://Marketing/AWS/passwordEvery API call the CLI makes is then authenticated as that agent, not your own account:
- Vaults: only the ones the profile was actually granted show up —
geslar list,run,injectandgeslar://resolution all naturally only see (and only resolve against) the served set. A vault outside the profile's scope fails exactly like it doesn't exist. readis blocked (exit5) unless the profile has thereadcapability — checked live against the server on every invocation, never assumed from what you passed atcreatetime.- No TTY and no active
geslar unlockgrant → exit6, same as the human flow, no attempt to prompt. geslar agent create/list/revokerefuse to run under an active agent context — they're human-only actions.- If the vault's owner loses access (removed from the org, etc.), the agent's access to it stops at the same moment — this isn't cached anywhere client-side.