{
  "slug": "zero-pad-ids",
  "name": "gizza-ai/zero-pad-ids",
  "version": "0.1.0",
  "title": "Zero Pad IDs — Fix Leading Zeros on an ID Column — gizza.ai",
  "description": "Paste a CSV, TSV or list of IDs and pad (or strip) leading zeros to a fixed width, so ZIP codes, SKUs and account numbers sort and join again. Runs locally.",
  "tags": [
    "zero pad ids",
    "leading zeros",
    "csv leading zeros",
    "pad with zeros",
    "fixed width ids",
    "zip code leading zero",
    "sku padding",
    "strip leading zeros"
  ],
  "category": "text",
  "urls": {
    "page": "https://gizza.ai/tools/zero-pad-ids/",
    "markdown": "https://gizza.ai/tools/zero-pad-ids/index.md",
    "descriptor": "https://gizza.ai/tools/zero-pad-ids/tool.json",
    "deep_link_example": "https://gizza.ai/tools/zero-pad-ids/?input=id%2Cname%0A42%2Cada%0A7%2Clinus%0A12345%2Cgrace&delimiter=comma&columns=id&width=5&mode=pad&overflow=keep&non_numeric=keep&header=true&quote_style=minimal"
  },
  "cli": "gizza tool zero-pad-ids \"id,name\n42,ada\n7,linus\n12345,grace\"",
  "tool": {
    "description": "Fix an identifier column whose leading zeros were eaten (or added) somewhere upstream. A spreadsheet or loader typed the column as a number, so '00042' came back as '42' and the codes stopped sorting lexicographically, stopped joining against a reference file, and stopped matching a fixed-width spec. This left-pads the selected column(s) of a CSV/TSV table — or a plain one-ID-per-line list — with zeros up to a fixed width, and can also run the other way and strip leading zeros. Only the zeros change: cells outside the selected columns, blank cells, and (by default) cells that are not plain digits are copied through untouched, the header row is never rewritten, quoted fields keep their quoting, ragged rows keep their length, and the separator round-trips unchanged. Real digits are never truncated to make a value fit. delimiter accepts 'auto' (sniffed from the first line), a single char, or 'comma'/'tab'/'semicolon'/'pipe'. columns takes names (with header on) or 1-based positions; empty means every column, so name the ID column when the table also holds prices or quantities. width is the target length (0 = auto-fit each column to its widest value; max 64). mode is 'pad' or 'strip'. overflow decides what happens to a value already at or over the width: 'keep', 'strip' its excess leading zeros, or 'error'. non_numeric decides what happens to a cell that is not all digits: 'keep', 'pad' it anyway (for alphanumeric codes), or 'error'. header (default on) protects row 1. quote_style is 'minimal', 'always' (helps downstream readers treat the codes as text), or 'never'. Runs entirely in the sandbox; nothing is uploaded.",
    "parameters": {
      "additionalProperties": false,
      "properties": {
        "columns": {
          "default": "",
          "description": "Which columns to rewrite: a comma-separated list of column names (needs header = true) or 1-based positions, e.g. 'id,sku' or '1,3'. Default (empty) rewrites every column — name the ID column when the table also holds real numbers such as prices or quantities, which you do not want zero-padded.",
          "type": "string"
        },
        "delimiter": {
          "default": "comma",
          "description": "Field separator: 'auto' to sniff it from the first line, a single character, or a name ('comma' (default), 'tab', 'semicolon', 'pipe'). The output uses the same separator as the input. A one-value-per-line list works with any setting.",
          "type": "string"
        },
        "header": {
          "default": true,
          "description": "When true (default), the first row is a header: it is copied through untouched, so a column literally named '2024' is not padded, and it supplies the names used by the columns option. Turn it off for a bare list or a headerless export.",
          "type": "boolean"
        },
        "input": {
          "description": "The table to fix, as text — CSV/TSV, or a plain one-ID-per-line list (which is just a one-column table). Quoted fields with embedded separators or newlines (RFC 4180) are preserved, and ragged rows stay ragged. Example: 'id,name\\n42,ada\\n7,linus'. Max 5,000,000 bytes.",
          "type": "string"
        },
        "mode": {
          "default": "pad",
          "description": "Direction: 'pad' (default) left-pads values with zeros up to width; 'strip' removes every leading zero instead ('00042' becomes '42', '000' becomes '0'), for when a fixed-width export needs to go back to plain numbers. width and overflow are unused in 'strip'.",
          "enum": [
            "pad",
            "strip"
          ],
          "type": "string"
        },
        "non_numeric": {
          "default": "keep",
          "description": "What to do with a cell that is not a plain run of digits — 'SKU-9', 'N/A', '-42', '1.5': 'keep' (default) copies it through untouched; 'pad' pads it anyway, for alphanumeric codes ('AB12' at width 6 becomes '00AB12'); 'error' fails and names the row, column and value. Blank cells are always left blank under every setting — a missing ID is never invented into '00000'.",
          "enum": [
            "keep",
            "pad",
            "error"
          ],
          "type": "string"
        },
        "overflow": {
          "default": "keep",
          "description": "What to do with a value already at or over width (pad mode only): 'keep' (default) leaves it exactly as it is; 'strip' drops its excess leading zeros so it lands on the width when possible ('0000012' at width 5 becomes '00012'); 'error' fails and names the row, column and value. Real digits are never truncated, so '123456' at width 5 survives intact under every setting.",
          "enum": [
            "keep",
            "strip",
            "error"
          ],
          "type": "string"
        },
        "quote_style": {
          "default": "minimal",
          "description": "Output quoting: 'minimal' (default) quotes only fields that need it; 'always' quotes every field, which makes some spreadsheets and loaders read the padded codes as text instead of stripping the zeros again; 'never' emits bare fields, which is compact but can produce ambiguous CSV when values contain the separator.",
          "enum": [
            "minimal",
            "always",
            "never"
          ],
          "type": "string"
        },
        "width": {
          "default": 0,
          "description": "Target width in characters, e.g. 5 for a US ZIP code, 8 for an 8-digit SKU. 0 (the default) means auto: each selected column is padded up to its own widest eligible value, which is what you want when the codes were all one length before a loader ate the zeros. Ignored when mode is 'strip'. Max 64.",
          "maximum": 64,
          "minimum": 0,
          "type": "integer"
        }
      },
      "required": [
        "input"
      ],
      "type": "object"
    }
  }
}