Python client + CLI for the Vivly social-data API (X / Reddit) with smart prompt-based routing.
Project description
vivly
Async Python client for the Vivly social-data API. One bearer key, two live sources: X (Twitter) and Reddit, plus a smart router that picks sources from a plain-language prompt. Comes with a CLI and an optional MCP server so AI agents (Claude Desktop, Claude Code, Cursor, …) can call it directly.
0.5.0b3 — breaking change. The Python API is now async (
async with+await). The CLI is unchanged. See Usage.
Install
pip install --pre vivly==0.5.0b3 # core SDK + CLI
pip install --pre "vivly[mcp]==0.5.0b3" # + MCP server (vivly-mcp)
The --pre flag is required while we're in beta.
Authenticate
The client needs a personal access token (looks like vk_live_...). Two ways:
# Option A: log in interactively (opens a browser, stores the token at
# ~/.config/vivly/config.json with 0600 perms)
vivly login
# Option B: set it yourself if you were handed a token
export VIVLY_API_KEY="vk_live_..."
A .env file in the working directory is auto-loaded. Resolution order:
explicit api_key= argument, then VIVLY_API_KEY (or legacy VIVLY_SKILL_KEY),
then .env, then ~/.config/vivly/config.json.
Usage
CLI
vivly route "what reddit thinks of claude code" # planner picks sources
vivly route "claude code launch reactions" --x # pin to X
vivly route "san antonio spurs" --x --reddit # pin both
vivly route "..." --limit 50 --pretty # 50 items, pretty JSON
vivly route "..." --out results.json # to file
vivly route "..." --no-interactive # take planner defaults
While a query runs you'll see a per-source progress block:
▰▰▰▱▱▱▱▱ reddit fetching
▰▰▰▱▱▱▱▱ x fetching
…finalising to per-source counts when the response lands.
Python (async)
import asyncio
from vivly import VivlyClient
async def main():
async with VivlyClient() as v:
# Reddit: one-shot retrieval. Auto-discovers subreddits, searches them,
# and LLM-filters the results for relevance.
r = await v.reddit.search("claude code agents", max_posts=10)
for post in r["posts"]:
print(post["score"], post["title"], post["url"])
# X / Twitter: async helper that starts a scrape, polls, returns items.
# (Runs a paid third-party actor server-side; expect a few seconds to
# minutes — pass on_progress to surface per-poll status.)
tweets = await v.x.scrape(
'"san antonio" arena Spurs lang:en',
max_items=50,
on_progress=lambda ev: print(ev["phase"], ev["status"], f"{ev['elapsed']:.1f}s"),
)
for t in tweets:
print(t["metrics"]["likes"], t["text"][:80])
# Smart router: describe what you want; it plans + runs the right sources.
result = await v.route(
"what are people saying about claude code on reddit",
force_sources=["reddit"],
max_items=20,
ask="auto", # never block on MCQs in scripts
)
asyncio.run(main())
If you'd rather drive the X scrape yourself instead of the blocking helper:
async with VivlyClient() as v:
started = await v.x.scrape_start("query lang:en", max_items=50)
status = await v.x.scrape_status(started["run_id"])
items = await v.x.scrape_items(started["dataset_id"])
MCP — expose Vivly to AI agents
Once pip install vivly[mcp] is in place, the vivly-mcp command runs a
Model Context Protocol server over stdio
exposing three tools: reddit_search, x_scrape, and route. Auth is read
from VIVLY_API_KEY exactly like the CLI — the model never sees the key.
Smoke-test in the inspector:
npx @modelcontextprotocol/inspector vivly-mcp
Register with Claude Code:
claude mcp add vivly vivly-mcp -e VIVLY_API_KEY=vk_live_...
Register with Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"vivly": {
"command": "vivly-mcp",
"env": { "VIVLY_API_KEY": "vk_live_..." }
}
}
}
Cursor uses the same shape at ~/.cursor/mcp.json. After restart, your agent
sees reddit_search / x_scrape / route in its tool list and calls them
on its own.
Errors
from vivly import VivlyError, AuthError, RateLimitError, NotFoundError
AuthError (401/403) usually means a missing, revoked, or mistyped token.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vivly-0.5.0b3.tar.gz.
File metadata
- Download URL: vivly-0.5.0b3.tar.gz
- Upload date:
- Size: 22.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e8b7d5a9ae23b497642f9995c87f5eea3138b4a92407a2f6f203607aafe7328
|
|
| MD5 |
8eec931fce0adfb8a1228f934695830a
|
|
| BLAKE2b-256 |
2653f3bc57488b072517ac5727c311218fddc16742895b36c1dfc67586160f82
|
File details
Details for the file vivly-0.5.0b3-py3-none-any.whl.
File metadata
- Download URL: vivly-0.5.0b3-py3-none-any.whl
- Upload date:
- Size: 28.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c1854703c766893cbf128ccaaf72a8bdedbaad1b07dd3b5ab604713dfe1d6b0
|
|
| MD5 |
447b3d5a11b60e4245bd7f5c0e27cf38
|
|
| BLAKE2b-256 |
bf31601add21d57741df7f07126afde31bbb1e78d911e4b37691f0b34c617d3a
|