You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
imogen profiles --json prints access and refresh tokens to stdout #33
imogen profiles --json prints the stored access_token and refresh_token to stdout.
src/commands/session.rs serialises the whole Config with out.json(&config), and Config / Profile (src/config.rs) carry both tokens with skip_serializing_if only for None. So on any
logged-in machine:
imogen profiles --json
puts live bearer credentials into whatever consumes that stream — a pipe, a CI log, a shell
history, an agent transcript, a bug report.
The human-readable table immediately below it shows name, server and browser|token and no
secret, so the two audiences disagree about what is safe to print. That asymmetry is the tell:
the table's author clearly thought about it.
Expected
--json describes the profile without its credentials — name, server, auth kind, perhaps
expiry — matching what the table already shows. A token should require an explicit, separate,
deliberate request if it is ever wanted at all.
#[serde(skip_serializing)] on the token fields, or a dedicated view struct for this command, both
work. A view struct is the safer shape: it cannot regress when a field is added to Config later.
Affected repos
Only this one. Nothing on the wire changes.
Context
Found by the pre-release cumulative review of v0.2.2..HEAD. Pre-existing and not a regression —
the range touched session.rs only for the non-UTF-8 path fix — so it did not gate v0.3.0. Filed
rather than left because the repository is actively growing --json surfaces and pointing automation
at them, which is exactly the direction that turns this from latent into routine.
Related: CLAUDE.md's rule that every command answers twice — a person gets a table, --json gets the
API's own payload unrenamed. Here the machine audience gets strictly more than the person, and the
extra part is the secret.
A view struct rather than #[serde(skip_serializing)], for the reason the issue gives: the attribute has to be remembered by whoever adds the next credential to Config, while a struct that must be extended on purpose cannot leak one by omission. The regression test walks the keys of the serialised output case-insensitively for token/secret/password/credential rather than checking fields one by one, so a field added later is caught by name whatever it is called.
client_id, expires_in and obtained_at went too — signedInVia and expiresAt carry the same information — and the keys are camelCase now, like every other key the CLI synthesises.
Nothing needed a token via --json: login --json already answered with the credentials path, and nothing in the repo reads a token back out of a --json stream. session.rs was the only place that serialised a Config.
Nothing on the wire changed. This lands for the next release; main is ahead of v0.3.0.
Activity
ergofobe commentedon Sep 15, 2026
Fixed in #36, merged to
main.imogen profiles --jsonnow answers with aProfilesView— the same four things the table shows, plusexpiresAtwhere there is one:A view struct rather than
#[serde(skip_serializing)], for the reason the issue gives: the attribute has to be remembered by whoever adds the next credential toConfig, while a struct that must be extended on purpose cannot leak one by omission. The regression test walks the keys of the serialised output case-insensitively fortoken/secret/password/credentialrather than checking fields one by one, so a field added later is caught by name whatever it is called.client_id,expires_inandobtained_atwent too —signedInViaandexpiresAtcarry the same information — and the keys are camelCase now, like every other key the CLI synthesises.Nothing needed a token via
--json:login --jsonalready answered with the credentials path, and nothing in the repo reads a token back out of a--jsonstream.session.rswas the only place that serialised aConfig.Nothing on the wire changed. This lands for the next release;
mainis ahead of v0.3.0.