# wasot(1)

## Name

wasot - transform Wasot documents

## Synopsis

```
wasot [OPTIONS] [FILE]...
wasot to-sqlite FILE -d DATABASE
wasot from-sqlite -d DATABASE [-o FILE]
wasot tools <check|info|pretty|completions|document-ids>
```

## Description

Wasot is a filter. It reads Wasot documents from stdin or files, transforms them, and writes to stdout or files. Like `jq` or `xmllint`, it composes with pipes. For design rationale, see [CLI design](./cli_design.md). For [shell completions](./shell_completions.md), see the completions guide.

```bash
wasot doc.wasot                    # normalize
wasot doc.wasot -t xml             # to XML
wasot doc.wasot -t jsonl | jq .    # to JSON, pipe to jq
cat doc.wasot | wasot -t xml       # from stdin
```

## Options

```
-f, --from FORMAT     Input format (auto-detected if omitted)
-t, --to FORMAT       Output format (default: wasot)
-o, --output FILE     Output file (default: stdout)
--select SELECTOR     Filter blocks with CSS-like selector
--no-id-index         Skip .wasot-ids index loading
-q, --quiet           Suppress warnings
-v, --verbose         Debug output to stderr
--color WHEN          auto, always, never (default: auto)
-h, --help            Show help
-V, --version         Show version
```

## Formats

```
wasot   .wasot    Wasot markup (default)
xml     .xml      XML representation
jsonl   .jsonl    JSON Lines, one event per line
binary  .wasotb   Protobuf binary
sql     .sql      SQL statements
sqlite  —         SQLite database (requires sqlite feature)
```

Format is auto-detected from extension. For stdin or unknown extensions, content is sniffed: `<` means XML, `{` or `[` means JSONL, binary magic bytes mean binary, everything else is wasot.

When output format is omitted, it's inferred from `-o` extension, or defaults to wasot.

## Commands

### Default (convert)

With no subcommand, wasot converts or normalizes:

```bash
wasot doc.wasot                    # normalize wasot
wasot doc.wasot -t xml             # wasot → XML
wasot doc.wasot -t jsonl           # wasot → JSONL
wasot doc.wasot -t binary -o d.wasotb
wasot -f binary d.wasotb           # binary → wasot
wasot doc.wasot -o doc.xml         # format from extension
```

### to-sqlite / from-sqlite

SQLite roundtrip:

```bash
wasot to-sqlite doc.wasot -d doc.db
wasot from-sqlite -d doc.db -o doc.wasot
wasot from-sqlite -d doc.db        # to stdout
```

### tools check

Validate syntax. Exit 0 if valid, 1 if invalid.

```bash
wasot tools check doc.wasot
wasot tools check *.wasot
find . -name "*.wasot" -exec wasot tools check {} +
wasot tools check doc.wasot && deploy.sh
```

### tools info

Document statistics:

```bash
$ wasot tools info doc.wasot
blocks: 36
  paragraph: 12
  section: 8
  code: 4
depth: 4
lines: 150
bytes: 4001
```

### tools pretty

Reformat files in place. Recursively processes directories, respects `.gitignore`.

```bash
wasot tools pretty                  # current dir
wasot tools pretty docs/            # specific dir
wasot tools pretty -y .             # skip confirmation
wasot tools pretty --stdout doc.wasot   # print, don't modify
```

Options: `--stdout`, `-v/--verbose`, `-y/--yes`

### tools completions

```bash
wasot tools completions bash > ~/.local/share/bash-completion/completions/wasot
wasot tools completions zsh > ~/.zsh/completions/_wasot
wasot tools completions fish > ~/.config/fish/completions/wasot.fish
```

Shells: bash, zsh, fish, elvish, powershell

### tools document-ids

Manage the `.wasot-ids` index file for cross-document references.

**scan** - Print document IDs found in files:
```bash
$ wasot tools document-ids scan docs/
abc123 docs/intro.wasot
def456 docs/chapter1.wasot
```

**update** - Build/rebuild the index:
```bash
wasot tools document-ids update              # scan cwd → .wasot-ids
wasot tools document-ids update docs/        # scan docs/
wasot tools document-ids update -o my.ids    # custom output
```

**get** - Look up ID in index:
```bash
$ wasot tools document-ids get abc123
docs/intro.wasot
$ wasot tools document-ids get missing; echo $?
1
```

## Selectors

Filter output with `--select`:

```bash
wasot --select "code" doc.wasot              # all code blocks
wasot --select "paragraph" doc.wasot -t jsonl
wasot --select "section > heading" doc.wasot
```

Works with all output formats. See [selectors](./selectors.md) for syntax.

## Exit Codes

```
0   Success
1   Invalid input (parse error, validation failure)
2   I/O error (file not found, permission denied)
3   Invalid arguments (bad format, bad selector)
```

## Stdin, Stdout, Pipes

Reads stdin when no file given. Writes stdout unless `-o` specified. Errors go to stderr.

```bash
cat doc.wasot | wasot -t xml
echo ".p .. hello" | wasot
wasot doc.wasot | head -10          # SIGPIPE handled correctly
```

## Examples

### Pipelines

```bash
# Process events with jq
wasot doc.wasot -t jsonl | jq 'select(.type == "BlockStarted")'

# Count blocks by type
wasot doc.wasot -t jsonl | jq -rs 'group_by(.meta_line.type_name) | .[] | "\(.[0].meta_line.type_name): \(length)"'

# Validate XML output
wasot doc.wasot -t xml | xmllint --format -

# XSLT transform
wasot doc.wasot -t xml | xsltproc template.xsl - > out.html
```

### Batch Processing

```bash
# Convert all to XML
for f in *.wasot; do wasot "$f" -o "${f%.wasot}.xml"; done

# Parallel with GNU parallel
find . -name "*.wasot" | parallel wasot {} -o {.}.xml

# Validate project
find . -name "*.wasot" -print0 | xargs -0 wasot tools check
```

### Roundtrip

```bash
# Through binary
wasot doc.wasot -t binary | wasot > roundtrip.wasot

# Through JSONL
wasot doc.wasot -t jsonl | wasot -f jsonl > roundtrip.wasot

# Verify identity
diff <(wasot doc.wasot) <(wasot doc.wasot -t binary | wasot)
```

### SQLite Workflow

```bash
wasot to-sqlite doc.wasot -d doc.db
sqlite3 doc.db "SELECT type_name, COUNT(*) FROM blocks GROUP BY type_name"
sqlite3 doc.db "SELECT text FROM blocks WHERE type_name='code'"
wasot from-sqlite -d doc.db > reconstructed.wasot
```

### CI Integration

```bash
# Pre-commit hook
#!/bin/sh
wasot tools check $(git diff --cached --name-only '*.wasot') || exit 1

# GitHub Actions
- run: find . -name "*.wasot" | xargs wasot tools check
```

## Files

`.wasot-ids` — Document ID index, maps IDs to file paths. Created by `wasot tools document-ids update`.

## Notes

If a file has the same name as a subcommand (unlikely but possible):
```bash
wasot ./tools              # relative path
wasot -- tools             # stop arg parsing
```

Memory usage is bounded regardless of input size. Streaming [architecture](./architecture.md) processes line by line (see [memory analysis](./memory_analysis.md)).

## See Also

[CLI design](./cli_design.md) — Design rationale
[Selectors](./selectors.md) — Selector syntax
[Architecture](./architecture.md) — Streaming architecture
