···1111 deleteOAuthSession,
1212 getOAuthStorePath,
1313 listOAuthSessions,
1414+ listOAuthSessionsWithHandles,
1515+ setOAuthHandle,
1416} from "../lib/oauth-store";
1517import { exitOnCancel } from "../lib/prompts";
1618···3335 handler: async ({ logout, list }) => {
3436 // List sessions
3537 if (list) {
3636- const sessions = await listOAuthSessions();
3838+ const sessions = await listOAuthSessionsWithHandles();
3739 if (sessions.length === 0) {
3840 log.info("No OAuth sessions stored");
3941 } else {
4042 log.info("OAuth sessions:");
4141- for (const did of sessions) {
4242- console.log(` - ${did}`);
4343+ for (const { did, handle } of sessions) {
4444+ console.log(` - ${handle || did} (${did})`);
4345 }
4446 }
4547 return;
···171173 new URLSearchParams(result.params!),
172174 );
173175174174- // Try to get the handle for display (use the original handle input as fallback)
175175- let displayName = handle;
176176- try {
177177- // The session should have the DID, we can use the original handle they entered
178178- // or we could fetch the profile to get the current handle
179179- displayName = handle.startsWith("did:") ? session.did : handle;
180180- } catch {
181181- displayName = session.did;
176176+ // Store the handle for friendly display
177177+ // Use the original handle input (unless it was a DID)
178178+ const handleToStore = handle.startsWith("did:") ? undefined : handle;
179179+ if (handleToStore) {
180180+ await setOAuthHandle(session.did, handleToStore);
182181 }
182182+183183+ // Try to get the handle for display (use the original handle input as fallback)
184184+ const displayName = handleToStore || session.did;
183185184186 s.stop(`Logged in as ${displayName}`);
185187
+46-6
packages/cli/src/commands/publish.ts
···55import { loadConfig, loadState, saveState, findConfig } from "../lib/config";
66import {
77 loadCredentials,
88- listCredentials,
88+ listAllCredentials,
99 getCredentials,
1010} from "../lib/credentials";
1111+import { getOAuthHandle, getOAuthSession } from "../lib/oauth-store";
1112import {
1213 createAgent,
1314 createDocument,
···59606061 // If no credentials resolved, check if we need to prompt for identity selection
6162 if (!credentials) {
6262- const identities = await listCredentials();
6363+ const identities = await listAllCredentials();
6364 if (identities.length === 0) {
6464- log.error("No credentials found. Run 'sequoia auth' first.");
6565+ log.error(
6666+ "No credentials found. Run 'sequoia login' or 'sequoia auth' first.",
6767+ );
6568 log.info(
6669 "Or set ATP_IDENTIFIER and ATP_APP_PASSWORD environment variables.",
6770 );
6871 process.exit(1);
6972 }
7373+7474+ // Build labels with handles for OAuth sessions
7575+ const options = await Promise.all(
7676+ identities.map(async (cred) => {
7777+ if (cred.type === "oauth") {
7878+ const handle = await getOAuthHandle(cred.id);
7979+ return {
8080+ value: cred.id,
8181+ label: `${handle || cred.id} (OAuth)`,
8282+ };
8383+ }
8484+ return {
8585+ value: cred.id,
8686+ label: `${cred.id} (App Password)`,
8787+ };
8888+ }),
8989+ );
70907191 // Multiple identities exist but none selected - prompt user
7292 log.info("Multiple identities found. Select one to use:");
7393 const selected = exitOnCancel(
7494 await select({
7595 message: "Identity:",
7676- options: identities.map((id) => ({ value: id, label: id })),
9696+ options,
7797 }),
7898 );
79998080- credentials = await getCredentials(selected);
100100+ // Load the selected credentials
101101+ const selectedCred = identities.find((c) => c.id === selected);
102102+ if (selectedCred?.type === "oauth") {
103103+ const session = await getOAuthSession(selected);
104104+ if (session) {
105105+ const handle = await getOAuthHandle(selected);
106106+ credentials = {
107107+ type: "oauth",
108108+ did: selected,
109109+ handle: handle || selected,
110110+ pdsUrl: "https://bsky.social",
111111+ };
112112+ }
113113+ } else {
114114+ credentials = await getCredentials(selected);
115115+ }
116116+81117 if (!credentials) {
82118 log.error("Failed to load selected credentials.");
83119 process.exit(1);
84120 }
85121122122+ const displayId =
123123+ credentials.type === "oauth"
124124+ ? credentials.handle || credentials.did
125125+ : credentials.identifier;
86126 log.info(
8787- `Tip: Add "identity": "${selected}" to sequoia.json to use this by default.`,
127127+ `Tip: Add "identity": "${displayId}" to sequoia.json to use this by default.`,
88128 );
89129 }
90130