Argus
Sources

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:8787

endpoint 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.yaml

Verify 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 /2 path.
  • Confirm the source is enabled and the watch uses non-empty account or query values.
  • Inspect argus logs fxembed and argus logs argus, then run argus doctor --json for 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 directoryContainer 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 fxembed

The 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.mjs

Run 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.

On this page