Skip to content

Commit 4c86b0a

Browse files
committed
Initial commit
0 parents  commit 4c86b0a

File tree

20 files changed

+1695
-0
lines changed

20 files changed

+1695
-0
lines changed

.github/workflows/ci.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["main"]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: oven-sh/setup-bun@v1
14+
with:
15+
bun-version: "1.1.38"
16+
- name: Install dependencies
17+
run: bun install
18+
- name: Run tests
19+
run: bun test
20+
- name: Typecheck
21+
run: bun run typecheck

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
dist
3+
tmp
4+
.DS_Store
5+
.env

README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# clifood
2+
3+
API-first CLI for iFood. It uses your authenticated browser session to call iFood’s internal APIs directly (search, catalog, cart, discovery) and only opens pages for login/address setup and checkout review. No UI scraping is required.
4+
5+
## Quick start
6+
7+
```bash
8+
bun install
9+
# Optional: install Playwright's bundled browser
10+
bunx playwright install chromium
11+
12+
# Run a quick restaurant search (API)
13+
bun src/cli.ts restaurants --query "pizza" --limit 5 --json
14+
```
15+
16+
## Use your existing logged-in browser (recommended)
17+
18+
Start Chrome with remote debugging enabled, then point the CLI to it:
19+
20+
```bash
21+
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
22+
--remote-debugging-port=9222 \
23+
--user-data-dir="$HOME/.clifood/chrome-profile"
24+
25+
# Then run
26+
bun src/cli.ts restaurants --query "japonesa" --cdp-url http://127.0.0.1:9222
27+
```
28+
29+
This keeps your existing iFood login and address selection. All API calls are executed from your authenticated browser context to avoid bot blocks.
30+
31+
## Commands
32+
33+
### Open iFood (manual setup)
34+
35+
```bash
36+
bun src/cli.ts open --wait
37+
```
38+
39+
Use this to log in or set your delivery address in the connected browser profile.
40+
41+
### Search restaurants
42+
43+
```bash
44+
bun src/cli.ts restaurants --query "sushi" --limit 10
45+
```
46+
47+
Exclude categories or names:
48+
49+
```bash
50+
bun src/cli.ts restaurants --query "a" --exclude pizza --exclude hamburguer --exclude doces --limit 10
51+
```
52+
53+
Shortcut:
54+
55+
```bash
56+
bun src/cli.ts restaurants --query "a" --exclude-defaults --limit 10
57+
```
58+
59+
Top restaurants (discovery feed, no search term):
60+
61+
```bash
62+
bun src/cli.ts restaurants --top --exclude-defaults --limit 10
63+
```
64+
65+
### Search items in a restaurant
66+
67+
```bash
68+
bun src/cli.ts items --restaurant "Restaurante X" --query "temaki" --limit 10
69+
```
70+
71+
You can also pass a full iFood restaurant URL with `--restaurant`.
72+
73+
### Place an order
74+
75+
```bash
76+
bun src/cli.ts order \
77+
--restaurant "Restaurante X" \
78+
--item "Temaki de salmão:2" \
79+
--item "Guioza" \
80+
--confirm
81+
```
82+
83+
Safety: without `--confirm`, the CLI opens checkout but does **not** submit the order.
84+
85+
## Configuration
86+
87+
Config lives at `~/.clifood/config.json`. You can also override via CLI flags or environment variables.
88+
89+
```bash
90+
bun src/cli.ts config show
91+
bun src/cli.ts config set cdpUrl http://127.0.0.1:9222
92+
bun src/cli.ts config set headless false
93+
```
94+
95+
Supported keys: `cdpUrl`, `profileDir`, `headless`, `slowMo`, `locale`, `timeoutMs`.
96+
97+
Environment overrides:
98+
99+
- `IFOOD_CDP_URL`
100+
- `IFOOD_PROFILE_DIR`
101+
- `IFOOD_HEADLESS`
102+
- `IFOOD_SLOW_MO`
103+
- `IFOOD_LOCALE`
104+
- `IFOOD_TIMEOUT_MS`
105+
106+
## Notes
107+
108+
- The CLI is API-first and depends on a valid logged-in browser session.
109+
- Some menu items require mandatory option choices; the CLI auto-selects minimum required options from the catalog data.
110+
- Read `docs/architecture.md` for the exact API flow and data dependencies.
111+
- Read `docs/troubleshooting.md` if you hit auth or anti-bot issues.

bun.lock

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/architecture.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Architecture
2+
3+
## Goals
4+
5+
- API-first: no DOM scraping for data.
6+
- Use the authenticated browser session to pass iFood anti-bot checks.
7+
- Keep checkout confirmation explicit and opt-in.
8+
9+
## Auth strategy
10+
11+
The CLI opens a Playwright page (either a persistent profile or a CDP-connected Chrome). It reads the Redux state for account + address data and listens for any iFood API request to capture required auth headers. Those headers are reused for subsequent API calls.
12+
13+
Key headers captured (example):
14+
- `authorization`
15+
- `x-ifood-device-id`
16+
- `x-ifood-session-id`
17+
- `x-ifood-user-id`
18+
- `x-client-application-key`
19+
- `access_key`, `secret_key`
20+
- `x-px-cookies`
21+
22+
All API calls are executed via `page.evaluate(fetch)` to inherit the browser’s context and avoid bot challenges.
23+
24+
## Core endpoints
25+
26+
- Search: `GET /v2/cardstack/search/results`
27+
- Discovery feed: `GET /v2/bm/home?alias=HOME_FOOD_DELIVERY`
28+
- Category page: `GET /v1/bm/page/{id}`
29+
- Merchant catalog: `GET /v1/bm/merchants/{id}/catalog`
30+
- Cart creation: `POST /v1/carts`
31+
32+
## Command flows
33+
34+
### `restaurants`
35+
36+
- `--top`: fetch discovery feed + category pages, filter locally.
37+
- `--query`: use search endpoint.
38+
39+
### `items`
40+
41+
- Resolve merchant by URL or search.
42+
- Fetch merchant catalog.
43+
- Filter catalog items locally.
44+
45+
### `order`
46+
47+
- Resolve merchant by URL or search.
48+
- Fetch catalog, resolve item IDs, and build required sub-items.
49+
- `POST /v1/carts` to create cart.
50+
- Open `https://www.ifood.com.br/carrinho` and `https://www.ifood.com.br/checkout` to review.
51+
- Only submit if `--confirm` is explicitly provided.
52+
53+
## Safety
54+
55+
- Checkout is never submitted unless `--confirm` is provided.
56+
- If iFood challenges with anti-bot, the user must solve the challenge in the browser once.

docs/troubleshooting.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Troubleshooting
2+
3+
## "Not logged in" or missing address
4+
5+
Run:
6+
7+
```bash
8+
bun src/cli.ts open --wait
9+
```
10+
11+
Log in and select a delivery address in the opened browser, then retry the command.
12+
13+
## Anti-bot challenge
14+
15+
If iFood shows a “click and hold” modal, complete it once in the browser session. The CLI will reuse that session for future calls.
16+
17+
## Empty search results
18+
19+
Use `--top` to rely on the discovery feed instead of search, or try a more specific query.
20+
21+
## Menu item not found
22+
23+
Use `bun src/cli.ts items --restaurant "..." --query "..."` to see the exact catalog item names and match those in your `order` command.

package.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "clifood",
3+
"version": "0.1.0",
4+
"private": true,
5+
"type": "module",
6+
"bin": {
7+
"clifood": "src/cli.ts"
8+
},
9+
"scripts": {
10+
"cli": "bun src/cli.ts",
11+
"build": "bun build src/cli.ts --outdir dist --target bun",
12+
"typecheck": "bunx tsc --noEmit",
13+
"test": "bun test"
14+
},
15+
"dependencies": {
16+
"commander": "^12.1.0",
17+
"playwright": "^1.49.0",
18+
"zod": "^3.24.1"
19+
},
20+
"devDependencies": {
21+
"@types/node": "^22.13.4",
22+
"typescript": "^5.7.3"
23+
}
24+
}

skills/clifood-api/SKILL.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
name: clifood-api
3+
description: API-first iFood automation for the clifood project. Use when adding features, debugging, or running the iFood CLI, or when working with iFood discovery/search/catalog/cart APIs and related parsing logic in this repo.
4+
---
5+
6+
# Clifood API Skill
7+
8+
## Overview
9+
10+
Use this skill to work on the clifood CLI and its API-first iFood integration without UI scraping. It captures auth headers from the logged-in browser session and calls iFood’s internal endpoints directly.
11+
12+
## Quick start
13+
14+
1. Ensure a logged-in browser session with a delivery address.
15+
2. Run CLI commands from repo root.
16+
17+
Examples:
18+
19+
```bash
20+
bun src/cli.ts restaurants --top --exclude-defaults --limit 10
21+
bun src/cli.ts items --restaurant "Restaurante X" --query "temaki"
22+
```
23+
24+
## Core workflow (API-first)
25+
26+
1. **Capture auth context**
27+
- Call `getApiContext(page)` from `src/ifood/api.ts`.
28+
- This reads Redux state (account + address) and captures required headers.
29+
30+
2. **Fetch data**
31+
- Discovery: `topRestaurantsApi` (home feed + category pages).
32+
- Search: `searchRestaurantsApi`.
33+
- Catalog: `getCatalog` + `extractMenuItems`.
34+
35+
3. **Build cart**
36+
- Resolve items with `buildCartItems` (uses catalog choices).
37+
- Create cart with `createCart`.
38+
39+
4. **Review checkout**
40+
- Use `openCart` and `openCheckout` from `src/ifood/navigation.ts`.
41+
- Do **not** submit the order unless explicitly requested.
42+
43+
## Implementation notes
44+
45+
- API calls must be executed via the browser context (`page.evaluate(fetch)`) to avoid bot challenges.
46+
- Use helper parsers in `src/ifood/parsers.ts` to extract category and merchant data.
47+
- Keep filters normalized using `normalizeText` (accent-insensitive).
48+
49+
## References
50+
51+
- `docs/architecture.md` for the full API flow.
52+
- `docs/troubleshooting.md` for auth/anti-bot issues.
53+
- `references/api.md` for endpoint summary.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# iFood API Summary
2+
3+
## Auth + headers
4+
5+
Use `getApiContext(page)` from `src/ifood/api.ts` to capture headers and address/account data. It listens for any iFood API request after loading `/restaurantes` and extracts required headers.
6+
7+
## Endpoints used
8+
9+
- Discovery feed: `GET https://cw-marketplace.ifood.com.br/v2/bm/home?alias=HOME_FOOD_DELIVERY&latitude=...&longitude=...`
10+
- Category page: `GET https://cw-marketplace.ifood.com.br/v1/bm/page/{categoryId}?latitude=...&longitude=...`
11+
- Search: `GET https://cw-marketplace.ifood.com.br/v2/cardstack/search/results?alias=SEARCH_RESULTS_MERCHANT_TAB_GLOBAL&term=...`
12+
- Merchant catalog: `GET https://cw-marketplace.ifood.com.br/v1/bm/merchants/{merchantId}/catalog?latitude=...&longitude=...`
13+
- Cart creation: `POST https://cw-marketplace.ifood.com.br/v1/carts`
14+
15+
## Data extraction helpers
16+
17+
- `extractHomeData` / `extractMerchantsFromPage` in `src/ifood/parsers.ts`
18+
- `extractMenuItems` in `src/ifood/api.ts`
19+
- `buildCartItems` in `src/ifood/api.ts`
20+
21+
## Safety
22+
23+
Do not submit orders unless explicitly requested. The default flow stops after opening checkout.

0 commit comments

Comments
 (0)