refactor(cli): unify token storage behind Store + add host/account switching#36830
Merged
Conversation
…itching Route all credential reads/writes through the Store interface so keychain and file backends share one code path. Add `use host` / `use account` commands for multi-account switching, with a zero-dependency arrow-key dropdown (replaces @inquirer/prompts, which broke under bun --compile). - login: blue dify spinner during device-flow poll; fail fast with a flag hint when host is omitted in a non-TTY (agent) context - select: custom keypress picker, restores raw mode / cursor on any exit including synchronous setup failure - hosts: remove() no longer clears the active host when a non-active account is removed Tests: 836 passing.
…-unify # Conflicts: # cli/src/commands/auth/login/login.test.ts # cli/src/commands/auth/login/login.ts
Registry.load() now always returns a Registry (empty when no config file exists) instead of Registry | undefined. The 'no config file' and 'no active account' states were handled identically by every caller, so they collapse into one signal: resolveActive() returning undefined. Callers drop the reg?. guards and the '?? Registry.empty(mode)' fallback. whoami and logout, which hand-reimplemented requireActive(), now call it directly.
Resolve conflicts from PR #36822 (absolute path refactor): keep Registry/ ActiveContext model from this branch, adopt @/ alias import style from main. Convert all remaining relative .js imports in branch-local files to @/ or @test/ aliases. Fix ./_strategies/index nested path to @/commands/ prefix.
Convert remaining relative .js imports in use/host, use/account, sys/io/select to @/ aliases. Fix perfectionist/sort-imports ordering in test and source files missed by the merge commit.
…ommands - auth list: table of all authenticated host+account pairs, supports -o json/yaml/name; replaces auth status (redundant with auth whoami for single-context view, no structured multi-context output) - use host --domain: switch active Dify instance interactively or by flag - use account --email: switch active account on current host - help account: add tips for auth list, use host, use account
…ers/
Single source of truth for all CLI output: framework/output.ts
(TablePrintable, FormattedPrintable) and framework/stream.ts (StreamPrinter).
- Move StreamPrinter type from printers/stream-printer.ts to framework/stream.ts
- Migrate run app blocking output to FormattedPrintable: AppRunObject now
implements text()+json() directly; mode-dispatch internalized
- Remove AppRunPrintFlags, TextPrintFlags, JsonYamlPrintFlags indirection;
strategies call stringifyOutput(formatted({...})) and streamPrinterFor() directly
- Migrate all handlers (get/app, get/member, get/workspace) to import
TableColumn from framework/output instead of printers/format-table
- Remove dead code: WorkspaceObject, workspaceTableHandler, payload-shape.ts
- Delete entire src/printers/ directory (15 files)
- Update ARD.md: document output protocol pattern, retire printer-chain section
…splay name in auth list - streaming-structured: use handle/unhandle from sys/index instead of process.once/off directly - auth/list/handlers: remove dead static tableColumns(); inline display name in ACCOUNT cell when present (email only when name is empty) - auth/list/list.test: add coverage for inline-name and empty-name table rendering
Resolve HTTP client refactor conflicts (cfc1cf2): replace KyInstance with HttpClient/createHttpClient across all authed commands, keeping Registry/Store multi-account model. Fix bin/** no-top-level-await lint.
wylswz
reviewed
Jun 2, 2026
wylswz
reviewed
Jun 2, 2026
wylswz
approved these changes
Jun 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Unifies how
difyctlreads and writes credentials, adds first-class multi-host/account switching, replaces the split output formatter system with a single protocol, and addsauth list.Resolves WTA-356.
What changed
Token storage
Storeinterface; keychain and file backends share one code path.tokens.ymlis authoritative.Auth commands
difyctl auth list— table of all authenticated host+account pairs, supports-o json/yaml/name. Replacesauth status(redundant withauth whoamifor single-context view).difyctl use host [--domain <domain>]— switch the active Dify instance.difyctl use account [--email <email>]— switch active account on the current host.Login UX
--hostin a non-TTY context now errors with a usage hint instead of hanging.Output formatter unification
framework/output.ts(TablePrintable,FormattedPrintable) andframework/stream.ts(StreamPrinter).src/printers/deleted entirely (15 files).AppRunObjectnow implementsFormattedPrintabledirectly; mode-dispatch (chat/completion/workflow) internalized.StreamPrintertype moved toframework/stream.ts; concrete implementations stay command-scoped.get/*handlers migrated fromprinters/format-tabletype imports toframework/output.Testing
pnpm type-check,pnpm lint,pnpm tree:check— clean.pnpm test— 786 passing, including coverage for the interactive picker,use host/use accountflows, andauth listoutput shapes.