Skill: aronchick/expanso-csv-to-json (version 1.0.0)

# csv-to-json "Convert CSV data to JSON array of objects" ## Requirements - Expanso Edge installed (`expanso-edge` binary in PATH) - Install via: `clawhub install expanso-edge` ## Usage ### CLI Pipeline ```bash # Run standalone echo '<input>' | expanso-edge run pipeline-cli.yaml ``` ### MCP Pipeline ```bash # Start as MCP server expanso-edge run pipeline-mcp.yaml ``` ### Deploy to Expanso Cloud ```bash expanso-cli job deploy https://skills.expanso.io/csv-to-json/pipeline-cli.yaml ``` ## Files | File | Purpose | |------|---------| | `skill.yaml` | Skill metadata (inputs, outputs, credentials) | | `pipeline-cli.yaml` | Standalone CLI pipeline | | `pipeline-mcp.yaml` | MCP server pipeline |

path: README.md
content: # csv-to-json

Convert CSV data to JSON array of objects.

## Overview

This skill parses CSV with headers and converts to JSON objects. Runs entirely locally.

## Usage

### CLI Mode

```bash
echo "name,age,city
Alice,30,NYC
Bob,25,LA" | expanso-edge run pipeline-cli.yaml

# Custom delimiter
DELIMITER=";" cat data.csv | expanso-edge run pipeline-cli.yaml
```

### MCP Mode

```bash
PORT=8080 expanso-edge run pipeline-mcp.yaml &
curl -X POST http://localhost:8080/convert \
  -H "Content-Type: application/json" \
  -d '{"csv": "name,age\nAlice,30\nBob,25"}'
```

## Output

```json
{
  "data": [
    {"name": "Alice", "age": "30", "city": "NYC"},
    {"name": "Bob", "age": "25", "city": "LA"}
  ],
  "row_count": 2,
  "columns": ["name", "age", "city"],
  "metadata": {...}
}
```

## Use Cases

- Data import/export
- API data transformation
- Spreadsheet processing
- Log parsing


path: pipeline-cli.yaml
content: # Expanso Pipeline: csv-to-json (CLI mode)
# =========================================
#
# Usage:
#   echo "name,age\nAlice,30\nBob,25" | expanso-edge run pipeline-cli.yaml
#   cat data.csv | expanso-edge run pipeline-cli.yaml
#
# No API key needed - runs entirely locally.

name: "csv-to-json-cli"
type: pipeline

config:
  input:
    stdin:
      codec: all
      max_buffer: 10485760

  pipeline:
    processors:
      - mapping: |
          meta trace_id = uuid_v4()
          let csv_text = content().trim()
          let delimiter = env("DELIMITER").or(",")

          # Split into lines
          let lines = $csv_text.split("\n").filter(line -> line.trim().length() > 0)

          # First line is headers
          let headers = if $lines.length() > 0 {
            $lines.index(0).split($delimiter).map_each(h -> h.trim())
          } else { [] }

          # Convert remaining lines to objects
          let data = $lines.slice(1).map_each(line -> $headers.fold({"index": 0, "obj": {}}, pair -> {
            "index": pair.tally.index + 1,
            "obj": pair.tally.obj.merge({(pair.value): line.split($delimiter).index(pair.tally.index).or("").trim()})
          }).obj)

          root.data = $data
          root.row_count = $data.length()
          root.columns = $headers
          root.metadata = {
            "skill": "csv-to-json",
            "mode": "cli",
            "delimiter": $delimiter,
            "trace_id": meta("trace_id"),
            "timestamp": now()
          }

      - log:
          level: INFO
          message: |
            [csv-to-json] Converted ${! root.row_count } rows (trace: ${! meta("trace_id").slice(0, 8) })

  output:
    stdout:
      codec: json_object


path: pipeline-mcp.yaml
content: # Expanso Pipeline: csv-to-json (MCP mode)
# =========================================
#
# Usage:
#   PORT=8080 expanso-edge run pipeline-mcp.yaml &
#   curl -X POST http://localhost:8080/convert -d '{"csv": "name,age\nAlice,30"}'

name: "csv-to-json-mcp"
type: pipeline

config:
  http:
    enabled: true
    address: "0.0.0.0:${PORT:-8080}"

  input:
    http_server:
      path: /convert
      allowed_verbs: [POST]
      timeout: 60s

  pipeline:
    processors:
      - mapping: |
          meta trace_id = uuid_v4()
          let csv_text = this.csv.or(content()).string().trim()
          let delimiter = this.delimiter.or(",")

          let lines = $csv_text.split("\n").filter(line -> line.trim().length() > 0)
          let headers = if $lines.length() > 0 {
            $lines.index(0).split($delimiter).map_each(h -> h.trim())
          } else { [] }

          let data = $lines.slice(1).map_each(line -> $headers.fold({"index": 0, "obj": {}}, pair -> {
            "index": pair.tally.index + 1,
            "obj": pair.tally.obj.merge({(pair.value): line.split($delimiter).index(pair.tally.index).or("").trim()})
          }).obj)

          root.data = $data
          root.row_count = $data.length()
          root.columns = $headers
          root.metadata = {
            "skill": "csv-to-json",
            "mode": "mcp",
            "delimiter": $delimiter,
            "trace_id": meta("trace_id"),
            "timestamp": now()
          }

      - log:
          level: INFO
          message: |
            [csv-to-json] Converted ${! root.row_count } rows (trace: ${! meta("trace_id").slice(0, 8) })

  output:
    sync_response: {}


path: skill.yaml
content: # Skill: csv-to-json
# Version: 1.0.0
#
# Convert CSV data to JSON.
# Runs locally without API calls.

name: "csv-to-json"
version: "1.0.0"
description: "Convert CSV data to JSON array of objects"

author:
  name: "Expanso Team"
  url: "https://expanso.io"
  avatar: "EX"

credentials: []

inputs:
  - name: csv
    type: string
    required: true
    description: CSV data with header row
  - name: delimiter
    type: string
    default: ","
    description: Field delimiter

outputs:
  - name: data
    type: array
    description: Array of JSON objects
  - name: row_count
    type: integer
    description: Number of data rows
  - name: columns
    type: array
    description: Column names from header

backends:
  - name: local
    type: local
    requires: []
    description: Pure local conversion

components:
  inputs:
    - stdin
    - http_server
  processors:
    - mapping
  outputs:
    - stdout
    - sync_response


path: test/fixtures/input.txt
content: name,email,department
Alice Smith,[REDACTED_SECRET],Engineering
Bob Jones,[REDACTED_SECRET],Marketing
Carol White,[REDACTED_SECRET],Sales


path: test/test.yaml
content: # Test cases for csv-to-json skill

tests:
  - name: "Convert simple CSV"
    input: "name,age\nAlice,30\nBob,25"
    expected:
      has_field: data
      has_field: row_count
      has_field: columns
      metadata_has: [skill, trace_id, timestamp]


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)