Claude Skill

csv-processor

Read a CSV file from disk, compute per-column min/mean/max for every numeric column, emit the result as JSON. Stdlib-only Python; no pandas, no numpy. Demonstrates the simplest possible "give me a file path, get back structured analysis" skill — a deliberate baseline for any skil

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download chronoaiproject-ornn-examples_csv-processor-e7e21e9.zip · 2 KB
Part of chronoaiproject/ornn — 6 skills

Install

skills CLI npx skills add https://github.com/ChronoAIProject/Ornn/tree/develop/examples/csv-processor
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install chronoaiproject-ornn@llmmart
Git git clone https://github.com/ChronoAIProject/Ornn.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole chronoaiproject/ornn collection as a plugin from our marketplace. Git is the plain clone.

README

csv-processor

Parse a CSV file, compute per-column min/mean/max for every numeric column.

Run: python src/main.py sample.csv

Adapt: add more aggregations (median, p95, stddev), or stream large files with running-mean updates. The in/out shape (path → { rowCount, columns: { ... } }) is intentionally fixed so the skill stays composable.

Stdlib only — no pandas, no numpy. See SKILL.md for the full contract.

Skill manifest

csv-processor

A deterministic, network-free skill — the easiest case. Useful as a control when debugging the agent ↔ skill plumbing: if this fails, the failure is in the runner, not the skill.

Contract

Input (single CLI argument):

python src/main.py /path/to/data.csv

The script reads argv[1] as a filesystem path. CSV must have a header row.

Output (stdout, JSON):

{
  "rowCount": 1234,
  "columns": {
    "price": { "min": 1.23, "mean": 42.0, "max": 999.99, "count": 1234 },
    "quantity": { "min": 0, "mean": 7.5, "max": 100, "count": 1230 }
  }
}

Only numeric columns appear under columns. count is the number of cells that parsed successfully (numeric); non-numeric / blank cells are skipped.

Errors — written to stderr as {"error": "..."} and exit code 1.

Run locally

cd examples/csv-processor
python src/main.py sample.csv

A sample.csv is bundled so the example runs out of the box.

Adapt this

  • Different aggregations — add median, p95, stddev; same shape, more keys per column.
  • Streaming — for huge files, replace the in-memory accumulation with a running-mean update; one extra variable per column, same output shape.
  • Source other than disk — accept a URL or stdin instead of argv[1]. The aggregation core doesn't care.
Files (ornn)
  • src
    • main.py 2.6 KB
      """CSV processor example skill.
      
      Reads a CSV file path from `argv[1]`, computes per-column min/mean/max
      for every column where at least one cell parses as a number, writes a
      JSON summary to stdout. On any failure: `{ "error": "..." }` on stderr
      + exit code 1.
      
      Stdlib only; deterministic; offline. The control case for debugging
      agent ↔ skill plumbing.
      """
      
      from __future__ import annotations
      
      import csv
      import json
      import sys
      from typing import Optional
      
      
      def parse_number(raw: str) -> Optional[float]:
          """Best-effort numeric parse — empty / non-numeric returns None."""
          s = raw.strip()
          if not s:
              return None
          try:
              return float(s)
          except ValueError:
              return None
      
      
      def summarise(path: str) -> dict:
          with open(path, newline="", encoding="utf-8") as fh:
              reader = csv.DictReader(fh)
              fieldnames = reader.fieldnames or []
              sums: dict[str, float] = {name: 0.0 for name in fieldnames}
              counts: dict[str, int] = {name: 0 for name in fieldnames}
              mins: dict[str, float] = {}
              maxs: dict[str, float] = {}
              row_count = 0
      
              for row in reader:
                  row_count += 1
                  for name in fieldnames:
                      value = parse_number(row.get(name, ""))
                      if value is None:
                          continue
                      sums[name] += value
                      counts[name] += 1
                      if name not in mins or value < mins[name]:
                          mins[name] = value
                      if name not in maxs or value > maxs[name]:
                          maxs[name] = value
      
              columns: dict[str, dict[str, float | int]] = {}
              for name in fieldnames:
                  if counts[name] == 0:
                      # Skip columns where no cell parsed as a number.
                      continue
                  columns[name] = {
                      "min": mins[name],
                      "mean": sums[name] / counts[name],
                      "max": maxs[name],
                      "count": counts[name],
                  }
      
              return {"rowCount": row_count, "columns": columns}
      
      
      def main(argv: list[str]) -> int:
          if len(argv) < 2:
              sys.stderr.write(json.dumps({"error": "usage: main.py <path>"}) + "\n")
              return 1
          try:
              result = summarise(argv[1])
          except FileNotFoundError as e:
              sys.stderr.write(json.dumps({"error": f"file not found: {e.filename}"}) + "\n")
              return 1
          except OSError as e:
              sys.stderr.write(json.dumps({"error": f"could not read CSV: {e}"}) + "\n")
              return 1
          sys.stdout.write(json.dumps(result) + "\n")
          return 0
      
      
      if __name__ == "__main__":
          sys.exit(main(sys.argv))
      
  • README.md 432 B
    # csv-processor
    
    Parse a CSV file, compute per-column min/mean/max for every numeric column.
    
    **Run:** `python src/main.py sample.csv`
    
    **Adapt:** add more aggregations (median, p95, stddev), or stream large files with running-mean updates. The in/out shape (`path → { rowCount, columns: { ... } }`) is intentionally fixed so the skill stays composable.
    
    Stdlib only — no pandas, no numpy. See `SKILL.md` for the full contract.
    
  • sample.csv 134 B · in bundle
  • SKILL.md 1.8 KB
    ---
    name: csv-processor
    description: Read a CSV file from disk, compute per-column min/mean/max for every numeric column, emit the result as JSON. Stdlib-only Python; no pandas, no numpy. Demonstrates the simplest possible "give me a file path, get back structured analysis" skill — a deliberate baseline for any skill that processes tabular data locally without an LLM in the loop.
    version: "1.0"
    license: MIT
    metadata:
      category: data
      tag:
        - example
        - csv
        - statistics
        - python
    ---
    
    # csv-processor
    
    A deterministic, network-free skill — the easiest case. Useful as a control when debugging the agent ↔ skill plumbing: if this fails, the failure is in the runner, not the skill.
    
    ## Contract
    
    **Input** (single CLI argument):
    
    ```
    python src/main.py /path/to/data.csv
    ```
    
    The script reads `argv[1]` as a filesystem path. CSV must have a header row.
    
    **Output** (stdout, JSON):
    
    ```json
    {
      "rowCount": 1234,
      "columns": {
        "price": { "min": 1.23, "mean": 42.0, "max": 999.99, "count": 1234 },
        "quantity": { "min": 0, "mean": 7.5, "max": 100, "count": 1230 }
      }
    }
    ```
    
    Only numeric columns appear under `columns`. `count` is the number of cells that parsed successfully (numeric); non-numeric / blank cells are skipped.
    
    **Errors** — written to stderr as `{"error": "..."}` and exit code `1`.
    
    ## Run locally
    
    ```bash
    cd examples/csv-processor
    python src/main.py sample.csv
    ```
    
    A `sample.csv` is bundled so the example runs out of the box.
    
    ## Adapt this
    
    - **Different aggregations** — add median, p95, stddev; same shape, more keys per column.
    - **Streaming** — for huge files, replace the in-memory accumulation with a running-mean update; one extra variable per column, same output shape.
    - **Source other than disk** — accept a URL or stdin instead of `argv[1]`. The aggregation core doesn't care.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related