Skip to content
Back to skills

Safe Analysis

ASecurity

sensitive data, patient data, analyze without sharing, safe analysis, don't send my data, confidential dataset, analyze locally, keep data local, work with patient data, GDPR-safe analysis, de-identify, metadata only, send code not data, analyse my data safely, dashboard from sensitive data

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 23, 2026
ai-agentspythongosqlapi

Works with

  • api

Security analysis

A100/100

Scanned September 23, 2026

npx -y skills add SVerITG/Metis --skill safe-analysis --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Safe Analysis?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Safe Analysis
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/sveritg-safe-analysis-metis/badge)](https://www.skillsdirectory.com/skills/sveritg-safe-analysis-metis)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: Safe Analysis
description: "sensitive data, patient data, analyze without sharing, safe analysis, don't send my data, confidential dataset, analyze locally, keep data local, work with patient data, GDPR-safe analysis, de-identify, metadata only, send code not data, analyse my data safely, dashboard from sensitive data"
effort: normal
complexity: standard
---

## Purpose

The safe way to use Metis on sensitive data — patient records, identifiable surveillance data, embargoed or unpublished datasets. **The raw data never enters a prompt.** Metis writes the analysis code, *you* run it on your own machine, and only derived, non-identifiable outputs (column names, value counts, summary tables, model results) come back. Claude reasons over the **shape** of your data, never the records.

This is the generalised, repeatable form of the "send code, not data" pattern (see the README Data Protection section). It is how a full dashboard or analysis can be built without any identifiable data ever leaving the researcher's computer.

## The contract (non-negotiable)

1. **Never ask the user to paste raw data, individual records, or a data file's contents.** If you need to understand the data, ask about its *structure*, or generate code that reports that structure.
2. **If the user pastes something that looks like raw or sensitive data, STOP.** Do not use it. Call `check_data_safety` on it; if the classification is `CONFIDENTIAL` or `SENSITIVE`, tell them plainly, discard it from your working answer, and hand them a script that emits only aggregates instead.
3. **Only ever request or accept aggregates:** column names, data types, value counts / frequency tables, ranges, missingness, summary statistics, model coefficients and diagnostics, and the like.
4. **All raw-data computation happens on the user's machine.** Metis's job is to produce code and to reason over the metadata that comes back.

## What to do when invoked

**Usage:** `/safe-analysis [what you want to do]`
e.g. *"build a dashboard for my screening dataset"*, *"interpret my logistic model"*, *"make Table 1"*, *"profile and clean this CSV"*.

**Step 1 — Clarify the goal, not the data.**
Ask only what you need and nothing identifiable: What's the task? What format is the data (CSV / Excel / SPSS / Stata / SQLite)? Roughly what *domains* of variables does it hold (e.g. "demographics, test results, dates") — never the values? R or Python?

**Step 2 — State the plan in plain language.**
> "Here's a script you'll run on your own machine. It prints only [the schema / value counts / a summary table / the model output]. Nothing identifiable leaves your computer. Paste me back only that output."

**Step 3 — Generate the local script.**
Emit a self-contained script (Step-templates below) that: reads their file path (placeholder), computes the needed metadata, and **prints only safe aggregate output** — never row-level data. Cap or omit any example values. Where useful, also have it write the metadata to a small `*_metadata.txt`/`.json` they can review before sharing.

**Step 4 — Receive metadata → sanity-check → do the work.**
When they paste the output: glance for anything identifiable (when unsure, call `check_data_safety`). Then perform the actual task using only that metadata, routing to the right specialist — **Dashboard Engineer** (dashboards), **Biostatistician** (models/power), **Methods Coach** (method choice), **Data Analyst** (profiling/cleaning), **Writing Partner** (Table 1 / results prose).

**Step 5 — Record.**
`log_agent_run(agent_slug="data-guardian", task_summary=..., session_id=...)` and a brief `write_reflexion`. Offer to capture the analysis as a project/idea.

## Script templates

### A. Profile / codebook — for dashboards, cleaning, understanding structure
```r
# R — prints schema + value summaries ONLY. No raw rows leave your machine.
df <- read.csv("PATH/TO/your_data.csv", stringsAsFactors = FALSE)  # or readxl/haven
cat("Rows:", nrow(df), " Cols:", ncol(df), "\n\n")
for (v in names(df)) {
  x <- df[[v]]
  cat(sprintf("%-24s %-10s  missing=%d  unique=%d\n",
              v, class(x)[1], sum(is.na(x)), length(unique(x))))
  if (is.numeric(x)) {
    cat("   range:", paste(round(range(x, na.rm = TRUE), 3), collapse = " – "),
        " mean:", round(mean(x, na.rm = TRUE), 3), "\n")
  } else if (length(unique(x)) <= 20) {           # only low-cardinality categoricals
    print(table(x, useNA = "ifany"))
  } else {
    cat("   (high-cardinality — value list withheld)\n")  # e.g. names/IDs: never printed
  }
}
```
```python
# Python equivalent
import pandas as pd
df = pd.read_csv("PATH/TO/your_data.csv")            # or read_excel / read_stata / read_spss
print("Rows:", len(df), "Cols:", df.shape[1])
for v in df.columns:
    s = df[v]
    print(f"{v:24} {str(s.dtype):10} missing={s.isna().sum()} unique={s.nunique()}")
    if pd.api.types.is_numeric_dtype(s):
        print("   range:", round(s.min(),3), "-", round(s.max(),3), " mean:", round(s.mean(),3))
    elif s.nunique() <= 20:
        print(s.value_counts(dropna=False).to_string())
    else:
        print("   (high-cardinality — values withheld)")
```

### B. Table 1 — descriptive stats by group
```r
# Counts/means/proportions only — never individual rows.
library(dplyr)
df %>% group_by(GROUP_VAR) %>% summarise(
  n = n(),
  age_mean = round(mean(AGE, na.rm = TRUE), 1),
  positive_pct = round(100 * mean(RESULT == "positive", na.rm = TRUE), 1)
) %>% print()
```

### C. Model interpretation — fit locally, share only the summary
```r
m <- glm(outcome ~ age + sex + zone, data = df, family = binomial)
print(summary(m))            # coefficients, SEs, p-values — no data
print(exp(cbind(OR = coef(m), confint(m))))   # odds ratios + 95% CI
# (paste this output; Metis interprets it and drafts the methods/results)
```

### D. De-identification — make a dataset shareable (output stays local too)
```r
# Hash IDs, shift dates per-subject, coarsen geography, check k-anonymity.
library(digest)
df$id_hash <- vapply(df$patient_id, function(z) digest(paste0(z, "SALT")), character(1))
df$patient_id <- NULL
df$zone <- df$health_zone            # keep zone, drop village/GPS
# k-anonymity check on the quasi-identifiers you keep:
ka <- df %>% count(sex, age_band, zone) %>% summarise(min_k = min(n))
cat("min k =", ka$min_k, "(want >= 5)\n")
saveRDS(df, "deidentified_local_only.rds")   # stays on your machine
```

## Safety net (not the first line of defence)

The pipeline's Data Guardian (`scan_content`, Stage 3) classifies every request, and `check_data_safety` can scan any pasted text on demand. But the whole point of this workflow is that the Guardian rarely has to fire — because only metadata is ever shared in the first place.

## Collaboration

Data Guardian (classification) · Data Analyst (profiling/cleaning) · Biostatistician (models, power) · Methods Coach (method choice) · Dashboard Engineer (dashboards) · Writing Partner (Table 1 / results prose).

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.