Skip to content

feat: Run one command as another session - #303

Open
scotwells wants to merge 6 commits into
mainfrom
feat/302-session-override
Open

scotwells wants to merge 6 commits into
mainfrom
feat/302-session-override

Conversation

@scotwells

@scotwells scotwells commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

You can now run a single command as any signed-in account by passing --session or setting DATUM_SESSION, and the active session stays as it was.

The value is a session name or an email signed in on one endpoint, the command uses that session's last context unless you name a scope, and plugins run this way act as that session too.

An email on several endpoints, or a value that matches nothing, fails and lists the sessions to choose from, while a stale DATUM_SESSION left in your shell only stops commands that need a session. This builds on the endpoint switching from #301.

$ datumctl whoami --session swells@datum.net@api.staging.env.datum.net
User:         Scot Wells (swells@datum.net)
Session:      swells@datum.net@api.staging.env.datum.net (from --session; the active session is unchanged)
Endpoint:     api.staging.env.datum.net
Context:      datum/datum-cloud
Organization: datum
Project:      datum-cloud

$ DATUM_SESSION=alice@example.com datumctl whoami
User:         Alice Example (alice@example.com)
Session:      alice@example.com@api.datum.net (from DATUM_SESSION; the active session is unchanged)
Context:      (none)
  Pass --project or --organization to choose a scope for this session.

$ datumctl whoami --session swells@datum.net
error: swells@datum.net is signed in on more than one endpoint, so --session swells@datum.net is ambiguous.
Name the session instead:
  --session swells@datum.net@api.datum.net
  --session swells@datum.net@api.staging.env.datum.net

$ DATUM_SESSION=gone@example.com datumctl version --client
Client Version: v0.0.0-master+$Format:%H$
Kustomize Version: v5.7.1

$ DATUM_SESSION=gone@example.com datumctl whoami
error: No session matches DATUM_SESSION gone@example.com.
Valid sessions:
  swells@datum.net@api.datum.net
  swells@datum.net@api.staging.env.datum.net
Pass a session name, or an email signed in on one endpoint. Run 'datumctl auth list' to see accounts.

$ datumctl auth switch alice@example.com --session swells@datum.net@api.staging.env.datum.net
error: 'datumctl auth switch' changes the active session, so it does not accept --session.
Run it without --session. It also ignores DATUM_SESSION.

Test plan

  • A command with --session or DATUM_SESSION shows that account and its last context, and the next plain command shows the active account again
  • A shared email or unknown value fails and lists the valid sessions, while a stale DATUM_SESSION leaves version, help, completion and plugin listing working
  • A plugin run with --session receives that session and its API host, and a datumctl it calls acts as that session
  • login, logout, auth switch and ctx use refuse --session, and auth get-token --session <name> works as before

Fixes #302

🤖 Generated with Claude Code

scotwells and others added 4 commits September 25, 2026 14:20
Every command ran as the active session, so reaching another account
or environment meant running 'auth switch' before and after. Scripts,
CI jobs and agents that touch production and staging in one run had
to change shared state, and anything running at the same time saw
the switch.

A global --session flag and the DATUM_SESSION environment variable
now pick the session for one process. The value is a session name
(email@api-host) or an email signed in on one endpoint; an ambiguous
or unknown value fails with the valid choices. The flag wins over the
variable. The command uses that session's last context unless a
scope flag or DATUM_PROJECT/DATUM_ORGANIZATION names one.

The override is held in memory in datumconfig and consulted by
ActiveSessionEntry and CurrentContextEntry, which every reader of the
active session already goes through, so no caller can miss it. It is
not a config field, so saving the config never persists it; the
console's context switcher keeps its pick in memory under an override.

login, logout, auth switch and ctx use change the active session, so
they reject --session and ignore DATUM_SESSION. auth get-token keeps
its own --session flag, which shadows the global one, so kubeconfig
exec entries resolve exactly as before. Plugin forwarding strips a
leading --session before the plugin name and resolves the session
first, so plugins get its name and API host and a datumctl they call
back into inherits it.

Fixes #302

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Reviewers flagged that datumctl sets DATUM_SESSION for plugins and
also reads it back, which looked like a hidden dependency. It is
intentional: it lets a plugin's own datumctl calls act as the same
session. Document that, and that a stale value (left over from a
previous logout, or inherited this way) only breaks commands that
actually need a session.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PersistentPreRunE validated --session and DATUM_SESSION the same way,
against the config file, before every command ran. A stale
DATUM_SESSION — left behind by a previous logout, or inherited from a
plugin's environment — made session-independent commands like
`version --client`, `plugin list`, and `completion bash` fail, even
though they never touch the active session.

--session is a mistake in this one invocation, so it still fails
immediately. DATUM_SESSION is recorded without validating it, and
resolved only the first time something consults the active session:
ConfigV1Beta1.ActiveSessionEntryE / CurrentContextEntryE, the
error-returning counterparts of the existing choke point, used by the
factory's REST config path, GetUserKeyForCurrentSession, whoami, and
plugin env injection. A command that never needs a session now
succeeds regardless of DATUM_SESSION; one that does gets the same
list-of-choices UserError a bad --session gives.

Bare `datumctl` reads the session to render its landing page, so a
stale DATUM_SESSION there prints a note and falls back to the real
active session rather than failing a command with nothing to retry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
"datumctl <plugin> <subcmd> --session X" failed with the plugin's own
"unknown flag: --session", because only a --session placed before the
plugin name was consumed by datumctl; anywhere else it was forwarded as
one of the plugin's arguments. That pointed users at the wrong component
and pushed them toward switching their active session instead, which is
exactly what the flag exists to avoid.

datumctl now takes --session out of a plugin command line wherever it
appears and turns it into the DATUM_SESSION (and API host) the plugin
already understands. Arguments after a bare "--" still belong to the
plugin. The flag continues to beat DATUM_SESSION, and --session with no
value now fails with datumctl's own message rather than quietly running
as the active session.

Fixes #304

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@scotwells
scotwells requested a review from a team October 1, 2026 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Reaching another account requires switching the active session

3 participants