Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Analyze Excel/CSV files with DuckDB SQL via bash.
.claude/skills/hezaohezao-data-analysis/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 23% | 0% |
| case-05 | ✗→✓ | ▲ Improved | 19% | 0% |
| case-09 | ✗→✓ | ▲ Improved | -16% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 79% | 0% |
Analyzes user-provided Excel (.xlsx/.xls) or CSV files using DuckDB — an in-process analytical SQL engine. Supports schema inspection, SQL querying, statistical summaries, and result export.
> Poirot note: The original deer-flow skill uses a bundled > scripts/analyze.py helper. Poirot doesn't bundle that script, so this > version uses bash with python3 + duckdb directly. Install duckdb first: > pip install duckdb.
bash# Install duckdb if not present pip install duckdb openpyxl
bashpython3 -c " import duckdb con = duckdb.connect() # For CSV result = con.execute(\"DESCRIBE SELECT * FROM read_csv_auto('data.csv')\").fetchall() for col in result: print(f'{col[0]:30s} {col[1]}') # For Excel (each sheet = a table) result = con.execute(\"SELECT * FROM st_read('data.xlsx', layer='Sheet1') LIMIT 0\").fetchall() # Row count count = con.execute(\"SELECT COUNT(*) FROM read_csv_auto('data.csv')\").fetchone()[0] print(f'Rows: {count}') "
bashpython3 -c " import duckdb con = duckdb.connect() # Describe statistics print(con.execute(\"SUMMARIZE SELECT * FROM read_csv_auto('data.csv')\").df().to_string()) "
bashpython3 -c " import duckdb con = duckdb.connect() # Aggregation result = con.execute(''' SELECT category, COUNT(*) as count, AVG(price) as avg_price FROM read_csv_auto('data.csv') GROUP BY category ORDER BY count DESC ''').fetchall() for row in result: print(row) # Join two files result = con.execute(''' SELECT a.id, a.name, b.amount FROM read_csv_auto('orders.csv') a JOIN read_csv_auto('payments.csv') b ON a.id = b.order_id ''').fetchall() "
bashpython3 -c " import duckdb con = duckdb.connect() # Export to CSV con.execute(\"COPY (SELECT * FROM read_csv_auto('data.csv') WHERE amount > 100) TO 'filtered.csv' (HEADER, DELIMITER ',')\") # Export to JSON con.execute(\"COPY (SELECT * FROM read_csv_auto('data.csv')) TO 'output.json' (FORMAT JSON)\") "
sqlSELECT product, SUM(CASE WHEN month = 'Jan' THEN amount ELSE 0 END) AS jan, SUM(CASE WHEN month = 'Feb' THEN amount ELSE 0 END) AS feb, SUM(CASE WHEN month = 'Mar' THEN amount ELSE 0 END) AS mar FROM read_csv_auto('sales.csv') GROUP BY product
sqlSELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY price) AS median, percentile_cont(0.95) WITHIN GROUP (ORDER BY price) AS p95 FROM read_csv_auto('data.csv')
bashpython3 -c " import duckdb con = duckdb.connect() # List sheets sheets = con.execute(\"SELECT table_name FROM st_geometry_tables()\").fetchall() # Query specific sheet result = con.execute(\"SELECT * FROM st_read('data.xlsx', layer='Sheet2') LIMIT 10\").fetchall() "
pip install duckdb openpyxl firstSUMMARIZE on verylarge datasets may be slow. Sample first: SELECT * FROM ... TABLESAMPLE 10%
read_csv_auto options.
explicit strptime parsing.
st_read reads cell values, not formula results. Useopenpyxl directly if you need computed values.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 5,997 | 10,508 | +75% | 1 | 1 | 0% | 585 | 1,556 | +166% | 0 | 0 | — |
case-02 | pass→fail | 19,434 | 7,766 | -60% | 1 | 1 | 0% | 2,214 | 1,545 | -30% | 0 | 0 | — |
case-03 | fail→fail | 9,740 | 5,868 | -40% | 1 | 1 | 0% | 520 | 1,399 | +169% | 0 | 0 | — |
case-04 | fail→pass | 8,809 | 6,003 | -32% | 1 | 1 | 0% | 1,592 | 1,955 | +23% | 0 | 0 | — |
case-05 | fail→pass | 12,551 | 8,834 | -30% | 1 | 1 | 0% | 2,083 | 2,488 | +19% | 0 | 0 | — |
case-06 | fail→fail | 17,062 | 7,147 | -58% | 1 | 1 | 0% | 2,612 | 2,290 | -12% | 0 | 0 | — |
case-07 | pass→pass | 16,309 | 17,821 | +9% | 1 | 1 | 0% | 2,689 | 3,181 | +18% | 0 | 0 | — |
case-08 | pass→pass | 9,731 | 6,252 | -36% | 1 | 1 | 0% | 1,727 | 2,269 | +31% | 0 | 0 | — |
case-09 | fail→pass | 13,730 | 6,514 | -53% | 1 | 1 | 0% | 2,506 | 2,104 | -16% | 0 | 0 | — |
case-10 | fail→pass | 10,286 | 6,348 | -38% | 1 | 1 | 0% | 1,714 | 2,093 | +22% | 0 | 0 | — |
case-11 | pass→pass | 10,871 | 5,212 | -52% | 1 | 1 | 0% | 1,463 | 1,765 | +21% | 0 | 0 | — |
case-12 | pass→pass | 12,634 | 5,004 | -60% | 1 | 1 | 0% | 2,218 | 1,997 | -10% | 0 | 0 | — |
case-13 | pass→pass | 34,559 | 27,450 | -21% | 1 | 1 | 0% | 7,269 | 7,120 | -2% | 0 | 0 | — |
case-14 | pass→pass | 14,472 | 7,554 | -48% | 1 | 1 | 0% | 2,482 | 2,142 | -14% | 0 | 0 | — |
case-15 | fail→pass | 8,072 | 7,988 | -1% | 1 | 1 | 0% | 1,298 | 2,322 | +79% | 0 | 0 | — |
case-16 | fail→pass | 15,033 | 10,567 | -30% | 1 | 1 | 0% | 2,806 | 2,907 | +4% | 0 | 0 | — |
case-17 | fail→pass | 9,993 | 4,343 | -57% | 1 | 1 | 0% | 1,537 | 1,781 | +16% | 0 | 0 | — |
case-18 | pass→pass | 13,566 | 4,644 | -66% | 1 | 1 | 0% | 2,109 | 1,759 | -17% | 0 | 0 | — |
case-19 | pass→pass | 21,389 | 19,177 | -10% | 1 | 1 | 0% | 3,348 | 4,289 | +28% | 0 | 0 | — |
case-20 | fail→pass | 8,205 | 15,891 | +94% | 1 | 1 | 0% | 1,502 | 1,927 | +28% | 0 | 0 | — |
case-21 | fail→pass | 9,100 | 6,167 | -32% | 1 | 1 | 0% | 1,508 | 2,183 | +45% | 0 | 0 | — |
case-22 | pass→pass | 9,768 | 5,839 | -40% | 1 | 1 | 0% | 1,542 | 2,037 | +32% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +36 percentage points is the difference between those two pass rates over the 19 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.