Skip to content

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 vaultpersonal
your family org's default vaultfamily
your business/enterprise org's default vaultcompany (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 vaultthat 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 list or 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/password

A 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/PIN

Errors

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

CodeMeaning
0Success
1General error
2Auth — not signed in, or the session expired
3Entitlement — plan doesn't include this feature (or, transiently, the server hasn't caught up — see the error text, which tells the two cases apart)
4Reference unresolvable — nothing ran/was written
5Grant denied or missing (device-flow approval denied; also read under an agent profile with no read capability — see Agent profiles)
6Vault locked — no active geslar unlock grant and no TTY to prompt in
126/127run: the child command exists but isn't executable / doesn't exist (shell convention)
128+Nrun: 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 same personal/family/company/work/vault-name address space as geslar:// references).
  • --allow-read opts the profile into the read capability (default profiles get run+inject only — 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 own agent-token namespace, 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/password

Every 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, inject and geslar:// 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.
  • read is blocked (exit 5) unless the profile has the read capability — checked live against the server on every invocation, never assumed from what you passed at create time.
  • No TTY and no active geslar unlock grant → exit 6, same as the human flow, no attempt to prompt.
  • geslar agent create/list/revoke refuse 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.