···251251| `--batch-delay <ms>` | `-d` | Delay between batches in ms | `500` (min) |
252252| `--help` | | Show help message | - |
253253254254+### PDS Override
255255+256256+If you already know the base URL of your Personal Data Server (PDS) you can bypass the Slingshot identity resolver and provide it directly with the `--pds` flag. This is useful for private instances, testing, or when the resolver is unreliable.
257257+258258+| Option | Description |
259259+|--------|-------------|
260260+| `--pds <url>` | PDS base URL to use for authentication and API calls (e.g. `https://pds.example.com`). When provided, Malachite will skip Slingshot lookup and use this URL directly. |
261261+262262+Notes:
263263+- The `--pds` flag overrides the configured Slingshot resolver for identity lookup. If `--pds` is given, Malachite will attempt to authenticate directly against the supplied PDS using your handle/DID and app password.
264264+- Use the full base URL (including scheme), e.g. `https://pds.example.com`.
265265+- If authentication fails when using `--pds`, try removing the flag so Malachite can resolve your PDS automatically via Slingshot.
266266+254267### Legacy Flags (Backwards Compatible)
255268256269These old flags still work but are deprecated:
+29-13
src/lib/auth.ts
···1212/**
1313 * Resolves an AT Protocol identifier (handle or DID) to get PDS information
1414 */
1515-async function resolveIdentifier(identifier: string): Promise<ResolvedIdentity> {
1515+async function resolveIdentifier(identifier: string, resolverBase: string): Promise<ResolvedIdentity> {
1616 ui.startSpinner(`Resolving identifier: ${identifier}`);
1717-1717+1818 try {
1919 const response = await fetch(
2020- `https://slingshot.microcosm.blue/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(identifier)}`
2020+ `${resolverBase}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(identifier)}`
2121 );
2222-2222+2323 if (!response.ok) {
2424 throw new Error(`Failed to resolve identifier: ${response.status} ${response.statusText}`);
2525 }
2626-2626+2727 const data = await response.json() as ResolvedIdentity;
2828-2828+2929 if (!data.did || !data.pds) {
3030 throw new Error('Invalid response from identity resolver');
3131 }
3232-3232+3333 ui.succeedSpinner(`Resolved to PDS: ${data.pds}`);
3434 return data;
3535 } catch (error) {
···4444export async function login(
4545 identifier: string | undefined,
4646 password: string | undefined,
4747- _resolverUrl?: string // Keep parameter for backwards compatibility but don't use it
4747+ resolverOrPds?: string // If this contains the Slingshot resolver base, it will be used to resolve; otherwise treated as a PDS override URL
4848): Promise<AtpAgent> {
4949 ui.header('ATProto Login');
5050···6464 console.log('');
65656666 try {
6767- // Resolve the identifier to get PDS and other info
6868- const resolved = await resolveIdentifier(identifier);
6969-6767+ // If resolverOrPds is provided and does NOT look like the Slingshot resolver,
6868+ // treat it as a PDS override and skip identity resolution.
6969+ const isSlingshot = resolverOrPds?.includes('slingshot') ?? false;
7070+7171+ if (resolverOrPds && !isSlingshot) {
7272+ ui.startSpinner(`Using provided PDS: ${resolverOrPds}`);
7373+ const agent = new AtpAgent({ service: resolverOrPds });
7474+ await agent.login({ identifier: identifier!, password: password });
7575+ ui.succeedSpinner('Logged in successfully (PDS override)!');
7676+ ui.keyValue('DID', agent.session?.did || 'unknown');
7777+ ui.keyValue('Handle', agent.session?.handle || 'unknown');
7878+ console.log('');
7979+ return agent;
8080+ }
8181+8282+ // Otherwise use the resolver (provided or default) to resolve identifier
8383+ const resolverBase = resolverOrPds || 'https://slingshot.microcosm.blue';
8484+ const resolved = await resolveIdentifier(identifier, resolverBase);
8585+7086 // Initialize the agent with the resolved PDS URL
7187 ui.startSpinner('Logging in...');
7288 const agent = new AtpAgent({
···7894 identifier: resolved.did,
7995 password: password,
8096 });
8181-9797+8298 ui.succeedSpinner('Logged in successfully!');
8399 ui.keyValue('DID', agent.session?.did || 'unknown');
84100 ui.keyValue('Handle', agent.session?.handle || 'unknown');
85101 console.log('');
8686-102102+87103 return agent;
88104 } catch (error) {
89105 const err = error as Error;