A skill that ships its own Python script: profile any CSV's columns, types, gaps and outliers in one command.
WHEN TO USE IT
When you hand Claude data files often, and want the same reliable first look every time instead of ad-hoc pandas.
Formats change. If a field stops working, check it against Anthropic's documentation.
${CLAUDE_SKILL_DIR} resolves to the skill's own folder, so the script is found wherever the skill is installed.
---
name: csv-profiler
description: Profile a CSV file — row count, column types, missing values, distinct counts and numeric ranges. Use when the user shares or asks about a CSV or TSV file.
allowed-tools: Bash(python *)
---
To profile a CSV, run the bundled script rather than writing new code:
```bash
python "${CLAUDE_SKILL_DIR}/scripts/profile.py" path/to/file.csv
```
Then summarise for the user:
- What each column appears to hold
- Columns with missing values, and how many
- Anything suspicious: a numeric column stored as text, a column that
is all one value, an id column with duplicates
Do not load the whole file into the conversation.
Standard library only, so it runs anywhere Python 3.9+ does — no pandas to install first.
import csv
import sys
from collections import Counter
def as_number(value):
try:
return float(value.replace(",", ""))
except ValueError:
return None
def main(path):
with open(path, newline="", encoding="utf-8-sig") as handle:
sample = handle.read(4096)
handle.seek(0)
dialect = csv.Sniffer().sniff(sample, delimiters=",;\t|")
rows = list(csv.DictReader(handle, dialect=dialect))
print(f"{path}: {len(rows)} rows")
if not rows:
return
for column in rows[0].keys():
values = [(row.get(column) or "").strip() for row in rows]
present = [v for v in values if v]
numbers = [n for n in map(as_number, present) if n is not None]
distinct = Counter(present)
kind = "number" if present and len(numbers) == len(present) else "text"
line = (f"- {column}: {kind}, {len(values) - len(present)} missing, "
f"{len(distinct)} distinct")
if kind == "number":
line += f", min {min(numbers):g}, max {max(numbers):g}"
elif distinct:
top, count = distinct.most_common(1)[0]
line += f", most common {top!r} ({count})"
print(line)
if __name__ == "__main__":
if len(sys.argv) != 2:
sys.exit("usage: profile.py <file.csv>")
main(sys.argv[1])
Keep the folder layout — SKILL.md at the top, the script under scripts/.
mkdir -p ~/.claude/skills/csv-profiler/scripts
mv SKILL.md ~/.claude/skills/csv-profiler/
mv profile.py ~/.claude/skills/csv-profiler/scripts/
# then, inside Claude Code:
# what's in sales-2026.csv? (Claude loads the skill itself)
# /csv-profiler sales-2026.csv (or call it directly)
MORE SKILLS
The authority
Anthropic's documentation for Skills
This template is a starting point. Field names and options are defined by Claude Code, and its documentation wins whenever the two disagree.
https://code.claude.com/docs/en/skills