exploring-data — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited exploring-data (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
ls -la <filepath> # or: wc -l for row estimatebash /mnt/skills/user/exploring-data/scripts/check_install.shReturns: installed or not_installed
if [ "$(bash /mnt/skills/user/exploring-data/scripts/check_install.sh)" = "not_installed" ]; then
bash /mnt/skills/user/exploring-data/scripts/install_ydata.sh
fibash /mnt/skills/user/exploring-data/scripts/analyze.sh <filepath> [minimal|full] [html|json]Defaults: minimal + html (also generates JSON)
Output:
eda_report.html - Interactive report for usereda_report.json - Machine-readable for Claude analysispython /mnt/skills/user/exploring-data/scripts/summarize_insights.py /mnt/user-data/outputs/eda_report.jsonClaude should read the stdout markdown summary, NOT the full JSON report.
The ydata report is exhaustive but dense; a link to it is a weak deliverable. Turn the JSON into a compact dashboard of the findings that matter:
python3 /mnt/skills/user/exploring-data/scripts/visualize_findings.py \
/mnt/user-data/outputs/eda_report.json
# → /mnt/user-data/outputs/eda_findings.htmlEmits a single self-contained HTML file (Chart.js from cdnjs, dark-mode aware): missingness by column (tiered good/bad), the most skewed or zero-inflated numeric distributions as small-multiple histograms, and the largest categorical breakdowns. --top N caps charts per category (default 6). Also reads profile_large.py --json output, so the large-file path gets the same treatment.
Present BOTH files: eda_findings.html for the headline read, eda_report.html for the full drill-down. In a chat surface that renders inline visuals, prefer rendering the two or three findings that actually answer the user's question as inline charts over linking a file — a link the user has to open is the weakest form of "showing" data.
Minimal (default, 5-10s): overview, variable analysis, correlations, missing values, alerts Full (10-20s): minimal + scatter matrices, sample data, character analysis
Full-mode triggers: "comprehensive analysis", "detailed EDA", "full profiling", "deep analysis". Otherwise minimal.
If the data has a datetime index/column and the user cares about temporal behavior (gaps, trends, seasonality, autocorrelation), pass tsmode=True to ProfileReport — run the venv python directly instead of analyze.sh:
ProfileReport(df, tsmode=True, sortby="<datetime_col>", title=...)This adds gap detection, stationarity and seasonality checks that the default report omits.
Comparing two versions of a dataset that BOTH fit in memory: use ydata's native compare — ProfileReport(df_a).compare(ProfileReport(df_b)).to_file(...). For files too big to load, or comparing against a months-old file you no longer have, use the sketch snapshot/drift ops in section C.
bash /mnt/skills/user/exploring-data/scripts/install_large.shpython3 /mnt/skills/user/exploring-data/scripts/profile_large.py <file> [--json out.json]Streams the file through DuckDB: per-column null%, approximate distinct counts (HLL), min/max/mean, approximate quantiles (t-digest) for numerics, top-5 values for strings, plus quality flags (mostly-null, constant, id-like columns). Markdown lands on stdout — read it directly, no summarize step needed. Handles csv/tsv/parquet/json/ndjson. 1M rows profiles in seconds; memory is flat regardless of file size.
For ad-hoc follow-up queries on the same large file, use DuckDB SQL directly (duckdb.connect().execute("SELECT ... FROM read_csv_auto('...')")) rather than loading pandas.
All via scripts/sketch_ops.py (deps from install_large.sh). These answer questions profilers don't:
python3 sketch_ops.py dups <file> [--threshold 0.9] [--cols a,b,c] [--unweighted]Exact duplicates counted by hash; near-duplicates via MinHash LSH over row tokens. --threshold is a weighted Jaccard cutoff: a token occurring c times in a row counts c times, so new york new york and york new score 0.5 rather than 1.0. Pass --unweighted for set semantics, where repeats are discarded. Use --cols to restrict to the columns that define identity.
python3 sketch_ops.py overlap <fileA> <fileB> --key <col> [--key-b <col>]Theta sketches per key column → estimated intersection, Jaccard, and "% of A's keys in B" both ways — answers "will this join hold?" without loading either file.
python3 sketch_ops.py snapshot <file> --out baseline.sketch.json # ~20KB
python3 sketch_ops.py drift <newfile> --baseline baseline.sketch.jsonSnapshot serializes HLL (all columns) + KLL quantile sketches (numeric columns) to a small JSON. Drift reports schema changes, >10% shifts in distinct counts, and IQR-relative quantile movement. The snapshot is a few KB — store it (repo, memory) and diff next month's delivery against it without keeping the original file.
Note: snapshot/dups stream rows through Python (~1M rows in a few seconds); profile_large is pure DuckDB and faster. For a quick look at a big file, profile first, sketch ops only when the question calls for them.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.