Skill: claudiodrusus/skill-3 (version 1.0.0)

--- name: json-toolkit description: Swiss-army knife for JSON files. Pretty-print, validate, minify, sort keys, and query with dot-notation paths. Zero dependencies. triggers: - format json - pretty print json - validate json - query json - minify json - json tool --- # JSON Toolkit A zero-dependency Python utility for working with JSON data. Validates, formats, minifies, queries, and inspects JSON files — all with Python's standard library. ## Features - **Pretty-print** with configurable indentation (2, 4, or any number of spaces) - **Minify** JSON to reduce file size for APIs and storage - **Validate** JSON and get structural stats (type, key count, size) - **Query** nested data with dot-notation paths including array indices - **Sort keys** alphabetically for deterministic output and easier diffs - **Stdin support** for use in shell pipelines with other tools ## Usage Examples Pretty-print a JSON file: ```bash python main.py data.json ``` Validate without output: ```bash python main.py config.json --validate # ✓ Valid JSON # Type: object (12 keys) # Size: 4832 bytes ``` Query a nested value: ```bash python main.py users.json --query data.users.0.name # "Alice" ``` Minify for production: ```bash python main.py config.json --minify -o config.min.json ``` Sort keys for consistent diffs: ```bash python main.py package.json --sort-keys -o package-sorted.json ``` Pipe from curl: ```bash curl -s https://api.example.com/data | python main.py - --query results.0 ``` ## Query Syntax Use dot notation to navigate nested structures. Array indices are numbers: - `name` — top-level key - `data.users` — nested object key - `data.users.0` — first element of an array - `data.users.0.email` — field of the first array element - `config.servers.2.host` — deeply nested value ## Command Line Options - `input` — JSON file path, or `-` for stdin - `-o, --output` — Output file (defaults to stdout) - `--indent N` — Indentation spaces (default: 2) - `--minify` — Output minified JSON (no whitespace) - `--query PATH` / `-q PATH` — Extract a value at the given dot-notation path - `--validate` — Only validate and print stats, no output - `--sort-keys` — Sort object keys alphabetically - `--json` — (implicit) Output is always valid JSON

path: main.py
content: #!/usr/bin/env python3
"""json-formatter: Validate, pretty-print, minify, and query JSON."""

import sys
import json
import argparse


def query_json(data, path):
    """Simple dot-notation query with array index support: a.b.0.c"""
    keys = path.split('.')
    current = data
    for key in keys:
        if isinstance(current, list):
            try:
                current = current[int(key)]
            except (ValueError, IndexError):
                raise KeyError(f"Invalid array index: {key}")
        elif isinstance(current, dict):
            if key not in current:
                raise KeyError(f"Key not found: {key}")
            current = current[key]
        else:
            raise KeyError(f"Cannot traverse into {type(current).__name__} with key: {key}")
    return current


def main():
    parser = argparse.ArgumentParser(description='JSON formatter and query tool')
    parser.add_argument('input', help='Input JSON file (use - for stdin)')
    parser.add_argument('-o', '--output', help='Output file (default: stdout)')
    parser.add_argument('--indent', type=int, default=2, help='Indentation (default: 2)')
    parser.add_argument('--minify', action='store_true', help='Minify output')
    parser.add_argument('--query', '-q', help='Query path (dot notation, e.g. data.users.0.name)')
    parser.add_argument('--validate', action='store_true', help='Only validate, no output')
    parser.add_argument('--sort-keys', action='store_true', help='Sort object keys')
    args = parser.parse_args()

    # Read input
    try:
        if args.input == '-':
            raw = sys.stdin.read()
        else:
            with open(args.input, 'r') as f:
                raw = f.read()
    except FileNotFoundError:
        print(f"Error: File not found: {args.input}", file=sys.stderr)
        sys.exit(1)

    # Parse
    try:
        data = json.loads(raw)
    except json.JSONDecodeError as e:
        print(f"Invalid JSON: {e}", file=sys.stderr)
        sys.exit(1)

    if args.validate:
        print("✓ Valid JSON")
        # Print stats
        if isinstance(data, dict):
            print(f"  Type: object ({len(data)} keys)")
        elif isinstance(data, list):
            print(f"  Type: array ({len(data)} items)")
        else:
            print(f"  Type: {type(data).__name__}")
        print(f"  Size: {len(raw)} bytes")
        sys.exit(0)

    # Query
    if args.query:
        try:
            data = query_json(data, args.query)
        except KeyError as e:
            print(f"Query error: {e}", file=sys.stderr)
            sys.exit(1)

    # Format
    if args.minify:
        result = json.dumps(data, separators=(',', ':'), sort_keys=args.sort_keys, ensure_ascii=False)
    else:
        result = json.dumps(data, indent=args.indent, sort_keys=args.sort_keys, ensure_ascii=False)

    # Output
    if args.output:
        with open(args.output, 'w') as f:
            f.write(result + '\n')
        print(f"Written to {args.output}", file=sys.stderr)
    else:
        print(result)


if __name__ == '__main__':
    main()


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