| name | anysite-cli |
| description | Operate the anysite command-line tool for web data extraction, batch API processing, multi-source dataset pipelines with scheduling/transforms/exports, database operations, and LLM-powered data analysis. Use when users ask to collect data from LinkedIn, Instagram, Twitter, or any web source via CLI; create or run dataset pipelines; schedule automated collection; batch-process API calls; query collected data with SQL; load data into PostgreSQL or SQLite; analyze data with LLM (summarize, classify, enrich, match, deduplicate); or work with anysite commands. Triggers on anysite CLI usage, data collection, dataset creation, scraping, API batch calls, scheduling, database loading, or LLM analysis tasks. |
Anysite CLI
Command-line tool for web data extraction, dataset pipelines, and database operations.
Agent Planning Workflow
BEFORE planning any data collection task, follow this sequence:
-
Discover available endpoints
anysite describe --search "<keyword>"
-
Select endpoints needed for the task — identify which endpoints will provide the required data
-
Inspect each selected endpoint
anysite describe /api/linkedin/company
-
Only then plan — now you know the exact parameters, field names, and data structure to build your config or API calls
This prevents errors from wrong endpoint paths, missing required parameters, or incorrect field names in dependencies.
Best Practices
-
Use dataset pipelines for multi-step tasks
- If a task requires sequential API calls, LLM enrichment, or chained data processing — create a
dataset.yaml config instead of running multiple ad-hoc commands
- Dataset pipelines handle dependencies, incremental collection, and error recovery automatically
- Even for "simple" tasks that grow in scope, a dataset config is easier to maintain
- Benefits: run history, incremental sync, scheduling, notifications, DB loading
-
Save data in Parquet format by default — unless user requests another format or CSV/JSON fits better
-
Prefer datasets over ad-hoc scripts — one dataset.yaml replaces dozens of shell commands
Quick Start Checklist
Before any data collection task:
anysite --version
anysite changelog --last 1 --json
anysite schema update
anysite config get api_key
After upgrading, run anysite changelog --since <old_version> --json to discover new features.
Endpoint Discovery
ALWAYS discover endpoints before writing API calls or dataset configs:
anysite describe
anysite describe --search "company"
anysite describe /api/linkedin/company
Search returns matched endpoints plus upstream providers (who can supply input IDs) and downstream consumers (who can use output IDs). Use this to plan endpoint chains for dataset pipelines.
Input params show type, description, examples, and defaults. Array params show item structure:
Input parameters:
* urn string User URN, only fsd_profile urn type is allowed
example: "urn:li:fsd_profile:ACoAABXy1234"
count integer Number of posts to return
default: 20
companies array[object{type,value}] Company URNs
example: [{"type": "company", "value": "14064608"}]
Prerequisites
pip install "anysite-cli[data]"
pip install "anysite-cli[llm]"
pip install "anysite-cli[postgres]"
pip install "anysite-cli[clickhouse]"
anysite config set api_key sk-xxxxx
anysite schema update
anysite llm setup
anysite llm setup --provider openai --api-key sk-xxx --no-test
anysite llm setup --provider anthropic --api-key-env ANTHROPIC_API_KEY --no-test
anysite db add pg --type postgres --host localhost --database mydb --user app --password secret
anysite db add ch --type clickhouse --host ch.example.com --port 8443 --database analytics --user app --password secret --ssl
Authentication
anysite auth login
anysite auth login --force --no-browser
anysite auth status
anysite auth status --json
anysite auth logout
anysite auth logout --force
Single API Call
anysite api /api/linkedin/user user=satyanadella
anysite api /api/linkedin/company company=anthropic --format table
anysite api /api/linkedin/search/users keywords="CTO" count=50 --format csv --output ctos.csv
anysite api /api/linkedin/user user=satyanadella --fields "name,headline,urn.value" -q | jq
URN/Name Parameter Formats
Parameters like location, current_companies, industry accept two formats:
location="London"
current_companies="Microsoft"
'location=["urn:li:geo:101165590", "urn:li:geo:101282230"]'
'current_companies=["urn:li:company:1035", "urn:li:company:1441"]'
Note: List of names ["Microsoft", "Google"] is NOT supported — use either one name OR multiple URNs.
Batch Processing
anysite api /api/linkedin/user --from-file users.txt --input-key user \
--parallel 5 --rate-limit "10/s" --on-error skip --progress --stats
Dataset Pipeline (Multi-Source Collection)
For complex data collection with dependencies, LLM enrichment, scheduling — use dataset pipelines.
Initialize
anysite dataset init my-dataset
Six Source Types
- Independent — single API call with static
input
- from_file — batch calls iterating over input file values
- Dependent — batch calls using values extracted from a parent source
- Union (type: union) — combine records from multiple parent sources into one
- LLM (type: llm) — process parent data through LLM without API calls
- SQL (type: sql) — query a database connection or dataset Parquet files via DuckDB
Comprehensive Dataset YAML Reference
name: my-dataset
description: Optional description
sources:
- id: search_results
endpoint: /api/linkedin/search/users
input:
keywords: "software engineer"
count: 50
parallel: 1
rate_limit: "10/s"
on_error: stop
- id: search_extra
endpoint: /api/linkedin/search/users
input: { keywords: "data engineer", count: 50 }
- id: companies
endpoint: /api/linkedin/company
from_file: companies.txt
file_field: company_slug
input_key: company
parallel: 3
- id: employees
endpoint: /api/linkedin/company/employees
dependency:
from_source: companies
field: urn.value
match_by: name
dedupe: true
input_key: companies
input_template:
companies:
- type: company
value: "{value}"
count: 5
refresh: auto
- id: profiles
endpoint: /api/linkedin/user
input:
user: ${companies.urn.value}
- id: all_search_results
type: union
sources: [search_results, search_extra]
dedupe_by: urn.value
- id: employees_analyzed
type: llm
dependency:
from_source: employees
field: name
llm:
- type: classify
categories: "developer,recruiter,executive"
output_column: role_type
fields: [headline]
- type: enrich
add:
- "sentiment:positive/negative/neutral"
- "language:string"
- "quality_score:1-10"
fields: [headline, summary]
temperature: 0.0
provider: openai
model: gpt-4o-mini
- type: summarize
max_length: 50
output_column: bio
- type: generate
prompt: "Write pitch for {name}"
output_column: pitch
temperature: 0.7
export:
- type: file
path: ./output/{{source}}-{{date}}.csv
format: csv
- id: billing_users
type: sql
connection: billing
query: "SELECT name, email FROM subscriptions WHERE status = 'inactive'"
filter: ".email != null"
- id: enriched_profiles
type: sql
query: |
SELECT u.*, c.description as company_desc
FROM user_profiles u
LEFT JOIN company_profiles c ON u._input_value = c._input_value
- id: profiles
endpoint: /api/linkedin/user
dependency: { from_source: employees, field: internal_id.value }
input_key: user
filter: '.follower_count > 100'
transform:
filter: '.location != ""'
fields:
- name
- urn.value AS urn_id
- headline
add_columns:
batch: "q1-2026"
export:
- type: file
path: ./output/profiles.csv
format: csv
- type: webhook
url: https://example.com/hook
headers: { X-Token: abc }
db_load:
filter: '.active == true'
table: people
key: urn.value
sync: full
fields:
- name
- urn.value AS urn_id
- headline
exclude: [_input_value, raw_html]
storage:
format: parquet
path: ./data/
schedule:
cron: "0 9 * * *"
notifications:
on_complete:
- url: "https://hooks.slack.com/xxx"
headers: { Authorization: "Bearer token" }
on_failure:
- url: "https://alerts.example.com/fail"
type: union Source Details
The type: union source combines records from multiple parent sources:
- Requires: non-empty
sources list (parent source IDs)
- Optional:
dedupe_by field path for removing duplicates (supports dot-notation)
- Cannot have:
endpoint, dependency, from_file, input_key, input
- Validation: all parent sources must have the same endpoint (same data structure)
- Use case: merge multiple search results before a single dependent source processes them
sources:
- id: search_cto
endpoint: /api/linkedin/search/users
input: { keywords: "CTO fintech", count: 50 }
- id: search_vp
endpoint: /api/linkedin/search/users
input: { keywords: "VP Engineering", count: 50 }
- id: all_candidates
type: union
sources: [search_cto, search_vp]
dedupe_by: urn.value
- id: profiles
endpoint: /api/linkedin/user
dependency:
from_source: all_candidates
field: urn.value
input_key: user
Records from union sources are annotated with _union_source (the parent source ID they came from).
type: llm Source Details
The type: llm source processes existing parent data without making API calls:
- Requires:
dependency (parent source) and non-empty llm list
- Cannot have:
endpoint, from_file, input_key, input
- Use case: Run LLM enrichment on already-collected data, re-analyze with different prompts
anysite dataset collect dataset.yaml --source employees_analyzed
Validate & Collect Commands
anysite dataset validate dataset.yaml
anysite dataset collect dataset.yaml --dry-run
anysite dataset collect dataset.yaml
anysite dataset collect dataset.yaml --load-db pg
anysite dataset collect dataset.yaml --incremental
anysite dataset collect dataset.yaml --source employees
anysite dataset collect dataset.yaml --no-llm
anysite dataset collect dataset.yaml --limit 100
Incremental Collection (Resume Where You Left Off)
For from_file and dependency sources, anysite tracks collected input values in metadata.json. This enables resuming collection without re-fetching existing data.
Workflow:
anysite dataset collect dataset.yaml
anysite dataset collect dataset.yaml --incremental
anysite dataset reset-cursor dataset.yaml
anysite dataset collect dataset.yaml
Per-source refresh option:
sources:
- id: profiles
refresh: auto
- id: posts
refresh: always
- id: companies
refresh: never
Reset cursor:
anysite dataset reset-cursor dataset.yaml
anysite dataset reset-cursor dataset.yaml --source posts
Query with DuckDB
anysite dataset query dataset.yaml --sql "SELECT * FROM companies LIMIT 10"
anysite dataset query dataset.yaml --source profiles --fields "name, urn.value AS id"
anysite dataset query dataset.yaml --source profiles --exclude "_input_value,_parent_source"
anysite dataset query dataset.yaml --interactive
anysite dataset stats dataset.yaml --source companies
anysite dataset profile dataset.yaml
Load into Database
anysite dataset load-db dataset.yaml -c pg --drop-existing
anysite dataset load-db dataset.yaml -c pg
anysite dataset load-db dataset.yaml -c pg --snapshot 2026-01-15
Compare Snapshots
anysite dataset diff dataset.yaml --source profiles --key urn.value
anysite dataset diff dataset.yaml --source profiles --key urn.value --from 2026-01-30 --to 2026-02-01
Scheduling & History
anysite dataset schedule dataset.yaml --incremental --load-db pg
anysite dataset history my-dataset
anysite dataset logs my-dataset --run 42
anysite dataset reset-cursor dataset.yaml
Database Operations
anysite db add pg --type postgres --host localhost --database mydb --user app --password secret
anysite db add pg --type postgres --host localhost --database mydb --user app --password-env PGPASS
anysite db add ch --type clickhouse --host ch.example.com --port 8443 --database analytics --user app --password secret --ssl
anysite db add local --type sqlite --path ./data.db
anysite db add replica --type postgres --host replica.example.com --read-only
anysite db list
anysite db test pg
cat data.jsonl | anysite db insert pg --table users --stdin --auto-create
anysite db query pg --sql "SELECT * FROM users" --format table
anysite db query pg --sql "SELECT * FROM users" --format parquet --output users.parquet
anysite db query pg --sql "SELECT * FROM users" --format csv --output "reports/{{date}}/users.csv"
anysite api /api/linkedin/user user=satyanadella -q --format jsonl \
| anysite db insert pg --table profiles --stdin --auto-create
anysite db discover mydb
anysite db discover mydb --with-llm
anysite db discover mydb --tables users,posts
anysite db discover mydb --exclude-tables _migrations
anysite db catalog
anysite db catalog mydb
anysite db catalog mydb --table users
anysite db catalog mydb --json
Credentials: --password saves directly in ~/.anysite/connections.yaml, --password-env references an env var. Direct value takes priority. LLM API keys follow the same pattern via anysite llm setup.
Supported databases: SQLite, PostgreSQL, ClickHouse. ClickHouse uses clickhouse-connect driver (HTTP protocol, port 8123 default, 8443 for HTTPS/SSL).
LLM Analysis Commands
Analyze collected dataset records using LLM. Requires anysite llm setup first.
Non-interactive setup (for agents):
anysite llm setup --provider openai --api-key <key> --no-test
anysite llm setup --provider anthropic --api-key-env ANTHROPIC_API_KEY --model claude-sonnet-4-5-20250514 --no-test
anysite llm summarize dataset.yaml --source profiles --fields "name,headline" --format table
anysite llm classify dataset.yaml --source posts --categories "positive,negative,neutral"
anysite llm enrich dataset.yaml --source profiles \
--add "seniority:junior/mid/senior" --add "is_technical:boolean"
anysite llm generate dataset.yaml --source profiles \
--prompt "Write intro for {name} who works as {headline}" --temperature 0.7
anysite llm match dataset.yaml --source-a profiles --source-b companies --top-k 3
anysite llm deduplicate dataset.yaml --source profiles --key name --threshold 0.8
anysite llm cache-stats
anysite llm cache-clear
Use anysite describe --search <keyword> for more endpoints.
Key Patterns
- Output formats:
--format json|jsonl|csv|table|parquet (parquet requires --output)
- Array params:
keywords=a,b,c auto-wraps as ["a","b","c"]
- Field selection:
--fields "name,headline,urn.value" (dot-notation for nested)
- Error handling:
--on-error stop|skip|retry
- Config priority: CLI args > ENV vars >
~/.anysite/config.yaml > defaults
References
For detailed option tables and advanced configuration: