X
Ingest X accounts and searches through VPS-hosted or operator-selected FxEmbed.
v2 stores canonical X records, public media pointers, reply/quote/repost relations, and engagement snapshots. Record identity is source-global, not tied to a watch.
Reply tracking
Reply tracking is opt-in under sources.x.replies. Onboarding offers Hot (24
hours), Standard (168 hours), and Niche (720 hours). The default sample is the
50 most-liked replies Argus observed. orderBy also supports newest,
oldest, replies, reposts, views, and upstream source order. Tracking
ends at the time window, not when the sample reaches 50.
Each refresh stores a conversation snapshot with observed and retained counts, ranks, completeness, and truncation. Root-post ingestion and reply refresh are independent jobs.
For agent traversal, use authenticated GET|HEAD /v1/primitives/x/2/* calls.
These bounded FxEmbed reads are transient and never ingested automatically.
What it collects
Argus collects public X posts from configured accounts and search queries. The recommended onboarding path runs FxEmbed privately on the same VPS; Cloudflare and external endpoints are advanced alternatives. Argus does not silently use an arbitrary public FxTwitter service.
Prerequisites
Select X during argus onboard. The default deploys the signed FxEmbed image
on the private Compose network and configures http://fxembed:8787. If you
choose Cloudflare or external mode, supply that deployment's origin. The base
URL is the origin; Argus appends /2/... API paths itself.
Configure the source
sources:
x:
enabled: true
endpoint: http://fxembed:8787endpoint must be an absolute URL. Argus appends account and search paths beneath this base.
Configure watches
Accounts and queries are separate inputs: accounts track a handle’s statuses; queries send a search expression. Either list may be empty.
watches:
- id: x-signals
schedule: "*/10 * * * *"
inputs:
x:
accounts: [openai]
queries: ["open source AI"]Validate and apply
argus config validate /opt/argus/argus.yaml
argus config apply /opt/argus/argus.yamlVerify ingestion
Run argus doctor --json, then query authenticated records with GET /v1/records?source=x. An immediate POST /v1/watches/x-signals/ingest queues the configured target(s).
Limits and safety
Only public data returned by your FxEmbed API is collected. Requests use a 20-second timeout and a 2 MiB response bound. FxEmbed response shape changes or non-success responses fail that collection job rather than silently inventing records.
Troubleshooting
- For VPS mode, confirm the URL is exactly
http://fxembed:8787; for an external service, use its API origin without a trailing/2path. - Confirm the source is enabled and the watch uses non-empty account or query values.
- Inspect
argus logs fxembedandargus logs argus, then runargus doctor --jsonfor the configured target.
Private account access on the local container
Guest access supports public-post retrieval. Search requires an operator-provided
X account; absent credentials return X_ACCOUNT_REQUIRED, not a successful empty
search. An account configuration alone does not prove current X search/timeline
compatibility. Verify both operations before enabling their watches.
The local image installs the system CA bundle and retains TLS certificate verification. FxEmbed runs as UID/GID 1000 without publishing port 8787. The container reads two separate, read-only mounts:
| Host path beneath the instance directory | Container input |
|---|---|
fxembed/credentials/credentials.enc.json | /run/argus-fxembed/credentials/credentials.enc.json |
fxembed/key/.credential-key | /run/argus-fxembed/key/.credential-key |
Both files must be regular files with mode 0600, readable by UID 1000. The first
contains encrypted {ciphertext, iv}; the second is a separate 32-byte base64url
key. Missing both inputs selects guest access. A partial, malformed, unreadable,
or permissively readable configuration stops startup with a bounded error.
At startup the entrypoint writes mode-0600 .dev.vars in a private temporary
in-memory directory. Pinned Wrangler loads it as ENCRYPTED_CREDENTIALS,
CREDENTIALS_IV, and CREDENTIAL_KEY bindings. Secret values never enter command
arguments, Compose environment variables, YAML configuration, or image layers.
Wrangler output and debug logs are suppressed; startup reports only configured,
missing, or failed state. Detailed collection failures remain available as bounded
Argus source/job health. No passwords or one-time codes are used.
Encrypt and install an operator-supplied account
Prepare a mode-0600 JSON input outside the repository with this structure. Replace placeholders privately, never in a shell command, chat, or log:
{
"twitter": {
"accounts": [{
"authToken": "VALUE_OF_auth_token_COOKIE",
"csrfToken": "VALUE_OF_ct0_COOKIE",
"username": "ACCOUNT_HANDLE"
}]
}
}For Buddy, the planned input is ~/.local/share/buddy-argus/credentials.json on
its VPS. That file is not provisioned by Argus; it must already contain valid
operator-supplied cookies. On a Linux Docker host, from the instance directory
(normally /opt/argus), stage it and run the image's upstream encryption tool:
cd /opt/argus
sudo install -d -m 0700 -o 1000 -g 1000 fxembed/credentials fxembed/key
sudo install -m 0600 -o 1000 -g 1000 \
"$HOME/.local/share/buddy-argus/credentials.json" \
fxembed/credentials/credentials.json
sudo docker compose run --rm --no-deps \
--volume "$PWD/fxembed/credentials:/run/argus-fxembed/credentials:rw" \
--volume "$PWD/fxembed/key:/run/argus-fxembed/key:rw" \
fxembed encrypt &&
sudo rm fxembed/credentials/credentials.json &&
sudo docker compose up -d --force-recreate fxembedThe encrypt command reuses the shipped upstream AES-256-GCM tool. It creates a
private key if absent and otherwise reuses the existing key; it never prints the
key or account data. Run the removal/restart steps only after encryption succeeds.
The original Buddy input remains private at its original location; protect it with
mode 0600 or remove it separately if you no longer need a plaintext recovery copy.
The service mounts contain only encrypted credentials and the separate key after
staging cleanup. Back up the two files separately and keep both outside Git and
public deployment artifacts.
For rotation, stage the replacement input, rerun encrypt, remove the staged
plaintext, and recreate FxEmbed. A restart reloads bindings; no image rebuild is
needed. Removing both inputs and recreating the service restores guest-only access.
These instructions cover the local container, not Cloudflare credential deployment.
Opt-in live verification
Credential-free CI does not call public X. From an Argus source checkout, pipe the shipped probe into the running Argus container on its private network:
docker compose -f /opt/argus/compose.yaml exec -T \
-e ARGUS_FXEMBED_LIVE=1 -e ARGUS_FXEMBED_LIVE_MODE=guest argus node --input-type=module < deploy/fxembed/check-live.mjsRun before installing credentials in guest mode, then repeat after installation
with ARGUS_FXEMBED_LIVE_MODE=account. Optional nonsecret probe values are
ARGUS_FXEMBED_LIVE_POST, ARGUS_FXEMBED_LIVE_QUERY, and
ARGUS_FXEMBED_LIVE_HANDLE. Account mode requires populated search and timeline
results; a failure leaves authenticated access unverified. invalid mode expects
an explicit invalid-account failure and is intended only for a separate test
instance containing deliberately invalid credentials. Repeat account mode after
restart and rotation. The probe prints only bounded success/failure summaries,
never account values, headers, or provider response bodies.