doordash-cli 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -9,6 +9,22 @@ All notable changes to `doordash-cli` will be documented in this file.
9
9
 
10
10
  See [docs/releasing.md](docs/releasing.md) for the maintainer release flow.
11
11
 
12
+ ## [0.3.1](https://github.com/LatencyTDH/doordash-cli/compare/v0.3.0...v0.3.1) (2026-03-11)
13
+
14
+ ### Bug Fixes
15
+
16
+ * keep managed browser session imports quiet ([#28](https://github.com/LatencyTDH/doordash-cli/issues/28)) ([dc25e04](https://github.com/LatencyTDH/doordash-cli/commit/dc25e0444ca63c7af1c2feaa2f32ede54b1c1f98))
17
+
18
+ ## [0.3.0](https://github.com/LatencyTDH/doordash-cli/compare/v0.2.0...v0.3.0) (2026-03-11)
19
+
20
+ ### Features
21
+
22
+ * rename auth commands to login/logout ([#27](https://github.com/LatencyTDH/doordash-cli/issues/27)) ([f5bf85c](https://github.com/LatencyTDH/doordash-cli/commit/f5bf85c556d23e7cefc95f346777d33fb1021bcc))
23
+
24
+ ### Bug Fixes
25
+
26
+ * preserve existing-order docs in release-flow cleanup ([#25](https://github.com/LatencyTDH/doordash-cli/issues/25)) ([4789089](https://github.com/LatencyTDH/doordash-cli/commit/4789089dd831b42cd037707e82a0f102988fd830))
27
+
12
28
  ## 0.2.0 (2026-03-11)
13
29
 
14
30
  ### Features
package/README.md CHANGED
@@ -46,7 +46,7 @@ npm run cli -- --help
46
46
 
47
47
  ### Browser prerequisite
48
48
 
49
- If you plan to use `auth-bootstrap`, install Playwright's Chromium build once:
49
+ If you plan to sign in with `login`, install Playwright's Chromium build once:
50
50
 
51
51
  ```bash
52
52
  doordash-cli install-browser
@@ -57,7 +57,7 @@ npm run install:browser
57
57
  ## First run
58
58
 
59
59
  ```bash
60
- doordash-cli auth-bootstrap
60
+ doordash-cli login
61
61
  doordash-cli auth-check
62
62
  doordash-cli set-address --address "350 5th Ave, New York, NY 10118"
63
63
  doordash-cli search --query sushi
@@ -65,7 +65,7 @@ doordash-cli search --query sushi
65
65
 
66
66
  If you are running from a checkout without `npm link`, replace `doordash-cli` with `npm run cli --`.
67
67
 
68
- If you already have a compatible signed-in DoorDash browser session available, `auth-check` may reuse it instead of asking you to sign in again.
68
+ If you already have a compatible signed-in DoorDash managed-browser session available, `auth-check` may quietly reuse it instead of asking you to sign in again. Routine direct commands stay quiet; use `login` when you want explicit browser interaction.
69
69
 
70
70
  ## Command surface
71
71
 
@@ -73,8 +73,8 @@ If you already have a compatible signed-in DoorDash browser session available, `
73
73
 
74
74
  - `install-browser`
75
75
  - `auth-check`
76
- - `auth-bootstrap`
77
- - `auth-clear`
76
+ - `login`
77
+ - `logout`
78
78
 
79
79
  ### Discovery
80
80
 
package/dist/cli.js CHANGED
@@ -24,8 +24,8 @@ export function usage() {
24
24
  "Safe commands:",
25
25
  " install-browser",
26
26
  " auth-check",
27
- " auth-bootstrap",
28
- " auth-clear",
27
+ " login",
28
+ " logout",
29
29
  ' set-address --address "350 5th Ave, New York, NY 10118"',
30
30
  " search --query sushi [--cuisine japanese]",
31
31
  " menu --restaurant-id 123456",
@@ -43,7 +43,8 @@ export function usage() {
43
43
  " - install-browser downloads the matching Playwright Chromium build used by this package.",
44
44
  " - Manual pages ship with the project: man dd-cli or man doordash-cli.",
45
45
  " - Direct GraphQL/HTTP is the default path for auth-check, set-address, search, menu, item, orders, order, cart, add-to-cart, and update-cart.",
46
- " - auth-check can reuse an already-signed-in compatible DoorDash browser session when one is available.",
46
+ " - login launches Chromium for a one-time manual sign-in flow and saves reusable state for later direct API calls.",
47
+ " - auth-check can quietly reuse an already-signed-in compatible managed-browser DoorDash session when one is available; use login for explicit browser interaction.",
47
48
  " - set-address now uses DoorDash autocomplete/get-or-create plus addConsumerAddressV2 for brand-new address enrollment when needed.",
48
49
  " - configurable items require explicit --options-json selections.",
49
50
  ' - standalone recommended add-ons that open a nested cursor step are supported via children, e.g. [{"groupId":"recommended_option_546935995","optionId":"546936011","children":[{"groupId":"780057412","optionId":"4702669757"}]}].',
@@ -58,9 +59,9 @@ export function usage() {
58
59
  " dd-cli search --query sushi",
59
60
  " dd-cli orders --active-only",
60
61
  " doordash-cli order --order-id 3f4c6d0e-1234-5678-90ab-cdef12345678",
61
- " doordash-cli auth-check",
62
+ " doordash-cli login",
62
63
  "",
63
- "Allowed commands: install-browser, auth-check, auth-bootstrap, auth-clear, set-address, search, menu, item, orders, order, add-to-cart, update-cart, cart",
64
+ "Allowed commands: install-browser, auth-check, login, logout, set-address, search, menu, item, orders, order, add-to-cart, update-cart, cart",
64
65
  ].join("\n");
65
66
  }
66
67
  export function normalizeOptionToken(token) {
package/dist/cli.test.js CHANGED
@@ -33,8 +33,8 @@ test("safe command allowlist stays cart-safe while adding install helpers", () =
33
33
  assert.deepEqual(SAFE_COMMANDS, [
34
34
  "install-browser",
35
35
  "auth-check",
36
- "auth-bootstrap",
37
- "auth-clear",
36
+ "login",
37
+ "logout",
38
38
  "set-address",
39
39
  "search",
40
40
  "menu",
@@ -46,11 +46,13 @@ test("safe command allowlist stays cart-safe while adding install helpers", () =
46
46
  "cart",
47
47
  ]);
48
48
  });
49
- test("dangerous and unsupported legacy commands are rejected", () => {
49
+ test("dangerous and renamed legacy commands are rejected with guidance", () => {
50
50
  assert.throws(() => assertSafeCommand("checkout"), /Blocked command: checkout/);
51
51
  assert.throws(() => assertSafeCommand("place-order"), /Blocked command: place-order/);
52
52
  assert.throws(() => assertSafeCommand("track-order"), /Use `orders` or `order --order-id/);
53
53
  assert.throws(() => assertSafeCommand("payment"), /Blocked command: payment/);
54
+ assert.throws(() => assertSafeCommand("auth-bootstrap"), /renamed it to login/);
55
+ assert.throws(() => assertSafeCommand("auth-clear"), /renamed it to logout/);
54
56
  });
55
57
  test("unsupported flags are rejected before network work runs", () => {
56
58
  assert.throws(() => assertAllowedFlags("cart", { payment: "visa" }), /Unsupported flag\(s\) for cart/);
@@ -102,7 +104,8 @@ test("help output shows the direct read-only/cart-safe command surface", () => {
102
104
  assert.match(result.stdout, /dd-cli <command>/);
103
105
  assert.match(result.stdout, /doordash-cli <command>/);
104
106
  assert.match(result.stdout, /install-browser/);
105
- assert.match(result.stdout, /auth-bootstrap/);
107
+ assert.match(result.stdout, /login/);
108
+ assert.match(result.stdout, /logout/);
106
109
  assert.match(result.stdout, /set-address --address/);
107
110
  assert.match(result.stdout, /orders \[--limit 20\] \[--active-only\]/);
108
111
  assert.match(result.stdout, /order --order-id/);
@@ -110,12 +113,17 @@ test("help output shows the direct read-only/cart-safe command surface", () => {
110
113
  assert.match(result.stdout, /--version, -v/);
111
114
  assert.match(result.stdout, /man dd-cli/);
112
115
  assert.match(result.stdout, /Out-of-scope commands remain intentionally unsupported/);
116
+ assert.doesNotMatch(result.stdout, /auth-bootstrap/);
117
+ assert.doesNotMatch(result.stdout, /auth-clear/);
113
118
  assert.doesNotMatch(result.stdout, /Dd-cli/);
114
119
  });
115
120
  test("repository ships man pages for the supported lowercase command names", () => {
116
121
  const ddManPath = join(distDir, "..", "man", "dd-cli.1");
117
122
  const aliasManPath = join(distDir, "..", "man", "doordash-cli.1");
118
123
  assert.match(readFileSync(ddManPath, "utf8"), /install-browser/);
124
+ assert.match(readFileSync(ddManPath, "utf8"), /\.B login/);
125
+ assert.doesNotMatch(readFileSync(ddManPath, "utf8"), /auth-bootstrap/);
126
+ assert.doesNotMatch(readFileSync(ddManPath, "utf8"), /auth-clear/);
119
127
  assert.doesNotMatch(readFileSync(ddManPath, "utf8"), /Dd-cli/);
120
128
  assert.equal(readFileSync(aliasManPath, "utf8").trim(), ".so man1/dd-cli.1");
121
129
  });
@@ -141,6 +149,16 @@ test("version flag prints the package version", () => {
141
149
  assert.equal(result.status, 0);
142
150
  assert.equal(result.stdout.trim(), version());
143
151
  });
152
+ test("legacy auth command invocations point users to login/logout", () => {
153
+ const loginRename = runCli(["auth-bootstrap"]);
154
+ assert.equal(loginRename.status, 1);
155
+ assert.match(loginRename.stderr, /Unsupported command: auth-bootstrap/);
156
+ assert.match(loginRename.stderr, /renamed it to login/);
157
+ const logoutRename = runCli(["auth-clear"]);
158
+ assert.equal(logoutRename.status, 1);
159
+ assert.match(logoutRename.stderr, /Unsupported command: auth-clear/);
160
+ assert.match(logoutRename.stderr, /renamed it to logout/);
161
+ });
144
162
  test("blocked commands fail immediately", () => {
145
163
  const result = runCli(["checkout"]);
146
164
  assert.equal(result.status, 1);
@@ -1,3 +1,4 @@
1
+ import { type Cookie } from "playwright";
1
2
  export type AuthResult = {
2
3
  success: true;
3
4
  isLoggedIn: boolean;
@@ -521,6 +522,12 @@ export declare function resolveAvailableAddressMatch(input: {
521
522
  printableAddress: string | null;
522
523
  source: SetAddressResult["matchedAddressSource"];
523
524
  } | null;
525
+ export declare function isDoorDashUrl(value: string): boolean;
526
+ export declare function hasDoorDashCookies(cookies: ReadonlyArray<Pick<Cookie, "domain">>): boolean;
527
+ export declare function selectManagedBrowserImportMode(input: {
528
+ pageUrls: readonly string[];
529
+ cookies: ReadonlyArray<Pick<Cookie, "domain">>;
530
+ }): "page" | "cookies" | "skip";
524
531
  export declare function parseSearchRestaurants(body: unknown[]): SearchRestaurantResult[];
525
532
  export declare function parseSearchRestaurantRow(entry: unknown): SearchRestaurantResult | null;
526
533
  export declare function parseExistingOrderLifecycleStatus(orderRoot: unknown): ExistingOrderLifecycleStatus;
@@ -808,6 +808,9 @@ class DoorDashDirectSession {
808
808
  return;
809
809
  }
810
810
  this.attemptedManagedImport = true;
811
+ if (await hasPersistedSessionArtifacts()) {
812
+ return;
813
+ }
811
814
  await importManagedBrowserSessionIfAvailable().catch(() => { });
812
815
  }
813
816
  }
@@ -1535,39 +1538,69 @@ function normalizeAddressText(value) {
1535
1538
  .replace(/[.,]/g, "")
1536
1539
  .replace(/\s+/g, " ");
1537
1540
  }
1541
+ export function isDoorDashUrl(value) {
1542
+ try {
1543
+ const url = new URL(value);
1544
+ return url.hostname === "doordash.com" || url.hostname.endsWith(".doordash.com");
1545
+ }
1546
+ catch {
1547
+ return false;
1548
+ }
1549
+ }
1550
+ export function hasDoorDashCookies(cookies) {
1551
+ return cookies.some((cookie) => {
1552
+ const domain = cookie.domain.trim().replace(/^\./, "").toLowerCase();
1553
+ return domain === "doordash.com" || domain.endsWith(".doordash.com");
1554
+ });
1555
+ }
1556
+ export function selectManagedBrowserImportMode(input) {
1557
+ if (input.pageUrls.some((url) => isDoorDashUrl(url))) {
1558
+ return "page";
1559
+ }
1560
+ if (hasDoorDashCookies(input.cookies)) {
1561
+ return "cookies";
1562
+ }
1563
+ return "skip";
1564
+ }
1538
1565
  async function importManagedBrowserSessionIfAvailable() {
1539
1566
  for (const cdpUrl of await getManagedBrowserCdpCandidates()) {
1540
1567
  if (!(await isCdpEndpointReachable(cdpUrl))) {
1541
1568
  continue;
1542
1569
  }
1543
1570
  let browser = null;
1544
- let tempPage = null;
1545
1571
  try {
1546
1572
  browser = await chromium.connectOverCDP(cdpUrl);
1547
1573
  const context = browser.contexts()[0];
1548
1574
  if (!context) {
1549
1575
  continue;
1550
1576
  }
1551
- let page = context.pages().find((candidate) => candidate.url().includes("doordash.com")) ?? null;
1552
- if (!page) {
1553
- tempPage = await context.newPage();
1554
- page = tempPage;
1555
- await page.goto(`${BASE_URL}/home`, { waitUntil: "domcontentloaded", timeout: 90_000 }).catch(() => { });
1556
- await page.waitForTimeout(1_000);
1557
- }
1558
- const consumerData = await fetchConsumerViaPage(page);
1559
- const consumer = consumerData.consumer ?? null;
1560
- if (!consumer || consumer.isGuest !== false) {
1577
+ const cookies = await context.cookies();
1578
+ const pages = context.pages();
1579
+ const reusablePage = pages.find((candidate) => isDoorDashUrl(candidate.url())) ?? null;
1580
+ const importMode = selectManagedBrowserImportMode({
1581
+ pageUrls: reusablePage ? [reusablePage.url()] : [],
1582
+ cookies,
1583
+ });
1584
+ if (importMode === "skip") {
1561
1585
  continue;
1562
1586
  }
1563
- await saveContextState(context);
1564
- return true;
1587
+ if (reusablePage) {
1588
+ const consumerData = await fetchConsumerViaPage(reusablePage).catch(() => null);
1589
+ const consumer = consumerData?.consumer ?? null;
1590
+ if (consumer?.isGuest === false) {
1591
+ await saveContextState(context, cookies);
1592
+ return true;
1593
+ }
1594
+ }
1595
+ if (hasDoorDashCookies(cookies)) {
1596
+ await saveContextState(context, cookies);
1597
+ return true;
1598
+ }
1565
1599
  }
1566
1600
  catch {
1567
1601
  continue;
1568
1602
  }
1569
1603
  finally {
1570
- await tempPage?.close().catch(() => { });
1571
1604
  await browser?.close().catch(() => { });
1572
1605
  }
1573
1606
  }
@@ -1588,12 +1621,12 @@ async function fetchConsumerViaPage(page) {
1588
1621
  });
1589
1622
  return parseGraphQlResponse("managedBrowserConsumerImport", raw.status, raw.text);
1590
1623
  }
1591
- async function saveContextState(context) {
1624
+ async function saveContextState(context, cookies = null) {
1592
1625
  const storageStatePath = getStorageStatePath();
1593
1626
  await ensureConfigDir();
1594
1627
  await context.storageState({ path: storageStatePath });
1595
- const cookies = await context.cookies();
1596
- await writeFile(getCookiesPath(), JSON.stringify(cookies, null, 2));
1628
+ const resolvedCookies = cookies ?? (await context.cookies());
1629
+ await writeFile(getCookiesPath(), JSON.stringify(resolvedCookies, null, 2));
1597
1630
  }
1598
1631
  async function getManagedBrowserCdpCandidates() {
1599
1632
  const candidates = new Set();
@@ -2282,6 +2315,12 @@ async function hasStorageState() {
2282
2315
  return false;
2283
2316
  }
2284
2317
  }
2318
+ async function hasPersistedSessionArtifacts() {
2319
+ if (await hasStorageState()) {
2320
+ return true;
2321
+ }
2322
+ return (await readStoredCookies()).length > 0;
2323
+ }
2285
2324
  async function readStoredCookies() {
2286
2325
  try {
2287
2326
  const raw = await readFile(getCookiesPath(), "utf8");
@@ -1,6 +1,6 @@
1
1
  import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
- import { buildAddConsumerAddressPayload, buildAddToCartPayload, buildUpdateCartPayload, extractExistingOrdersFromApolloCache, normalizeItemName, parseExistingOrderLifecycleStatus, parseExistingOrdersResponse, parseOptionSelectionsJson, parseSearchRestaurantRow, resolveAvailableAddressMatch, } from "./direct-api.js";
3
+ import { buildAddConsumerAddressPayload, buildAddToCartPayload, buildUpdateCartPayload, extractExistingOrdersFromApolloCache, hasDoorDashCookies, normalizeItemName, parseExistingOrderLifecycleStatus, parseExistingOrdersResponse, parseOptionSelectionsJson, parseSearchRestaurantRow, resolveAvailableAddressMatch, selectManagedBrowserImportMode, } from "./direct-api.js";
4
4
  function configurableItemDetail() {
5
5
  return {
6
6
  success: true,
@@ -144,6 +144,25 @@ test("parseSearchRestaurantRow extracts restaurant metadata from facet rows", ()
144
144
  url: "https://www.doordash.com/store/24633898/?pickup=false",
145
145
  });
146
146
  });
147
+ test("managed browser import falls back to cookie reuse without opening a DoorDash page", () => {
148
+ const cookies = [{ domain: ".doordash.com" }];
149
+ assert.equal(hasDoorDashCookies(cookies), true);
150
+ assert.equal(selectManagedBrowserImportMode({ pageUrls: [], cookies }), "cookies");
151
+ });
152
+ test("managed browser import prefers an existing DoorDash page when one is already open", () => {
153
+ const cookies = [{ domain: ".doordash.com" }];
154
+ assert.equal(selectManagedBrowserImportMode({
155
+ pageUrls: ["https://github.com/LatencyTDH/doordash-cli/pulls", "https://www.doordash.com/home"],
156
+ cookies,
157
+ }), "page");
158
+ });
159
+ test("managed browser import skips unrelated browser contexts", () => {
160
+ assert.equal(hasDoorDashCookies([{ domain: ".github.com" }]), false);
161
+ assert.equal(selectManagedBrowserImportMode({
162
+ pageUrls: ["https://github.com/LatencyTDH/doordash-cli"],
163
+ cookies: [{ domain: ".github.com" }],
164
+ }), "skip");
165
+ });
147
166
  test("parseOptionSelectionsJson parses structured recursive option selections", () => {
148
167
  assert.deepEqual(parseOptionSelectionsJson('[{"groupId":"703393388","optionId":"4716032529"},{"groupId":"recommended_option_546935995","optionId":"546936011","children":[{"groupId":"780057412","optionId":"4702669757","quantity":2}]}]'), [
149
168
  { groupId: "703393388", optionId: "4716032529" },
package/dist/lib.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { type AddToCartResult, type AuthBootstrapResult, type AuthResult, type CartResult, type ItemResult, type MenuResult, type OrderResult, type OrdersResult, type SearchResult, type SetAddressResult, type UpdateCartResult } from "./direct-api.js";
2
- export declare const SAFE_COMMANDS: readonly ["install-browser", "auth-check", "auth-bootstrap", "auth-clear", "set-address", "search", "menu", "item", "orders", "order", "add-to-cart", "update-cart", "cart"];
2
+ export declare const SAFE_COMMANDS: readonly ["install-browser", "auth-check", "login", "logout", "set-address", "search", "menu", "item", "orders", "order", "add-to-cart", "update-cart", "cart"];
3
3
  export declare const BLOCKED_COMMANDS: readonly ["checkout", "place-order", "track-order", "payment", "pay", "tip", "submit-order"];
4
4
  export type SafeCommand = (typeof SAFE_COMMANDS)[number];
5
5
  export type CommandFlags = Record<string, string>;
package/dist/lib.js CHANGED
@@ -8,8 +8,8 @@ const PLAYWRIGHT_CLI_PATH = join(dirname(require.resolve("playwright/package.jso
8
8
  export const SAFE_COMMANDS = [
9
9
  "install-browser",
10
10
  "auth-check",
11
- "auth-bootstrap",
12
- "auth-clear",
11
+ "login",
12
+ "logout",
13
13
  "set-address",
14
14
  "search",
15
15
  "menu",
@@ -29,11 +29,15 @@ export const BLOCKED_COMMANDS = [
29
29
  "tip",
30
30
  "submit-order",
31
31
  ];
32
+ const LEGACY_COMMAND_RENAMES = {
33
+ "auth-bootstrap": "login",
34
+ "auth-clear": "logout",
35
+ };
32
36
  const COMMAND_FLAGS = {
33
37
  "install-browser": [],
34
38
  "auth-check": [],
35
- "auth-bootstrap": [],
36
- "auth-clear": [],
39
+ login: [],
40
+ logout: [],
37
41
  "set-address": ["address"],
38
42
  search: ["query", "cuisine"],
39
43
  menu: ["restaurant-id"],
@@ -58,6 +62,10 @@ export function assertSafeCommand(value) {
58
62
  const guidance = value === "track-order" ? " Use `orders` or `order --order-id ...` for read-only existing-order status instead." : "";
59
63
  throw new Error(`Blocked command: ${value}. This CLI is read-only for browse, cart, and existing-order inspection only; checkout, order placement, and payment actions stay out of scope.${guidance}`);
60
64
  }
65
+ const renamedTo = LEGACY_COMMAND_RENAMES[value];
66
+ if (renamedTo) {
67
+ throw new Error(`Unsupported command: ${value}. This CLI renamed it to ${renamedTo}.`);
68
+ }
61
69
  throw new Error(`Unsupported command: ${value}. Allowed commands: ${SAFE_COMMANDS.join(", ")}`);
62
70
  }
63
71
  export function assertAllowedFlags(command, args) {
@@ -76,9 +84,9 @@ export async function runCommand(command, args) {
76
84
  return installBrowser();
77
85
  case "auth-check":
78
86
  return checkAuthDirect();
79
- case "auth-bootstrap":
87
+ case "login":
80
88
  return bootstrapAuthSession();
81
- case "auth-clear":
89
+ case "logout":
82
90
  return clearStoredSession();
83
91
  case "set-address": {
84
92
  const address = requiredArg(args, "address");
package/docs/examples.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # doordash-cli examples
2
2
 
3
- Use the preferred lowercase command name `dd-cli`. `doordash-cli` is an equivalent alias.
3
+ Use the preferred lowercase command name `doordash-cli`. `dd-cli` is an equivalent shorter alias.
4
4
 
5
5
  If you are running from a local checkout without linking, prefix commands with:
6
6
 
@@ -17,25 +17,25 @@ All commands print JSON.
17
17
  Install the matching Chromium build once if you do not already have it:
18
18
 
19
19
  ```bash
20
- dd-cli install-browser
20
+ doordash-cli install-browser
21
21
  ```
22
22
 
23
23
  Check whether you already have reusable session state:
24
24
 
25
25
  ```bash
26
- dd-cli auth-check
26
+ doordash-cli auth-check
27
27
  ```
28
28
 
29
29
  If needed, launch Chromium for a one-time sign-in and save reusable state:
30
30
 
31
31
  ```bash
32
- dd-cli auth-bootstrap
32
+ doordash-cli login
33
33
  ```
34
34
 
35
35
  Reset saved session state when you want a clean start:
36
36
 
37
37
  ```bash
38
- dd-cli auth-clear
38
+ doordash-cli logout
39
39
  ```
40
40
 
41
41
  ## Search, menus, and items
@@ -43,21 +43,21 @@ dd-cli auth-clear
43
43
  Set the active delivery address before discovery commands:
44
44
 
45
45
  ```bash
46
- dd-cli set-address --address "350 5th Ave, New York, NY 10118"
46
+ doordash-cli set-address --address "350 5th Ave, New York, NY 10118"
47
47
  ```
48
48
 
49
49
  Search by query, with or without a cuisine filter:
50
50
 
51
51
  ```bash
52
- dd-cli search --query tacos
53
- dd-cli search --query tacos --cuisine mexican
52
+ doordash-cli search --query tacos
53
+ doordash-cli search --query tacos --cuisine mexican
54
54
  ```
55
55
 
56
56
  Inspect a restaurant menu and a specific item:
57
57
 
58
58
  ```bash
59
- dd-cli menu --restaurant-id 1721744
60
- dd-cli item --restaurant-id 1721744 --item-id 546936015
59
+ doordash-cli menu --restaurant-id 1721744
60
+ doordash-cli item --restaurant-id 1721744 --item-id 546936015
61
61
  ```
62
62
 
63
63
  ## Existing orders
@@ -65,20 +65,20 @@ dd-cli item --restaurant-id 1721744 --item-id 546936015
65
65
  List recent existing orders:
66
66
 
67
67
  ```bash
68
- dd-cli orders
69
- dd-cli orders --limit 5
68
+ doordash-cli orders
69
+ doordash-cli orders --limit 5
70
70
  ```
71
71
 
72
72
  Focus on still-active orders only:
73
73
 
74
74
  ```bash
75
- dd-cli orders --active-only
75
+ doordash-cli orders --active-only
76
76
  ```
77
77
 
78
78
  Inspect one order in detail. `--order-id` accepts the CLI's returned internal ID, `orderUuid`, or `deliveryUuid`:
79
79
 
80
80
  ```bash
81
- dd-cli order --order-id 3f4c6d0e-1234-5678-90ab-cdef12345678
81
+ doordash-cli order --order-id 3f4c6d0e-1234-5678-90ab-cdef12345678
82
82
  ```
83
83
 
84
84
  ## Cart basics
@@ -86,19 +86,19 @@ dd-cli order --order-id 3f4c6d0e-1234-5678-90ab-cdef12345678
86
86
  Add by item ID:
87
87
 
88
88
  ```bash
89
- dd-cli add-to-cart --restaurant-id 1721744 --item-id 876658890 --quantity 2
89
+ doordash-cli add-to-cart --restaurant-id 1721744 --item-id 876658890 --quantity 2
90
90
  ```
91
91
 
92
92
  Add by visible item name:
93
93
 
94
94
  ```bash
95
- dd-cli add-to-cart --restaurant-id 1721744 --item-name "Spicy Tuna Roll"
95
+ doordash-cli add-to-cart --restaurant-id 1721744 --item-name "Spicy Tuna Roll"
96
96
  ```
97
97
 
98
98
  Add with special instructions:
99
99
 
100
100
  ```bash
101
- dd-cli add-to-cart \
101
+ doordash-cli add-to-cart \
102
102
  --restaurant-id 1721744 \
103
103
  --item-name "Fries" \
104
104
  --special-instructions "extra crispy"
@@ -107,14 +107,14 @@ dd-cli add-to-cart \
107
107
  Update quantity or remove an item:
108
108
 
109
109
  ```bash
110
- dd-cli update-cart --cart-item-id 3b231d03-5a72-4636-8d12-c8769d706d45 --quantity 1
111
- dd-cli update-cart --cart-item-id 3b231d03-5a72-4636-8d12-c8769d706d45 --quantity 0
110
+ doordash-cli update-cart --cart-item-id 3b231d03-5a72-4636-8d12-c8769d706d45 --quantity 1
111
+ doordash-cli update-cart --cart-item-id 3b231d03-5a72-4636-8d12-c8769d706d45 --quantity 0
112
112
  ```
113
113
 
114
- Inspect the active cart:
114
+ Inspect the active cart before or after a mutation:
115
115
 
116
116
  ```bash
117
- dd-cli cart
117
+ doordash-cli cart
118
118
  ```
119
119
 
120
120
  ## Configurable items
@@ -122,7 +122,7 @@ dd-cli cart
122
122
  For items with required option groups, pass `--options-json` with explicit selections:
123
123
 
124
124
  ```bash
125
- dd-cli add-to-cart \
125
+ doordash-cli add-to-cart \
126
126
  --restaurant-id 1721744 \
127
127
  --item-id 546936015 \
128
128
  --options-json '[
@@ -134,7 +134,7 @@ dd-cli add-to-cart \
134
134
  Supported standalone recommended add-ons can include recursive `children` selections:
135
135
 
136
136
  ```bash
137
- dd-cli add-to-cart \
137
+ doordash-cli add-to-cart \
138
138
  --restaurant-id 1721744 \
139
139
  --item-id 546936015 \
140
140
  --options-json '[
package/docs/install.md CHANGED
@@ -33,7 +33,7 @@ If you stay in checkout mode, replace `doordash-cli` with `npm run cli --` in th
33
33
 
34
34
  ## Install the browser once
35
35
 
36
- If you plan to use `auth-bootstrap`, install the matching Playwright Chromium build:
36
+ If you plan to sign in with `login`, install the matching Playwright Chromium build:
37
37
 
38
38
  ### Global or linked install
39
39
 
@@ -50,7 +50,7 @@ npm run install:browser
50
50
  ## First run
51
51
 
52
52
  ```bash
53
- doordash-cli auth-bootstrap
53
+ doordash-cli login
54
54
  doordash-cli auth-check
55
55
  doordash-cli set-address --address "350 5th Ave, New York, NY 10118"
56
56
  doordash-cli search --query sushi
@@ -58,6 +58,6 @@ doordash-cli search --query sushi
58
58
 
59
59
  ## Session reuse
60
60
 
61
- If you already have a compatible signed-in DoorDash browser session available, direct commands may reuse it instead of opening a fresh browser context.
61
+ If you already have a compatible signed-in DoorDash managed-browser session available, direct commands may quietly reuse it instead of opening or navigating a DoorDash tab.
62
62
 
63
- If not, run `doordash-cli auth-bootstrap` once to save reusable state for later commands.
63
+ If not, run `doordash-cli login` once to save reusable state for later commands.
package/man/dd-cli.1 CHANGED
@@ -1,6 +1,6 @@
1
- .TH DD-CLI 1 "2026-03-10" "doordash-cli 0.1.0" "User Commands"
1
+ .TH DD-CLI 1 "2026-03-11" "doordash-cli 0.3.0" "User Commands"
2
2
  .SH NAME
3
- dd-cli, doordash-cli \- unofficial cart-safe DoorDash CLI for browsing, read-only order inspection, and cart management
3
+ dd-cli, doordash-cli \- unofficial cart-safe DoorDash CLI for browsing, read-only existing-order inspection, and cart management
4
4
  .SH SYNOPSIS
5
5
  .B dd-cli
6
6
  [\fICOMMAND\fR] [\fIOPTIONS\fR]
@@ -14,18 +14,18 @@ fit well in a terminal: signing in, setting delivery context, searching stores,
14
14
  inspecting menus and items, inspecting existing orders, and managing the cart.
15
15
  .PP
16
16
  The command surface is intentionally small. The CLI does not expose checkout,
17
- order placement, payment actions, or order mutation/cancellation. Read-only
18
- existing-order inspection is allowed. If a payload cannot be validated safely
19
- from known DoorDash consumer-web request shapes, the tool fails closed instead
20
- of guessing.
17
+ order placement, payment actions, live tracking, or order mutation/cancellation.
18
+ Read-only existing-order inspection is allowed. If a payload cannot be
19
+ validated safely from known DoorDash consumer-web request shapes, the tool
20
+ fails closed instead of guessing.
21
21
  .PP
22
22
  If invoked with no command, or with
23
23
  .BR -h / --help ,
24
24
  it prints usage text and exits successfully.
25
25
  .PP
26
26
  The preferred command name is
27
- .BR dd-cli .
28
- .B doordash-cli
27
+ .BR doordash-cli .
28
+ .B dd-cli
29
29
  is installed as a lowercase alias.
30
30
  .SH COMMANDS
31
31
  .TP
@@ -34,14 +34,14 @@ Install the matching Playwright Chromium build used by this package.
34
34
  .TP
35
35
  .B auth-check
36
36
  Verify whether the saved session appears authenticated. This command can also
37
- import an already-signed-in compatible managed-browser DoorDash session when a
38
- usable CDP endpoint is available.
37
+ quietly reuse an already-signed-in compatible managed-browser DoorDash session
38
+ when a usable CDP endpoint is available.
39
39
  .TP
40
- .B auth-bootstrap
40
+ .B login
41
41
  Launch Chromium for a one-time manual sign-in flow, then save reusable browser
42
42
  state for later direct API calls.
43
43
  .TP
44
- .B auth-clear
44
+ .B logout
45
45
  Delete stored session material used by this CLI.
46
46
  .TP
47
47
  .BI "set-address --address " ADDRESS
@@ -155,34 +155,34 @@ man dd-cli
155
155
  Install the matching browser build once:
156
156
  .PP
157
157
  .EX
158
- dd-cli install-browser
158
+ doordash-cli install-browser
159
159
  .EE
160
160
  .PP
161
161
  Bootstrap a reusable session:
162
162
  .PP
163
163
  .EX
164
- dd-cli auth-bootstrap
164
+ doordash-cli login
165
165
  .EE
166
166
  .PP
167
167
  Set an address and search for sushi:
168
168
  .PP
169
169
  .EX
170
- dd-cli set-address --address "350 5th Ave, New York, NY 10118"
171
- dd-cli search --query sushi
170
+ doordash-cli set-address --address "350 5th Ave, New York, NY 10118"
171
+ doordash-cli search --query sushi
172
172
  .EE
173
173
  .PP
174
174
  Inspect existing orders:
175
175
  .PP
176
176
  .EX
177
- dd-cli orders
178
- dd-cli orders --active-only
179
- dd-cli order --order-id 3f4c6d0e-1234-5678-90ab-cdef12345678
177
+ doordash-cli orders
178
+ doordash-cli orders --active-only
179
+ doordash-cli order --order-id 3f4c6d0e-1234-5678-90ab-cdef12345678
180
180
  .EE
181
181
  .PP
182
182
  Add a configurable item to the cart:
183
183
  .PP
184
184
  .EX
185
- dd-cli add-to-cart \
185
+ doordash-cli add-to-cart \
186
186
  --restaurant-id 1721744 \
187
187
  --item-id 546936015 \
188
188
  --options-json '[{"groupId":"703393388","optionId":"4716032529"},{"groupId":"703393389","optionId":"4716042466"}]'
@@ -194,7 +194,7 @@ parsers, or scripts.
194
194
  The CLI persists reusable session state under the user's configuration
195
195
  directory. The exact file layout is an implementation detail and may evolve over
196
196
  time, but the saved state is reused across runs unless cleared with
197
- .BR auth-clear .
197
+ .BR logout .
198
198
  .SH ENVIRONMENT
199
199
  .TP
200
200
  .B DOORDASH_MANAGED_BROWSER_CDP_URL
@@ -211,10 +211,10 @@ Success, including help and no-argument usage output.
211
211
  .B 1
212
212
  Validation error, blocked command, unsupported flag, or runtime failure.
213
213
  .SH SAFETY
214
- The CLI is intentionally limited to browsing, read-only existing-order
215
- inspection, and cart management. Dangerous commands such as checkout,
216
- place-order, payment actions, and order mutation/cancellation are blocked
217
- immediately. The legacy
214
+ The CLI is intentionally limited to session, discovery, read-only
215
+ existing-order inspection, and cart management. Dangerous commands such as
216
+ checkout, place-order, payment actions, live tracking, and order
217
+ mutation/cancellation are blocked immediately. The legacy
218
218
  .B track-order
219
219
  verb remains blocked; use
220
220
  .B orders
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "doordash-cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Cart-safe DoorDash CLI with direct API support for browse, read-only existing-order, and cart workflows.",
5
5
  "type": "module",
6
6
  "main": "dist/lib.js",