feat: one-click cookie import from browser

New: agent-eyes configure --from-browser chrome
- Extracts Twitter, XiaoHongShu, Bilibili cookies in ONE command
- No F12, no manual copying, no extension needed
- Supports: chrome, firefox, edge, brave, opera
- Uses browser-cookie3 (optional dependency: pip install agent-eyes[cookies])

Install guide now 3x shorter:
1. pip install + agent-eyes install (auto-detect env)
2. agent-eyes configure --from-browser chrome (one-click all cookies)
3. agent-eyes configure exa-key KEY (one API key)
4. Done

User actions reduced from 4 trips to 2:
- Before: go to exa.ai + F12 Twitter + F12 XHS + go to webshare.io
- After: go to exa.ai + say 'yes' to auto-import cookies
This commit is contained in:
Panniantong
2026-02-24 06:55:08 +01:00
parent f98fc991bc
commit b264070a8d
4 changed files with 257 additions and 79 deletions
+46 -7
View File
@@ -80,11 +80,15 @@ def main():
help="Exa API key (get free at https://exa.ai)")
# ── configure ──
p_conf = sub.add_parser("configure", help="Set a config value")
p_conf.add_argument("key", choices=["exa-key", "proxy", "github-token", "groq-key",
"twitter-cookies", "xhs-cookie", "youtube-cookies"],
help="What to configure")
p_conf.add_argument("value", nargs="+", help="The value(s) to set")
p_conf = sub.add_parser("configure", help="Set a config value or auto-extract from browser")
p_conf.add_argument("key", nargs="?", default=None,
choices=["exa-key", "proxy", "github-token", "groq-key",
"twitter-cookies", "xhs-cookie", "youtube-cookies"],
help="What to configure (omit if using --from-browser)")
p_conf.add_argument("value", nargs="*", help="The value(s) to set")
p_conf.add_argument("--from-browser", metavar="BROWSER",
choices=["chrome", "firefox", "edge", "brave", "opera"],
help="Auto-extract ALL platform cookies from browser (chrome/firefox/edge/brave/opera)")
# ── doctor ──
sub.add_parser("doctor", help="Check platform availability")
@@ -224,11 +228,46 @@ def _detect_environment():
def _cmd_configure(args):
"""Set a config value and test it."""
"""Set a config value and test it, or auto-extract from browser."""
from agent_eyes.config import Config
config = Config()
value = " ".join(args.value) if isinstance(args.value, list) else args.value
# ── Auto-extract from browser ──
if args.from_browser:
from agent_eyes.cookie_extract import configure_from_browser
browser = args.from_browser
print(f"🔍 Extracting cookies from {browser}...")
print()
results = configure_from_browser(browser, config)
found_any = False
for platform, success, message in results:
if success:
print(f"{platform}: {message}")
found_any = True
else:
print(f"{platform}: {message}")
print()
if found_any:
print("✅ Cookies configured! Run `agent-eyes doctor` to see updated status.")
else:
print(f"No cookies found. Make sure you're logged into the platforms in {browser}.")
return
# ── Manual configure ──
if not args.key:
print("Usage: agent-eyes configure <key> <value>")
print(" or: agent-eyes configure --from-browser chrome")
return
value = " ".join(args.value) if args.value else ""
if not value:
print(f"Missing value for {args.key}")
return
if args.key == "proxy":
config.set("reddit_proxy", value)
+166
View File
@@ -0,0 +1,166 @@
# -*- coding: utf-8 -*-
"""Auto-extract cookies from local browsers for all supported platforms.
Supports: Chrome, Firefox, Edge, Brave, Opera
Extracts: Twitter, XiaoHongShu, Bilibili cookies in one shot.
Usage:
agent-eyes configure --from-browser chrome
"""
import sys
from typing import Dict, List, Optional, Tuple
# Platform cookie specs: (platform_name, domain_pattern, needed_cookies)
PLATFORM_SPECS = [
{
"name": "Twitter/X",
"domains": [".x.com", ".twitter.com"],
"cookies": ["auth_token", "ct0"],
"config_key": "twitter",
},
{
"name": "XiaoHongShu",
"domains": [".xiaohongshu.com"],
"cookies": None, # None = grab all cookies as header string
"config_key": "xhs",
},
{
"name": "Bilibili",
"domains": [".bilibili.com"],
"cookies": ["SESSDATA", "bili_jct"],
"config_key": "bilibili",
},
]
def extract_all(browser: str = "chrome") -> Dict[str, dict]:
"""
Extract cookies for all supported platforms from the specified browser.
Returns:
{
"twitter": {"auth_token": "xxx", "ct0": "yyy"},
"xhs": {"cookie_string": "a=1; b=2; ..."},
"bilibili": {"SESSDATA": "xxx", "bili_jct": "yyy"},
}
"""
try:
import browser_cookie3
except ImportError:
raise RuntimeError(
"browser_cookie3 not installed. Run: pip install browser-cookie3"
)
# Get browser cookie jar
browser_funcs = {
"chrome": browser_cookie3.chrome,
"firefox": browser_cookie3.firefox,
"edge": browser_cookie3.edge,
"brave": browser_cookie3.brave,
"opera": browser_cookie3.opera,
}
browser = browser.lower()
if browser not in browser_funcs:
raise ValueError(
f"Unsupported browser: {browser}. "
f"Supported: {', '.join(browser_funcs.keys())}"
)
try:
cookie_jar = browser_funcs[browser]()
except Exception as e:
raise RuntimeError(
f"Could not read {browser} cookies: {e}\n"
f"Make sure {browser} is closed and you have permission to read its data."
)
results = {}
for spec in PLATFORM_SPECS:
platform_cookies = {}
all_cookies_for_domain = []
for cookie in cookie_jar:
# Check if cookie belongs to this platform
domain_match = any(
cookie.domain.endswith(d) or cookie.domain == d.lstrip(".")
for d in spec["domains"]
)
if not domain_match:
continue
all_cookies_for_domain.append(cookie)
if spec["cookies"] is not None:
if cookie.name in spec["cookies"]:
platform_cookies[cookie.name] = cookie.value
if spec["cookies"] is None:
# Grab all as header string
if all_cookies_for_domain:
cookie_str = "; ".join(
f"{c.name}={c.value}" for c in all_cookies_for_domain
)
results[spec["config_key"]] = {"cookie_string": cookie_str}
else:
if platform_cookies:
results[spec["config_key"]] = platform_cookies
return results
def configure_from_browser(browser: str, config) -> List[Tuple[str, bool, str]]:
"""
Extract cookies and configure all found platforms.
Returns list of (platform_name, success, message) tuples.
"""
results_list = []
try:
extracted = extract_all(browser)
except Exception as e:
return [("Browser", False, str(e))]
if not extracted:
return [("All platforms", False,
f"No platform cookies found in {browser}. "
f"Make sure you're logged into Twitter, XiaoHongShu, etc. in {browser}.")]
# Configure each found platform
if "twitter" in extracted:
tc = extracted["twitter"]
if "auth_token" in tc and "ct0" in tc:
config.set("twitter_auth_token", tc["auth_token"])
config.set("twitter_ct0", tc["ct0"])
results_list.append(("Twitter/X", True, "auth_token + ct0"))
else:
found = ", ".join(tc.keys())
missing = [k for k in ["auth_token", "ct0"] if k not in tc]
results_list.append(("Twitter/X", False,
f"Found {found}, but missing: {', '.join(missing)}. "
f"Make sure you're logged into x.com in {browser}."))
if "xhs" in extracted:
cookie_str = extracted["xhs"].get("cookie_string", "")
if cookie_str:
config.set("xhs_cookie", cookie_str)
n_cookies = len(cookie_str.split(";"))
results_list.append(("XiaoHongShu", True, f"{n_cookies} cookies"))
if "bilibili" in extracted:
bc = extracted["bilibili"]
if "SESSDATA" in bc:
config.set("bilibili_sessdata", bc["SESSDATA"])
if "bili_jct" in bc:
config.set("bilibili_csrf", bc["bili_jct"])
results_list.append(("Bilibili", True, "SESSDATA" +
(" + bili_jct" if "bili_jct" in bc else "")))
else:
results_list.append(("Bilibili", False,
f"No SESSDATA found. Make sure you're logged into bilibili.com in {browser}."))
return results_list
+43 -71
View File
@@ -12,7 +12,7 @@ Install Agent Eyes: https://raw.githubusercontent.com/Panniantong/agent-eyes/mai
## For AI Agents
Install Agent Eyes and set it up for the user. Minimize friction — ask as few questions as possible.
Install Agent Eyes and set it up with minimal user effort.
### Step 1: Install and check
@@ -21,103 +21,75 @@ pip install git+https://github.com/Panniantong/agent-eyes.git || pip3 install gi
agent-eyes install --env=auto
```
That's it. This installs the package, auto-detects the environment, and shows what's working.
### Step 2: One-click cookie import (LOCAL COMPUTERS ONLY)
### Step 2: Tell user what's ready + offer ONE upgrade
If the environment was detected as **local**, offer to grab all cookies at once:
Tell the user what already works, then offer the single highest-value upgrade:
> "I can automatically import your cookies from Chrome to unlock Twitter, XiaoHongShu, and Bilibili — all at once, one command. Want me to do that?
> (Make sure Chrome is closed first)"
> "✅ Agent Eyes installed! Here's what I can already do:
> - Read web pages, GitHub repos, RSS feeds, YouTube transcripts
> - Read individual tweets
>
> **Want me to unlock search too?** One free API key lets me search the entire web, Reddit, and Twitter for you.
> Just go to https://exa.ai → sign up (free, 1000 searches/month) → send me the API key.
>
> Or say 'skip' and I'm ready to use as-is."
If yes:
```bash
pip install browser-cookie3
agent-eyes configure --from-browser chrome
```
If the user provides a key:
This extracts cookies for ALL supported platforms in one shot. No F12, no manual copying.
If user uses a different browser:
```bash
agent-eyes configure --from-browser firefox # or edge, brave, opera
```
If the environment is **server** or the user declines, skip to Step 3.
### Step 3: Offer search upgrade
> "Want to unlock web search? One free API key lets me search the entire web, Reddit, and Twitter.
> → Go to https://exa.ai → sign up (free) → send me the API key.
> Or say 'skip'."
If user provides key:
```bash
agent-eyes configure exa-key THE_KEY
```
If the user says skip, move to Step 4.
### Step 4: Server-only — offer proxy
### Step 3: Offer additional channels
Only if auto-detected as server:
After Exa is configured (or skipped), briefly mention what else is available:
> "I can also unlock these with cookies from your browser (2 min each):
> 🐦 **Twitter** deep search — timelines, threads, advanced search
> 📕 **XiaoHongShu** — read notes and comments
>
> Want any of these? Or say 'done' and we're good to go."
Only proceed with channels the user explicitly asks for.
#### How to get cookies (for any platform)
When the user wants to set up a cookie-based channel, give them the SIMPLEST method:
**Method 1 — Browser extension (easiest):**
> "Install the 'Cookie-Editor' extension for Chrome/Firefox (free). Open [the site], click the extension icon, click 'Export' → 'Header String'. Paste it to me."
**Method 2 — Manual (if they don't want to install an extension):**
> "Open [the site] in Chrome. Press F12. Click 'Application' tab at the top. Click 'Cookies' on the left. Find and copy the values I need."
#### Twitter setup
Cookie-Editor export, or manually copy **auth_token** and **ct0** from x.com cookies.
```bash
agent-eyes configure twitter-cookies AUTH_TOKEN CT0
```
#### XiaoHongShu setup
Cookie-Editor export the full cookie string from xiaohongshu.com.
```bash
agent-eyes configure xhs-cookie COOKIE_STRING
```
#### YouTube (only mention if user has age-restricted video needs)
No cookies needed for public videos. For age-restricted/member content:
```bash
agent-eyes configure youtube-cookies chrome
```
(yt-dlp reads cookies directly from the browser — just tell it which browser)
#### Bilibili
- Local computer: already works
- Server: needs proxy (see below)
#### Reddit full reader + Bilibili on server
Only offer this if `agent-eyes install` detected server environment:
> "Reddit and Bilibili block server IPs. Reddit search already works (via Exa), but for reading full posts you'd need a $1/month proxy from https://webshare.io. Want to set that up?"
> "Reddit and Bilibili block server IPs. Reddit search still works free via Exa, but for full access you'd need a cheap proxy ($1/month).
> → Get one at https://webshare.io if interested. Or skip — search still works!"
If user provides proxy:
```bash
agent-eyes configure proxy http://user:pass@ip:port
```
### Step 4: Done
### Step 5: Done
```bash
agent-eyes doctor
```
Summarize naturally:
> "✅ Ready! Here's everything I can do: [list channels]. Try asking me to search or read something!"
> "✅ All set! [list what's active]. Try asking me to search or read something!"
**Remember**: the user can always come back and say "set up Twitter" or "add a proxy" later. You just run the corresponding `agent-eyes configure` command.
**Users can always configure more later** by saying things like "set up Twitter for Agent Eyes" or "add my XiaoHongShu cookies".
---
## Quick Reference
## Manual configure (one channel at a time)
These commands are for manual setup or adding individual channels later:
| Command | What it does |
|---------|-------------|
| `agent-eyes doctor` | Show all channels and status |
| `agent-eyes configure --from-browser chrome` | Import ALL cookies at once |
| `agent-eyes configure exa-key KEY` | Unlock search (web + Reddit + Twitter) |
| `agent-eyes configure twitter-cookies TOKEN CT0` | Unlock Twitter deep search |
| `agent-eyes configure xhs-cookie COOKIE` | Unlock XiaoHongShu |
| `agent-eyes configure youtube-cookies BROWSER` | Unlock age-restricted YouTube |
| `agent-eyes configure proxy URL` | Unlock Reddit reader + Bilibili (server) |
| `agent-eyes configure twitter-cookies TOKEN CT0` | Twitter deep search (manual) |
| `agent-eyes configure xhs-cookie COOKIE` | XiaoHongShu (manual) |
| `agent-eyes configure youtube-cookies chrome` | Age-restricted YouTube |
| `agent-eyes configure proxy URL` | Reddit + Bilibili on servers |
| `agent-eyes doctor` | Show all channels and status |
| `agent-eyes read URL` | Read any URL |
| `agent-eyes search "query"` | Search the web |
+2 -1
View File
@@ -30,8 +30,9 @@ dependencies = [
[project.optional-dependencies]
browser = ["playwright>=1.40"]
cookies = ["browser-cookie3>=0.19"]
mcp = ["mcp[cli]>=1.0"]
all = ["playwright>=1.40", "mcp[cli]>=1.0"]
all = ["playwright>=1.40", "mcp[cli]>=1.0", "browser-cookie3>=0.19"]
[project.scripts]
agent-eyes = "agent_eyes.cli:main"