# Sheet Scrub > Drop a messy spreadsheet export - CSV, TSV, semicolon or pipe separated, a Markdown table or a JSON array of records - and the browser profiles every column and paints every dirty cell on a cell map, free, before you sign in. Then a data steward model makes the decisions a profile cannot: which spellings are the same customer, which way round ambiguous dates are written, which repeated rows are real duplicates, which outliers are typos, and what only the sheet's owner can answer. The browser applies those decisions and exports the cleaned CSV with a cell-by-cell change log. Live at https://sheet-scrub.skillsafe.ai/ · API tutorial at https://sheet-scrub.skillsafe.ai/api.html · Tokens at https://sheet-scrub.skillsafe.ai/tokens.html ## What it does One work object: one table. The first non-blank row is the header; row numbers everywhere are spreadsheet rows (header = row 1, first data row = row 2). The free profile (no account, no model): - format sniffing: delimiter chosen by the most consistent field count, RFC 4180 quoting, Markdown pipe tables, JSON arrays (or an object holding one); blank and duplicate header names are labelled; ragged rows are padded or cut and listed; a preamble above the real header (a bank statement's account block) is detected and the likely header row named - column types by majority (number, date, yes/no, text; 60% share or the column is "mixed"); identifiers with leading zeros, phone and postal columns stay text - flags, cell by cell, in four families: Format (stray, doubled or non-breaking whitespace; spelling and casing variants that are identical up to case, punctuation, spacing and "&"/"and"), Value (numbers stored as text - currency signs and codes, thousands separators, bracketed or trailing-minus negatives, percent signs, decimal commas; values of the wrong type; values outside Q1 - 3 IQR .. Q3 + 3 IQR), Date (minority date formats, day/month order that cannot be decided, impossible calendar dates, spreadsheet serial numbers in a date column), Missing (N/A, TBD, "-", #N/A and friends) - day/month evidence per date column: how many dates can only be read day-first or month-first, how many are ambiguous, and the order the unambiguous ones imply (or a conflict) - whole-row duplicates after trimming and case-folding; identifiers reused on otherwise different rows - looser same-entity candidates that also ignore Inc/Ltd/LLC/Co suffixes (reported, never flagged) - the cell map (one mark per cell, coloured by the worst family, duplicates in a gutter), per-column stacked bars, a sortable row grid, and free downloads: a mechanical clean (trim, placeholders to blank, numbers converted, unambiguous dates to ISO), the flags as CSV, the profile as Markdown One metered lane, `scrub` (gpt-terra): a decision for every column (meaning, type, canonical format, date order, placeholder policy), merges of spellings that are one entity, decisions for duplicate groups, cell-level decisions for outliers and impossible values, and questions only the owner can answer. Verdict: ready / fixable / needs_owner / unusable. The browser then applies the decisions, pins them on the map (numbered column pins, outlined cells), and reconciles them against the profile: columns with flagged cells but no decision, date orders that contradict unambiguous dates, merges naming spellings that do not exist, cells quoted differently from the sheet, duplicate groups left undecided, a "ready" verdict on a sheet with flags. Exports: cleaned CSV, change log CSV (row, column, before, after, rule, source), open items CSV, Markdown report, JSON. History is saved to the user's SkillSafe account (a declared collection) and mirrored in the browser; re-dropping a sheet with the same columns shows how many flagged cells were fixed since the last review. ## The contract Run body: `{ "task": "scrub", "context": string, "sheet": string, "facts": string }`. `sheet` is CSV of whole rows with a leading `_row` column (every flagged row first, then the first rows for context, at most 150 rows / 26,000 characters); `facts` is the JSON profile of the whole sheet. All fields are strings. The reply is one JSON object: `lane`, `title`, `headline`, `verdict`, `sheet_reading`, `columns[]`, `merges[]`, `duplicates[]`, `cells[]`, `questions[]`, `summary`, `notes_on_input[]`, `risks[]`, `next_steps[]`. ## Sources Derived from the agent skill @anthropics/clean-data-xls (https://skillsafe.ai/skill/@anthropics/clean-data-xls/), from the anthropics/financial-services-plugins repository. Not affiliated with the skill's author. The outlier fence is Tukey's (1977) far-out rule (3 x IQR).