Requirements
- Target platform
- OpenClaw
- Install method
- Manual import
- Extraction
- Extract archive
- Prerequisites
- OpenClaw
- Primary doc
- SKILL.md
Order groceries from Zepto in seconds. Just say what you need, get a payment link on WhatsApp, pay on your phone, done. Remembers your usual items. Works across India where Zepto delivers.
Order groceries from Zepto in seconds. Just say what you need, get a payment link on WhatsApp, pay on your phone, done. Remembers your usual items. Works across India where Zepto delivers.
Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.
I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete.
I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run.
Order groceries from Zepto in 30 seconds. From chat to checkout. Tell your AI what you need. It shops, generates a payment link, sends it to WhatsApp. You pay on your phone. Groceries arrive in 10 minutes.
Quick orders: "Order milk and bread from Zepto" "Add vegetables - tomatoes, onions, potatoes" "Get me Amul butter and cheese" Your usuals: "Add my usual milk" โ AI picks the brand you always order "Order the usual groceries" โ AI suggests your frequent items Full shopping list: "Add milk, bread, eggs, coriander, ginger, and tea bags" โ AI adds everything, shows total: โนX โ Sends payment link to WhatsApp โ You pay, groceries arrive
What this skill does: โ Browser automation on zepto.com (your local browser, your session) โ Stores order history locally in ~/.openclaw/skills/zepto/order-history.json (local file, not shared) โ Sends payment links via WhatsApp (requires your consent for each order) โ All authentication happens through Zepto's official flow (Phone + OTP) What this skill does NOT do: โ No automatic payments (you must click the link and pay manually) โ No data sent to external servers (except Zepto.com and WhatsApp via your channels) โ No persistent background jobs (optional one-time order status check only if you approve) โ No storage of payment info or OTPs โ No access to your banking/UPI apps Data Storage: Order history: ~/.openclaw/skills/zepto/order-history.json (local only, helps with "usuals" feature) Browser session: Managed by OpenClaw's browser (standard Chrome/Chromium profile) User Control: You control when to order You approve each payment link You can delete order history file anytime All browser actions happen in your profile with your visibility
ALWAYS follow this order when building an order:
# Before adding ANY items, ALWAYS check cart state node zepto-agent.js get-cart Why: Cart may have items from previous sessions. Adding duplicates is wasteful.
# This handles everything: clears unwanted, checks duplicates, adds missing node zepto-agent.js smart-shop "milk, bread, eggs" What it does: Checks current cart state Clears existing items (if any) For each item: checks if already in cart โ skips if present โ adds only if missing Returns: { added: [], skipped: [], failed: [] }
Snapshot shows all refs, buttons, text Screenshot is ONLY for visual debugging when snapshot is truncated or unclear In 99% of cases, snapshot is enough
When you see in snapshot: "Decrease quantity 1 Increase quantity" โ Item is IN CART button "Remove" [ref=eXX] โ Item is IN CART DO NOT click "ADD" when you see these signals!
Authentication - Phone + OTP verification Address Confirmation - Verify delivery location Shopping - Search & add items (with YOUR usuals prioritized!) Payment Link - Generate & send Juspay link via WhatsApp
Your order history is tracked in: {SKILL_DIR}/order-history.json (Where {SKILL_DIR} is your skill directory, typically ~/.openclaw/skills/zepto/) Smart Selection Logic: When user requests an item (e.g., "add milk") Check order-history.json for that category If ordered 2+ times โ Auto-add your most-ordered variant If ordered 0-1 times โ Show options and ask for selection
When to run: User says "update my zepto history" or "refresh order history" Process: Navigate to account page Get all delivered order URLs Visit each order sequentially Extract items using DOM scraping Build frequency map Save to order-history.json Implementation: # Step 1: Navigate to account page browser navigate url=https://www.zepto.com/account profile=openclaw # Step 2: Extract order URLs browser act profile=openclaw request='{"fn":"() => { const orders = []; document.querySelectorAll(\"a[href*=\\\"/order/\\\"]\").forEach(link => { if (link.href.includes(\"isArchived=false\") && link.textContent.includes(\"delivered\")) { orders.push(link.href); } }); return [...new Set(orders)]; }", "kind":"evaluate"}' # Returns array of order URLs # Step 3: For each order URL: browser navigate url={order_url} profile=openclaw # Step 4: Extract items from order page browser act profile=openclaw request='{"fn":"() => { const items = []; document.querySelectorAll(\"*\").forEach(el => { const text = el.textContent; if (text.match(/\\d+\\s*unit/i)) { const parent = el.closest(\"div\"); if (parent) { const lines = parent.textContent.split(\"\\n\").map(l => l.trim()).filter(l => l && l.length > 5 && l.length < 100); if (lines[0]) { const qtyMatch = text.match(/(\\d+)\\s*unit/i); items.push({ name: lines[0], quantity: qtyMatch ? parseInt(qtyMatch[1]) : 1 }); } } } }); const uniqueItems = {}; items.forEach(item => { if (!uniqueItems[item.name]) uniqueItems[item.name] = item; }); return Object.values(uniqueItems); }", "kind":"evaluate"}' # Returns array of {name, quantity} # Step 5: Aggregate all items into frequency map # Build JSON structure with counts # Step 6: Write to file write path={SKILL_DIR}/order-history.json content={json_data} Automated scraper advantages: โ No manual screenshot review โ Faster (visits all orders programmatically) โ Always up-to-date โ Can re-run anytime Example: User: "Update my Zepto order history" Response: "๐ Scanning your Zepto orders... ๐ฆ Found 6 delivered orders ๐ Extracting items... โ Updated! Found: - Coriander: 4 orders - Milk: 3 orders - Bread: 2 orders - Potato: 2 orders + 15 other items Your usuals are ready!" Smart Selection Logic (Using History): Example: User: "Add milk" [Check order-history.json] โ "Amul Taaza Toned Fresh Milk | Pouch (500ml)" ordered 3x Response: "๐ฅ Adding your usual milk! Amul Taaza Toned Fresh Milk (500ml) - โน29 ๐ You've ordered this 3 times โ Added to cart" If only ordered once or never: User: "Add milk" [Check order-history.json] โ "Amul Taaza" ordered 1x only Response: "๐ฅ Found some milk options: 1. Amul Taaza Toned (500ml) - โน29 โญ 4.8 (100k) - You've ordered this once 2. Amul Gold (1L) - โน68 โญ 4.9 (80k) - Most popular 3. Mother Dairy (500ml) - โน30 โญ 4.7 (60k) Which one? (or tell me a number)" Update order history: After each successful order, update the JSON file with new items.
Check if already logged in: browser open url=https://www.zepto.com profile=openclaw browser snapshot --interactive profile=openclaw # Look for "login" button vs "profile" link If NOT logged in, start auth flow:
Ask user: "What's your phone number for Zepto? (10 digits)"
# Click login button browser act profile=openclaw request='{"kind":"click","ref":"{login_button_ref}"}' # Type phone number browser act profile=openclaw request='{"kind":"type","ref":"{phone_input_ref}","text":"{phone}"}' # Click Continue browser act profile=openclaw request='{"kind":"click","ref":"{continue_button_ref}"}'
Ask user: "I've sent the OTP to {phone}. What's the OTP you received?"
browser snapshot --interactive profile=openclaw # Get OTP input refs browser act profile=openclaw request='{"kind":"type","ref":"{otp_input_ref}","text":"{otp}"}' # OTP auto-submits after 6 digits Result: User is now logged in! Session persists across browser restarts.
๐จ CRITICAL: ALWAYS CHECK ADDRESS BEFORE PROCEEDING WITH ANY SHOPPING!
Default behavior: Most users have multiple saved addresses (Home, Office, etc.) ALWAYS show current address and ASK for confirmation - never assume Check what was used in the last order (if order history exists) Wait for explicit user confirmation before proceeding On homepage, address is visible in the header: browser snapshot --interactive profile=openclaw # Look for button with heading level=3 containing the address # Example ref: e16 with text like "Home - [Address Details]..." # Delivery time shown nearby (e.g., "10 minutes") ALWAYS ask user to confirm before shopping: ๐ I see your delivery address is set to: {Address Name} - {Full Address} โฑ๏ธ Delivery in ~{X} minutes Is this correct? Should I proceed with this address?
Use the zepto-agent.js select-address command: node zepto-agent.js select-address "Home" node zepto-agent.js select-address "sanskar" # Fuzzy matching works! node zepto-agent.js select-address "kundu blr" How it works: Fuzzy matching - Case-insensitive, partial match supported "sanskar" โ "Sanskar Blr" โ "home" โ "New Home" โ "kundu" โ "Kundu Blr" โ Already-selected detection - Skips if you're already at that address Verification - Confirms address change in header after click Example: # Current address: "Kundu Blr" node zepto-agent.js select-address "sanskar" # Output: # โน๏ธ Opening Zepto... # โ Zepto opened # โน๏ธ ๐ Selecting address: "sanskar" # โน๏ธ Current: Kundu Blr # โ Clicked: Sanskar BlrA-301, A, BLOCK-B... # ๐ Address changed to: Sanskar blr When user says "change address to X" or "deliver to X": # Just call the command with their address name/query node zepto-agent.js select-address "{user_query}" No manual modal navigation needed! The script handles: Opening the address modal Finding the address (fuzzy match) Clicking it Verifying the change Closing the modal Manual Selection (Fallback): If the programmatic method fails or address isn't found: # Click the address button (ref e16 or similar) browser act profile=openclaw request='{"kind":"click","ref":"e16"}' # This opens address selection modal with all saved addresses Select address using JavaScript: # Replace {USER_ADDRESS_NAME} with the actual address name user selected browser act profile=openclaw request='{"fn":"() => { const input = document.querySelector('input[placeholder*=\"address\"]'); if (!input) return { error: 'Modal not found' }; let modal = input; for (let i = 0; i < 15; i++) { if (!modal.parentElement) break; modal = modal.parentElement; if (window.getComputedStyle(modal).position === 'fixed') break; } const divs = Array.from(modal.querySelectorAll('div')); const match = divs.find(d => d.textContent && d.textContent.trim().startsWith('{USER_ADDRESS_NAME}')); if (!match) return { error: 'Address not found' }; let p = match; for (let i = 0; i < 10; i++) { if (!p) break; const s = window.getComputedStyle(p); if (p.onclick || p.getAttribute('onClick') || s.cursor === 'pointer') { p.scrollIntoView({ block: 'center' }); setTimeout(() => {}, 300); p.click(); return { clicked: true, text: match.textContent.substring(0, 100) }; } p = p.parentElement; } return { error: 'No clickable parent' }; }()","kind":"evaluate"}' After address confirmed by user: โ Delivery address confirmed: {address_name} ๐ {full_address} โฑ๏ธ ETA: {eta} mins Ready to shop! What would you like to add to cart? โ ๏ธ Address is CRITICAL - never skip this step!
When user asks to "explore", "show me", "what's good", "find something", or "discover": Common Discovery Patterns: "Show me healthy snacks under โน50" "What's good in dairy products?" "Find me something for breakfast" "Any deals on fruits?" "Discover protein bars" Browse Categories: # Navigate to category pages browser navigate url=https://www.zepto.com profile=openclaw browser snapshot --interactive profile=openclaw # Categories available on homepage: # - Fruits & Vegetables # - Dairy, Bread & Eggs # - Munchies (snacks) # - Cold Drinks & Juices # - Breakfast & Sauces # - Atta, Rice, Oil & Dals # - Cleaning Essentials # - Bath & Body # - Makeup & Beauty Filter & Sort: # Example: Browse "Munchies" category browser navigate url=https://www.zepto.com/pn/munchies profile=openclaw browser snapshot --interactive profile=openclaw # Take screenshot to show user the options browser screenshot profile=openclaw Discovery Response Format: ๐ Found some great options in {category}: 1. **{Product Name}** - โน{price} ({discount}% OFF) โญ {rating} ({review_count} reviews) ๐ฆ {size/quantity} 2. **{Product Name}** - โน{price} โญ {rating} ({review_count} reviews) 3. **{Product Name}** - โน{price} ({discount}% OFF) โญ {rating} ({review_count} reviews) Want me to add any of these? Just tell me the number(s)! Smart Filtering Tips: Price range: Extract from query ("under โน50", "below 100") Discount focus: Look for items with โนX OFF tags High ratings: Prioritize 4.5+ star products Popular items: Sort by review count (k = thousands) Health focus: Keywords like "protein", "sugar-free", "organic", "millet" Interactive Discovery: After showing options, user can: Add by number: "Add 1 and 3" Ask for more: "Show me more" Refine: "Show cheaper options" or "What about chocolate flavors?" Browse different category: "Now show me dairy products"
MANDATORY PRE-FLIGHT CHECK: Before adding ANY items: Click cart button Read current cart contents If cart has items: Ask user "Keep existing items or clear cart first?" If empty: Proceed to shopping Multi-Item Shopping Flow: When user gives a list (e.g., "add milk, butter, bread"): Add items ONE AT A TIME with verification: Search for item Click ADD button Wait 0.5s for page update VERIFY item shows quantity controls (means it's in cart) If verification fails: Retry up to 3 times Then show final cart summary with all items and total CRITICAL: Never batch-add without verification! Page refs change after each add. Item Selection Logic: Check order-history.json first If item ordered 2+ times โ auto-select that variant If item ordered 0-1 times or multiple unclear variants โ show options and ASK Pick closest match to user's request (e.g., "Yakult Light" when they said "light") Use highest review count as tiebreaker When UNCLEAR about variant: ๐ฅ Found multiple milk options: 1. Amul Taaza (500ml) - โน29 โญ 4.8 (100k) 2. Amul Gold (1L) - โน68 โญ 4.9 (80k) 3. Mother Dairy (500ml) - โน30 โญ 4.7 (60k) Which one? (or tell me a number) Search Process: browser navigate url=https://www.zepto.com/search?query={item} profile=openclaw browser snapshot --interactive profile=openclaw
Rule: Pick product with highest review count (unless order history says otherwise). Format: {rating} ({count}) where k=thousand, M=million. Example: "4.8 (694.4k)" = 694,400 reviews = most popular.
browser act profile=openclaw request='{"kind":"click","ref":"{ADD_button_ref}"}'
browser navigate url=https://www.zepto.com/?cart=open profile=openclaw browser snapshot profile=openclaw # Get cart summary Cart Summary Format: ๐ Added to cart: 1. Item 1 - โนXX 2. Item 2 - โนYY 3. Item 3 - โนZZ ๐ฐ Total: โน{total} Ready to checkout? (say "yes" or "checkout" or "lessgo") CRITICAL - Quantity Mapping: When user provides a shopping list with quantities (e.g., "3x jeera, 2x saffola oats"): ALWAYS create a mapping file FIRST before any cart operations Map each item name to its requested quantity Before removing/modifying items, verify against this mapping Never assume which item has which quantity - CHECK THE MAPPING Example mapping: { "jeera": 3, "saffola_oats": 2, "milk": 1 } Before removing duplicates or adjusting quantities: Take a cart snapshot Match cart items to your mapping by name similarity Verify quantities match the original request If unsure, ASK the user before making changes
After all items added to cart and user confirms checkout:
# Open cart modal browser act profile=openclaw request='{"kind":"click","ref":"{cart_button_ref}"}' # Example ref from homepage: e44 # Wait for cart to open, take snapshot browser snapshot --interactive profile=openclaw # Click "Click to Pay โน{amount}" button browser act profile=openclaw request='{"kind":"click","ref":"{click_to_pay_button_ref}"}' # Example ref: e3579
# Wait 2 seconds for navigation to complete browser act profile=openclaw request='{"fn":"async () => { await new Promise(r => setTimeout(r, 2000)); return window.location.href; }","kind":"evaluate"}' URL Format: https://payments.juspay.in/payment-page/signature/zeptomarketplace-{order_id} Example: https://payments.juspay.in/payment-page/signature/zeptomarketplace-{ORDER_ID_EXAMPLE}
message action=send channel=whatsapp target={user_phone} message="๐ *Your Zepto order is ready!* *Cart Summary ({item_count} items):* 1. {item1} - โน{price1} 2. {item2} - โน{price2} 3. {item3} - โน{price3} *๐ฐ Total: โน{total}* ๐ Delivering to: {address_name} - {address} โฑ๏ธ ETA: {eta} minutes *๐ Click here to pay:* {juspay_payment_link} โ ๏ธ *IMPORTANT: After payment, message me \"DONE\" to confirm your order!* (Don't rely on the payment page - just tell me when you've paid and I'll verify it) ๐"
This is DIFFERENT from normal flow - auto-clear expected! 1. Navigate to zepto.com and check order status browser navigate url=https://www.zepto.com profile=openclaw browser snapshot --interactive profile=openclaw 2. Look for "Your order is on the way" or "Arriving in X mins" 3. Open cart and AUTO-CLEAR without asking # Open cart browser act profile=openclaw request='{"kind":"click","ref":"{cart_button_ref}"}' # Remove all items (they're from the order that just went through) browser act profile=openclaw request='{"kind":"click","ref":"{remove_ref_1}"}' browser act profile=openclaw request='{"kind":"click","ref":"{remove_ref_2}"}' browser act profile=openclaw request='{"kind":"click","ref":"{remove_ref_3}"}' 4. Confirm to user โ Payment confirmed! Your order is on the way! Arriving in ~{X} mins. โ Cart cleared ({item_count} items removed from previous order) ๐ Ready for your next order! Why auto-clear in post-payment? User expects cart to be empty after successful order Cart items are from the order they just paid for Zepto hasn't synced yet, so items persist temporarily Clearing prevents confusion and duplicate orders
โ Cart cleared! โ Address confirmed: {address} What would you like to order? ๐ Key Difference: Normal flow: ASK before clearing cart (user might want those items) Post-payment flow: AUTO-CLEAR cart (user knows those items are ordered)
โ DO: Check auth status before every order Confirm address with user Extract payment link accurately Send link via WhatsApp Let user complete payment โ DON'T: Never click "Pay" button Never store OTP Never auto-submit payment Never change address without user confirmation
Phone number invalid: "Phone number should be 10 digits. Please try again." OTP verification failed: "OTP verification failed. Let me resend the OTP. Check your phone for the new code." Location not serviceable: "โ ๏ธ Your location is currently not serviceable by Zepto. Store might be temporarily closed or location outside delivery zone. Want to try a different address?" Item not found: "Couldn't find {item} on Zepto. Try a different search term?"
After successful authentication: Browser cookies persist login No need to re-authenticate for future orders Address selection persists Can directly proceed to shopping To check if authenticated: browser navigate url=https://www.zepto.com profile=openclaw browser snapshot --interactive profile=openclaw # If "profile" link exists โ logged in # If "login" button exists โ need to auth
Messaging, meetings, inboxes, CRM, and teammate communication surfaces.
Largest current source with strong distribution and engagement signals.