CLI Reference¶
Synopsis¶
Global entry point defined in the src/trustsight/cli/ package.
Global flags¶
| Flag | Description |
|---|---|
-h, --help |
Show help message, including config subcommands and usage examples. |
-v, --version |
Print version number (trustsight X.Y.Z) and exit. |
--json |
Output JSON on commands that expose this option. It is a command option, not a global flag. |
The help output also documents trustsight config show, trustsight config set <key> <value>, and trustsight config sync-rules with inline examples.
Interrupt handling¶
Ctrl+C during any operation prints Interrupted. to stderr and exits with code 130 instead of dumping an SSL/httpx traceback.
trustsight review¶
Scan packages for newer versions on the AUR, produce a diff for each outdated package, run the full analysis pipeline, and print one panel per package with a summary line.
trustsight review [--limit N] [--repo REPO]... [--foreign] [--all-repos] [--verbose] [--score] [--risk] [--depth N] [--deps] [--sort score|risk|name] [--refresh]
Flags¶
| Flag | Type | Default | Description |
|---|---|---|---|
--limit |
int |
[limits] default_review_limit (0) |
Maximum number of outdated packages to review. 0 means unlimited, which is the shipped default: a review that stops early has not looked at the rest. When the limit does cut the list, the summary names how many went unread rather than reporting the smaller number as the whole. |
--verbose |
flag | false |
Render the full per-package inspection detail, including the complete declared-practice group. With --json, add score_breakdown; it does not imply --score or --risk. |
--quiet |
flag | false |
Suppress the progress bar during analysis. |
--score |
flag | false |
Show aggregate trust score for each package. |
--risk |
flag | false |
Show risk level; colours the panel border by risk. |
--depth |
int |
[depth] levels (1) |
AUR dependency levels to analyse. 0 disables it, 1 analyses direct AUR dependencies, n analyses n levels, and -1 walks every level there is - bounded by depth.MAX_DEPTH_LEVELS (8) and depth.MAX_DEPTH_NODES (200), because the dependency graph is written by the party under review. A walk cut short by either ceiling records the deps_not_scanned coverage gap. |
--all |
flag | false |
Review all installed AUR packages, not just outdated ones. |
--deps |
flag | false |
Review the AUR dependencies of the discovered packages instead of the packages themselves. Each dependency is reviewed as a package in its own right, and reports a Required by section naming the packages in the reviewed set that declare it. Honours --depth, which here means levels of dependencies to review rather than levels below each one: --deps --depth 2 reviews direct dependencies and their dependencies. The roots are not reviewed - they are what you get without the flag. Bounded by the same depth.MAX_DEPTH_LEVELS and depth.MAX_DEPTH_NODES ceilings, and a closure cut short says so. |
--repo |
str |
- | Scan packages from a specific local repository. Can be repeated (--repo aur --repo testing). |
--foreign |
flag | false |
Also include foreign packages (pacman -Qm). When used with --repo, foreign packages are added to the set. |
--all-repos |
flag | false |
Automatically detect all local repositories from /etc/pacman.conf (excludes official repos: core, extra, community, multilib, testing, etc.) and scan packages from all of them. |
--sort |
str |
discovery order | Sort results after analysis. score: worst (highest) first. risk: Critical, High, Medium, Inconclusive, Low. name: alphabetical. When omitted, results appear in discovery order (the order pacman or AUR returned them). |
--refresh |
flag | false |
Force refresh the AUR metadata snapshot regardless of the configured TTL. Useful when the snapshot is stale but its age is still within the TTL window. |
Flag precedence¶
If any discovery flag (--repo, --foreign, --all-repos) is given on the command line, the [discovery] config section is ignored for that run. Otherwise, the config defaults apply (see Configuration Reference).
Examples¶
trustsight review # Foreign packages only (default)
trustsight review --repo aur # Packages from the aur repo only
trustsight review --repo aur --repo testing --foreign
# aur + testing repos + foreign
trustsight review --all-repos # All local repos, no foreign
trustsight review --deps # The dependencies, not the packages
trustsight review --deps --depth 2 # ...and their dependencies too
trustsight review --all-repos --foreign
# All local repos + foreign
Behaviour¶
Discovery uses a local AUR metadata snapshot by default:
- Collects package names and versions from the requested sources (repo contents via
pacman -Sl <repo>intersected withpacman -Q, foreign viapacman -Qm, or auto-detected repos viapacman-conf --repo-list). - Looks up each installed package in the AUR metadata snapshot (
full-aur-meta.json, an offline copy of the AUR package database). On the first run the snapshot is downloaded and the run stops there, since there is nothing to compare against yet. Later runs reuse the snapshot until it is older than[discovery] metadata_ttl_minutes(default 60), then refetch it: the version a review compares against is the snapshot's, so a snapshot left to age reports a machine with pending updates as fully current. A refresh that cannot reach the AUR keeps the snapshot on disk and warns that a package updated since then will not be reported. - Filters to packages whose installed version is older than the snapshot version (using
vercmp). - For each outdated package (up to
--limit): clones/fetches the repository, computes a git diff between the last-analysed commit and HEAD, applies the published R/H/C/D/S/X rule families, classifies source URLs into trust buckets, checks novelty against the local database, calculates a deterministic 0-100 score, and generates a verdict. - Prints one panel per package, and a summary line counting what needed review separately from what was read.
With --deps the subject changes: step 3's outdated set becomes the roots of a dependency closure walked to --depth, and it is the dependencies that are analysed and printed, each naming the packages that require it.
If the metadata snapshot is unavailable or corrupt, the tool falls back to the AUR RPC interface (https://aur.archlinux.org/rpc?v=5&type=info) for the same comparison.
Output¶
Uses rich tables when available; falls back to plain text.
With --json, review writes a JSON list of report bodies to stdout. Progress
events go to stderr. The default body includes findings, changes, coverage,
suppressed rules, and the verdict, but withholds score, risk, and
risk_label; pass --score or --risk to include them. --verbose adds
score_breakdown.
trustsight inspect¶
Show the full analysis for a single package: version diff, maintainer change, diff summary, checksum behaviour, added source URLs with bucket classification, resolved commands, triggered rules, and status.
Arguments¶
| Argument | Required | Description |
|---|---|---|
package |
Yes | AUR package name to analyse. |
Flags¶
| Flag | Description |
|---|---|
--verbose |
Include the full declared-practice group in terminal output and score_breakdown in JSON. It does not imply --score or --risk. |
--score |
Show aggregate trust score with weight contribution breakdown. |
--risk |
Show risk level with per-rule severity labels. Implies a coloured border in rich mode. |
--depth |
AUR dependency levels to analyse: 0 off, 1 (default) direct dependencies, n levels, -1 every level (bounded). Each dependency is analysed as a package in its own right, with its own score and band, shown as a mini-card inside the package's card. |
--allow-uninstalled |
Analyse a package that is not in the local pacman set. The name is resolved against the AUR and cloned. Without this flag, inspect refuses a name not present locally. |
--last N |
Analyse the N most recent content-bearing commits as N separate results, newest first. N >= 1 and N <= 50. Commits whose diff is empty after filtering (.SRCINFO- and .gitignore-only regenerations) are skipped and do not count toward N. Combined with --depth > 0 is refused in this version. |
--record |
Write observations to the database. Only meaningful with --allow-uninstalled; without it, installed packages already record on every analysis. |
Output¶
With --json, inspect writes one report body to stdout (or, with --last N, an array of bodies). Its optional score
and verbose fields follow the same rules as review --json.
When rich is available:
╭───────────────────── TrustSight Inspect: example-pkg ──────────────────────╮
│ Version 1.4.2-1 -> 1.5.0-2 │
│ Not vetted the diff exceeded the size cap, so only its first │
│ bytes were examined │
│ Lines +6 -2 │
│ Maintainer Jane Doe <[email protected]> │
│ Checksum checksum_added_or_changed │
│ │
│ What changed │
│ pkgver 1.4.2-1 -> 1.5.0-2 │
│ checksums added or changed │
│ source host added: example.invalid │
│ │
│ Files changed │
│ ~ PKGBUILD │
│ ~ .SRCINFO │
│ │
│ Source URLs added │
│ [unknown] https://example.invalid/p.tar.gz │
│ │
│ Resolved commands │
│ curl -fsSL https://example.invalid/p.tar.gz │
│ │
│ Rules Triggered │
│ R001 Remote Script Execution │
│ │
│ Unverifiable findings │
│ W001 Executes Code This Analysis Did Not Read │
│ │
│ Declared verification │
│ P001 checksums declared for all non-VCS sources │
│ P002 validpgpkeys declared │
│ │
│ Dependencies │
│ ╭──────────────── L1 libhelper ─────────────────╮ │
│ │ Findings 2 │ │
│ ╰────────────────────────────────────────────────╯ │
│ │
│ Suppressed by override │
│ R099 known │
│ │
│ Status The update is not trivial. Review it. │
╰────────────────────────────────────────────────────────────────────────────╯
Sections appear only when they have content. Status is printed once, at the
foot of the panel.
The --score flag shows per-rule weights (+40) and a Score N/100 (risk)
row with the weight sum beneath it. The --risk flag shows per-rule severities
(CRITICAL) and a Risk <level> row, and colours the border by band. Without
either flag the band is withheld everywhere, dependency cards included, and the
border is blue. When both are given the Score row wins, since it already names
the band.
The plain-text fallback carries the same sections in the same order, and nothing is dropped from it: a field on one renderer and not the other is a difference in information, which B11 forbids.
Database¶
The analysis result (PackageFact serialised to JSON, triggered rules, raw diff) is persisted to the local SQLite database before output is printed.
trustsight history¶
Show analysis history for a package.
trustsight history <package> [--limit N] [--score-breakdown] [--json] [--from-date DATE] [--to-date DATE]
Arguments¶
| Argument | Required | Description |
|---|---|---|
package |
Yes | AUR package name. |
Flags¶
| Flag | Type | Default | Description |
|---|---|---|---|
--limit |
int |
20 |
Maximum number of history entries to display. 0 means all entries; a negative value is an error. |
--score-breakdown |
flag | false |
When set, print the score breakdown for the latest (most recent) history entry. |
--json |
flag | false |
Emit history rows as JSON. With --score-breakdown, the latest row includes triggered_rules when rules were recorded. |
--from-date |
str |
- | Only show entries with a timestamp on or after this date. Accepts YYYY-MM-DD or full ISO datetime. Useful for "was this package safe three months ago?". |
--to-date |
str |
- | Only show entries with a timestamp on or before this date. Accepts YYYY-MM-DD or full ISO datetime. Inclusive: --to-date 2026-06-01 includes entries from that day. |
Output¶
Table with columns: Date, Old, → New, Score, Risk. Stored risk preserves an incomplete or cold-start qualification rather than being recomputed from the numeric score.
If --score-breakdown is set, the triggered rules for the latest entry are printed below the table.
trustsight list¶
List all packages tracked in the database with their latest score.
Flags¶
| Flag | Type | Default | Description |
|---|---|---|---|
--limit |
int |
0 |
Maximum number of packages to show. 0 means unlimited. |
--sort |
str |
alphabetical | Sort results. score: highest (worst) first. risk: Critical, High, Medium, Inconclusive, Low. name: alphabetical. last-checked: oldest first. Packages that have never been analysed sort last. |
Output¶
Table with columns: Package, Version, Maintainer, Last Checked, Score, Risk.
With --json, each row also carries a verdict field: the stored risk band (e.g., Low, Medium, High, Critical, Inconclusive). Packages that have never been analysed show - for score and - for verdict. Version strings that could not be resolved (raw bash expressions, nested parameter expansions) display as unresolved.
trustsight forget¶
Remove a tracked package and all associated history (analysis history, triggered rules, snapshots, profiles, alert state). Package data is removed permanently; source URL and maintainer records are reassigned to the internal sentinel rather than deleted.
Arguments¶
| Argument | Required | Description |
|---|---|---|
package |
One or more | Package name(s) to remove from tracking. |
Flags¶
| Flag | Description |
|---|---|
--prune |
Remove every tracked package that no longer exists in the AUR. Re-verifies each name against the AUR RPC and removes absent ones. Useful for cleaning up packages that were deleted from the AUR or that were never in it. |
--dry-run |
Show what would be removed without actually deleting anything. Only meaningful with --prune. |
--yes |
Skip the confirmation prompt when removing named packages (always skips for --prune). |
Behaviour¶
When removing named packages:
- Deletes
alert_state,pkgbuild_snapshots,package_profiles, andpackage_propertiesrows keyed by the package name. - Deletes
triggered_rulesrows (viaanalysis_history). - Deletes
analysis_historyrows. - Reassigns
source_urls.first_seen_package_idandmaintainers.first_seen_package_idto the internal sentinel (id 0). - Deletes the
packagesrow.
Reserved names (__seed__, or any name starting with __) cannot be forgotten and raise an error.
Examples¶
trustsight forget aurch # Remove a single non-AUR helper
trustsight forget aurch openssl-1.1 # Remove multiple packages
trustsight forget --prune --dry-run # Show what would be pruned
trustsight forget --prune # Remove all non-AUR packages
trustsight status¶
Show database and system health statistics.
Output¶
| Metric | Description |
|---|---|
| Packages tracked | Number of distinct packages in the local database. |
| Total analyses | Analysis runs recorded across all packages. |
| Effective observations | Max of real analyses and seed bootstrap (what maturity() actually sees). |
| Seed observations | Bootstrap count from the novelty seed, or 0 if not imported. |
| Dependency corpus | Whether the dependency observation table has been populated. |
| Rule patterns | Whether shipped rule patterns match the installed rules.toml. Shows "Up to date" or "N stale". |
trustsight config¶
View or modify TrustSight configuration.
Subcommands¶
| Subcommand | Description |
|---|---|
show |
Print the current configuration from ~/.config/trustsight/config.toml. Displays seed auto-import status, experimental rules toggle, and scoring weights. |
set <key> <value> |
Set a configuration value. Example: trustsight config set seed.auto_import false. |
sync-rules |
Add rules that ship with this version but are absent from your rules.toml. |
sync-rules¶
rules.toml is written only when it does not exist, so upgrading the package
never changes it. An install that predates a rule addition silently never
receives that rule, and a corrected pattern never reaches anyone who already
has the file.
Without flags, starts an interactive wizard that shows what changed (new rules, outdated patterns, drifted fields) and offers full update, safe update, or skip.
| Flag | Description |
|---|---|
--update |
Also replace rules whose current pattern is one this project shipped previously. A rule whose pattern matches neither the current default nor a known earlier one has been edited by you and is never touched. |
--full |
Fully overwrite all rules with shipped defaults. Overrides user customisations. |
Adding is always safe and happens by default. Replacing is not, which is why it
is opt-in and limited to rules you demonstrably have not customised.
trustsight lint-rules reports both conditions.
Config file location¶
~/.config/trustsight/config.toml; created automatically on first run via ensure_default_configs().
trustsight override¶
Suppress a rule that misfires on your packages, with a recorded reason.
trustsight override list
trustsight override add <rule_id> --reason "..." [--package NAME]
trustsight override rm <rule_id> [--package NAME]
trustsight override wizard <package>
Some rules are correct in general and wrong for you. R010 fires on any curl
inside a build function; if you maintain a package that legitimately fetches at
build time, that finding is noise on every single review, and noise that never
goes away is worse than no finding at all, because it trains you to skim.
Subcommands¶
| Subcommand | Description |
|---|---|
list |
Show configured overrides. This is the default when no subcommand is given. |
add <rule_id> |
Suppress a rule. --reason is required. |
rm <rule_id> |
Stop suppressing a rule. Exits non-zero if no override matched. |
wizard <package> |
Interactive wizard: analyses the package, shows triggered non-FATAL rules, and prompts you to suppress each with a reason. |
Flags¶
| Flag | Description |
|---|---|
--reason TEXT |
Why the rule is suppressed. Required on add; an override with no stated reason is indistinguishable later from a mistake. |
--package NAME |
Limit the override to one package. Without it, the override applies to every package. |
What an override does not do¶
An override removes a finding from the score, but the finding is still recorded
and still reported, under a Suppressed by override heading in
trustsight inspect, with the reason you gave. A suppression you cannot see is
indistinguishable from a detection that never happened.
FATAL rules cannot be overridden. add refuses to create one, and the
filter refuses to honour one even if the file is edited by hand. R012 (prompt
injection) and R013 (unicode deception) are the two findings an attacker would
most want switched off, and both indicate the package is trying to deceive the
reviewer rather than merely doing something unusual.
Overrides live in ~/.config/trustsight/overrides.json.
trustsight seed-db¶
Import the novelty seed database, so a fresh install is not cold.
On an empty database every source URL looks first-seen and maturity() returns 0, which gates tier C off entirely and downgrades every Medium verdict to INCONCLUSIVE. Maturity is global to the database, not per package. The seed supplies both halves of what maturity is really asking about: a body of known AUR source URLs, and a bootstrap observation count.
The seed is not shipped inside the package. It is published as the signed
baseline-seed.tar.gz release asset (v2 hashed format) and fetched with
trustsight seed fetch; seed-db --file still imports any .db, .db.gz
or .tar.gz seed you built yourself. The underlying data is built from the
AUR git mirror by scripts/generate_seed.py, which parses each package's
.SRCINFO (including the arch-suffixed source_x86_64 arrays, where -bin
packages put their real download) and the # Maintainer: comment from its
PKGBUILD. URLs are normalised with the same normalize_url() the runtime
uses, so a routine version bump matches a seeded entry.
Flags¶
| Flag | Description |
|---|---|
--import |
Import the seed. This is the default action; the flag is accepted for explicitness. |
--file PATH |
Import a specific seed file (.db, .db.gz, or a .tar.gz v2 seed) instead of the default. |
--force |
Re-import even if a seed has already been imported. |
Automatic import¶
Only trustsight review and trustsight inspect attempt the verified
release-channel seed, and only when the database has no seed and no
analysis history. Other commands never trigger that fetch. On a machine without
network, or when the download fails verification, the attempt is silently
skipped and the run starts cold.
Disable with:
Import takes a few seconds for the full seed and is additive: existing rows win, so a seed can never overwrite something learned from a real analysis, and re-importing is a no-op.
Maturity handover¶
effective_observation_count() returns max(real_analyses, seed_observation_count). Real analyses take over as soon as they outnumber the seed, so ordinary use replaces the bootstrap and the tool never depends on external data permanently.
Trust¶
The seed is derived entirely from public AUR data and is reproducible: re-running the generator against the same mirror produces the same database. The release asset is accepted only when its detached ed25519 signature verifies against the key pinned in the package (fingerprint in baseline keys); the import records the digest of the exact bytes that were verified. It only ever makes novelty signals quieter; it cannot lower a rule score, change a severity, or suppress a finding. A tampered seed could at most hide a novelty signal, never fabricate an UNFLAGGED verdict.
trustsight seed¶
Inspect and migrate the hashed maintainer seed.
trustsight seed info
trustsight seed stats
trustsight seed migrate [--from-backup]
trustsight seed fetch [--tag TAG] [--key PATH]
Subcommands¶
| Subcommand | Description |
|---|---|
info |
Show seed metadata and hashing configuration. |
stats |
Show hashed maintainer counts by source. |
migrate |
Migrate plaintext maintainer rows into the hashed store. |
fetch |
Download baseline-seed.tar.gz from the release channel, verify its detached Ed25519 signature against the pinned distribution key, and import it. Refuses (exit 2) anything that does not verify. |
Flags¶
| Flag | Description |
|---|---|
--tag |
Fetch a specific release tag instead of the latest release. |
--key |
Verify against this ed25519 public key file instead of the pinned key shipped in the package. |
--from-backup |
Migrate from the maintainers_deprecated_backup table left behind after the automatic v0.12.0 migration. |
--json |
Output JSON. |
trustsight db¶
Database maintenance commands: integrity check, vacuum, and backup.
Subcommands¶
| Subcommand | Description |
|---|---|
check |
Run PRAGMA integrity_check on the database. Exits 0 on success and 2 if corruption is detected, including with --json. |
vacuum |
Reclaim disk space by rebuilding the database file. Prompts for confirmation unless --force is passed. |
backup |
Create a safe online backup via sqlite3.backup(). No need to stop TrustSight. Default output: <db_path>.YYYYMMDD-HHMMSS.bak. |
Common flags¶
| Flag | Description |
|---|---|
--json |
Output JSON. |
trustsight lint-rules¶
Check rules.toml for rules that are unreachable, over-broad, or malformed.
A malformed rule fails silently at runtime. An empty pattern matches every line, and at FATAL severity forces every package to score 100. A pattern that only matches comment text can never fire, because the engine strips comments before matching. Neither failure is visible without a corpus.
Flags¶
| Flag | Description |
|---|---|
--file PATH |
Lint a specific rules TOML file instead of ~/.config/trustsight/rules.toml. Use in CI to check the ruleset in the repository. |
--json |
Output the source, counts, findings, and any missing or superseded shipped-rule notices as JSON. |
Checks¶
| Check | Level | Meaning |
|---|---|---|
required-field |
error | A rule is missing id, name, pattern, severity, or category. |
empty-pattern |
error | The pattern is empty, so it matches every line. |
matches-everything |
error | The pattern matches the empty string. |
compile |
error | The pattern does not compile. apply_rules() skips uncompilable rules silently. |
backtracking |
error | The pattern is superlinear on adversarial input; a crafted PKGBUILD line could hang the scan. |
duplicate-id |
error | Two rules share an id, so the later one silently redefines what the id means in baselines and fixtures. |
programmatic-id |
error | The id is one the analysis modules emit rather than one rules.toml defines. Every catalog id that is not a shipped TOML rule is reserved, so defining it here would make one id mean two different things. |
severity |
error | Unknown severity. Unknown severities score 0. |
match-target / scope |
error | Unknown match_target, or an unknown scope value. |
comment-shadowed |
error | Every line the pattern matches is a comment or depends declaration, which filter_raw_lines() strips before matching. |
scope-contradiction |
warning | The pattern matches a function header line while scoping itself to function_body. A bare header is classified other, so the rule misses the ordinary multi-line form; it still fires on a single-line definition. |
benign-hit |
warning | A MEDIUM-or-higher rule fires on ordinary packaging in the probe corpus (for example chmod 644 or an install into $pkgdir/etc). |
end-anchor |
warning | A raw_line pattern is anchored with $, but raw diff lines keep trailing quotes and parentheses. |
scope-shadowed |
warning | The pattern matches probe lines, but none within its declared scope. |
id-format / scope-ignored |
warning | The id does not follow the R###/C### convention, or scope is set on a resolved rule, where it is ignored. |
How reachability is checked¶
Rules are run through the real matching engine against a small annotated probe diff, so comment filtering and function-body scoping apply exactly as they do in production. Probe lines are tagged benign or suspicious; a high-severity rule firing on a benign line is reported as benign-hit, because a rule that matches ordinary packaging will fire across a large share of the AUR.
Backtracking is measured rather than guessed. Static nested-quantifier heuristics false-positive on safe patterns such as (?:-\S+\s+)*, where the inner and outer character classes are disjoint. Probe inputs are capped at 22 characters (adjusted for Python 3.12+ optimized re engine) so that detecting an exponential pattern does not itself hang the linter.
Exit codes¶
| Code | Meaning |
|---|---|
0 |
No errors (warnings may be present). |
2 |
At least one error, or the --file path does not exist. |
trustsight baseline¶
Build or import a full-AUR baseline corpus. The baseline is a signed artifact containing analysis profiles for every AUR package, priors for novelty detection, and a metadata snapshot for delta computation.
trustsight baseline build [--resume] [--bootstrap] [--export FILE] [--sign PATH] [--json]
trustsight baseline import FILE [--allow-unsigned] [--json]
Subcommands¶
| Subcommand | Description |
|---|---|
build |
Bootstrap or incrementally update the corpus. Fetches the AUR metadata snapshot, diffs against the stored copy, processes changed packages, and stores results. The first run processes all packages; subsequent runs only process changed ones. Suitable for cron. |
import |
Import a signed baseline artifact. Verifies the signature, then merges profiles, priors, and the metadata snapshot into the local database. After import the database is warm. |
Flags (build)¶
| Flag | Description |
|---|---|
--resume |
Resume an interrupted bootstrap. The bootstrap saves progress after each package. |
--export PATH |
Write the signed baseline artifact to this path. |
--sign PATH |
Path to an ed25519 private key to sign the artifact. |
--json |
Output JSON. |
Flags (import)¶
| Flag | Description |
|---|---|
--allow-unsigned |
Import even if the artifact is unsigned. Use only for self-built local artifacts. |
--json |
Output JSON. |
trustsight full-aur¶
Bootstrap or update the full-AUR baseline corpus. Fetches the AUR metadata snapshot, downloads PKGBUILDs via codeload (no git repos), analyses stateless rules, and optionally emits a signed baseline artifact.
trustsight full-aur [--bootstrap] [--resume] [--export PATH] [--sign PATH] [--json]
trustsight full-aur --watch [--interval SECONDS] [--cycles N] [--json]
Flags¶
| Flag | Description |
|---|---|
--bootstrap |
Allow a from-scratch bootstrap of the whole AUR when there is no prior snapshot. Required to start one, because it fetches every PKGBUILD; without it a snapshot-less run refuses rather than scraping ~120k packages by accident. The bootstrap is capped per cycle and resumes automatically, so run the command repeatedly to finish it in gentle chunks. |
--resume |
Accepted and implied. Every cycle resumes automatically from its saved progress, so the flag has no effect. |
--export PATH |
Write the signed baseline artifact to this path. Only written when the cycle completes the current transition; a capped, still-pending cycle does not export a half-built corpus. |
--sign PATH |
Path to an ed25519 private key to sign the artifact. |
--watch |
Keep running cycles on an interval until interrupted. |
--interval SECONDS |
Seconds between --watch cycles. Defaults to [limits] watch_interval (3600) and is clamped to [limits] watch_min_interval (60). |
--cycles N |
Stop --watch after N cycles. 0, the default, means run until interrupted. |
--json |
Output JSON. |
With a prior snapshot present (any trustsight review run creates one), a cycle processes only the changed packages, which is the intended cadence: run it periodically and the corpus grows incrementally. A from-scratch bootstrap is the exception, gated behind --bootstrap. Either way, each invocation is capped at [limits] corpus_max_per_cycle (default 2000) and resumes, so a large amount of work advances in bounded, resumable chunks rather than one avalanche.
Use --export to produce a shareable baseline that other TrustSight instances can consume via trustsight import-baseline.
What one cycle does¶
- Fetch the AUR metadata snapshot and diff it against the stored copy.
- Download and analyse the PKGBUILDs of everything added or changed.
- Run the Class D corpus sweep over the whole metadata delta, which returns one finding per cluster rather than one per member.
- Record the cycle into the adoption feed that H073's introduction-rate baseline reads.
- Report the packages that scored 40 or more this cycle, worst first.
The first cycle of a fresh install is a bootstrap: with no prior snapshot there is nothing to deviate from, so the corpus sweep is silent by construction.
Progress and performance¶
A bootstrap analyses the whole AUR (tens of thousands of packages), and its cost is dominated by one PKGBUILD fetch per package. Two things make that bearable:
- A progress bar. When the output is an interactive terminal, the analysis loop renders a live bar on stderr with the current package, an
M/Ncount, elapsed time and an ETA. It is on stderr so it never corrupts a--exportartifact or a piped--jsonstream; a non-TTY (a cron job, a pipe,--json) falls back to a log line every 1000 packages. - Parallel fetching, rate-capped. PKGBUILDs are fetched a window ahead, several at a time (
[limits] corpus_fetch_workers, default 5). Analysis itself stays strictly serial and in package order, because novelty reads the observations earlier packages recorded; only the fetch is parallelised. The AUR's cgit rate-limits per IP and runs anti-scraping, so the fetcher enforces a global aggregate rate cap (~5 requests/second across all workers) and backs off on429,5xxand connection resets, honouring aRetry-Afterheader. Raising the worker count past what the cap can keep busy only idles threads; the cap, not the worker count, is what keeps a 120k-package bootstrap from getting the IP blocked.
Benign per-package fetch fallbacks (a VCS or -bin package with no snapshot tarball falls back to a cgit text fetch) are logged at debug level, so they do not flood the bar; a genuine unfetchable PKGBUILD is counted and the total reported once at the end.
Even so, a full from-scratch bootstrap is roughly a hundred thousand rate-limited fetches, which takes hours and leans on a shared community host. Prefer to let the corpus grow incrementally: run full-aur (or --watch) periodically so each cycle fetches only the small metadata delta, and publish updated baselines over time rather than rebuilding the whole corpus at once.
Watch mode¶
--watch repeats that cycle on an interval and adds memory. A cluster is announced the first time it is seen and counted afterwards, so a quiet night prints nothing instead of re-announcing the same forty-package adoption on every cycle. The record lives in the alert_state table, keyed by package and rule, with a first-seen timestamp and a count.
The interval floor exists because the AUR regenerates its metadata dump every few minutes: anything shorter re-downloads the same snapshot and re-walks the same diff. A mistyped --interval 1 is raised to 60 rather than turned into a request loop against someone else's mirror.
Interrupting with Ctrl-C ends the loop, during a cycle or during the wait. Nothing is lost by stopping: each cycle writes its metadata snapshot and resume file before it returns, so the next run picks up from there.
--watch cannot be combined with --export or --sign. Those describe a single artifact, and pairing them with a loop would silently overwrite it every cycle; the command exits with status 2 instead.
trustsight import-baseline¶
Import a signed baseline corpus artifact. Verifies the signature, then merges profiles, priors, and the metadata snapshot into the local database. After import the database is warm: no cold-start floor, real stable_for_n values, populated priors.
Arguments¶
| Argument | Required | Description |
|---|---|---|
path |
Yes | Path to the baseline artifact (.tar.zst). |
Flags¶
| Flag | Description |
|---|---|
--allow-unsigned |
Import even if the artifact is unsigned. Use only for self-built local artifacts. |
--json |
Output JSON. |
trustsight ioc¶
Manage IOC federation baselines. Baselines are signed or unsigned directories
containing manifest.json and iocs.jsonl; they supplement the local
iocs.toml used by H056.
trustsight ioc sources
trustsight ioc import <dir> [--source NAME] [--allow-unsigned]
trustsight ioc update [--path DIR]...
trustsight ioc list [--source SOURCE] [--type TYPE] [--include-expired]
trustsight ioc export [<dir>] [--source SOURCE] [--json]
Subcommands¶
| Subcommand | Description |
|---|---|
sources |
Show configured and imported baseline sources. |
import |
Import a baseline directory. Replaces any existing rows for the same source. |
update |
Re-import baselines from local directories, or, when no --path is given, update every enabled feed whose url is a release-channel URL: the baseline-ioc-<prefix>-manifest.json / -iocs.jsonl pair is downloaded, verified against the pinned distribution key, and imported (curator-key verification still applies). Feeds with any other URL are refused. |
list |
List active IOC entries, optionally filtered by source or type. |
export |
Write the current IOC database to a baseline directory, or with --json and no directory, print the merged IOC view to stdout for debugging. |
Flags¶
| Flag | Description |
|---|---|
--source |
Override or filter by baseline source name. |
--allow-unsigned |
Import a baseline whose signature is missing or cannot be verified. Use only for local baselines. |
--path |
Baseline directory to re-import with ioc update. Can be repeated. |
--type |
Filter ioc list by indicator type (package, domain, or hash). |
--include-expired |
Include expired entries in ioc list. |
trustsight corpus pivot¶
Given one indicator, list every corpus package that references it. This inverts H056: instead of asking what a single package carries, it asks who points at a published indicator, which is the question an advisory creates.
Arguments¶
| Argument | Required | Description |
|---|---|---|
indicator |
Yes | A package name, domain, or artifact hash. The type is inferred from its shape. |
Flags¶
| Flag | Description |
|---|---|
--type |
Force the indicator type (package, domain, or hash) when the shape is ambiguous: a package name spelled like a host, or a name that is all hex of digest length. |
--json |
Output JSON. |
Behaviour¶
The match is exact: evil.example matches neither notevil.example nor cdn.evil.example, and a truncated digest matches nothing. The query does not have to appear in iocs.toml; when it does, the entry's provenance and confidence tier are reported with the result.
Only stored corpus material is searched: the AUR metadata snapshot (names, declared dependencies, upstream url=) and the stored PKGBUILD snapshots. Nothing a PKGBUILD points at is ever fetched. Package-name queries read the metadata only, because a name appearing in PKGBUILD text is not a declared fact.
The output names which stores were searched. An empty corpus reports that nothing was searched, never that nothing references the indicator. A miss is uninformative: the indicator list records what has already been reported, so it says nothing about a package it does not name.