Plain markdown files without frontmatter now parse into a structured object instead of a bare content string. Reuses the existing extract_tasks/extract_inline_tags helpers from record.rs; adds parse_markdown_structure as a new pub fn there to avoid duplication. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .hooks | ||
| .moira | ||
| docs | ||
| jsaw-bin | ||
| jsaw-core | ||
| tests/data | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| cog.toml | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| README.md | ||
| renovate.json | ||
| zensical.toml | ||
jsaw
A universal runtime for structured data.
JSON, TOML, YAML, Markdown frontmatter, CSV — one tool to inspect, query, validate, convert, and browse them all. Unix-friendly by default; a rich TUI when you want to think.
Install
# Nix (recommended)
nix run github:yourusername/jsaw
# From source
cargo install --path jsaw-bin
CLI
Composable, pipeable, scriptable. Every command reads from a file or - for stdin.
jsaw inspect <file|-> # type tree: keys, depths, value types
jsaw validate <path> [--schema <f>] # JSON Schema validation; auto-detects $schema
[--recursive] # walk a whole directory
[--skip-unparseable] # silently skip unreadable files
[--quiet] # only print failures
jsaw query <file|-> <expr> # jq-style filter via jaq
[--raw] # raw string output, no JSON quoting
jsaw convert <file> --to <fmt> # json | toml | yaml
[--out <file>] # write to file instead of stdout
jsaw fmt <file> [--in-place] # pretty-print in original format
jsaw db <dir> [-c col] [-f filter] # directory as queryable table → TUI or CSV
[-s field] [-r] # sort, reverse
[--offset N] [-l N] # pagination
[--json] # output as JSON instead
jsaw render <file|-> <template> # render a Tera template with data as context
Piping examples:
cat secrets.yaml | jsaw query - '.tokens[]'
jsaw db ./posts -c "title" -c "date" -f '.published == true' -s date -r
jsaw validate ./schemas/ --recursive --skip-unparseable --quiet
# Render all open todos across a markdown vault
jsaw db ./vault -c "file.name" -c "md.tasks" -c "md.tasks_open" --json \
| jsaw render - todos.j2
TUI
jsaw inspect <file> and jsaw db <dir> launch a TUI automatically when stdout is a terminal. This is the primary interactive surface of jsaw — the place where you think with your data, not just read it.
Column browser (jsaw inspect)
A ranger/twig-style multi-column file browser for JSON data:
- Side-by-side columns — each nesting level is its own column (not an indented tree).
←/→orh/l— navigate between columns.↑/↓orj/k— move selection.g/G— first/last.- Inspector pane on the right shows key, value, semantic type, path, and pretty preview.
- View modes:
Browse(columns),Table,List,Grouped— switch withTab. /— open jq filter bar to narrow the view.- Semantic coloring — every value is classified and color-coded by inferred type.
Table view (jsaw db)
j/k↑/↓— move row;g/G— first/last;PgUp/PgDn` — page.s/S— cycle sort column / reverse./— open jq filter bar (applied instantly on Enter).Enter— open detail view for selected row.?— help overlay;q/Esc— quit.
Semantic rendering
Every value is classified and colored by jsaw-core::semantic:
| Semantic type | Display |
|---|---|
| URL | cyan + underline |
| cyan | |
| DateTime | yellow |
| Date | yellow |
| Boolean | green ✓ / red ✗ |
| Integer / Float | magenta |
| UUID | blue |
Color (#rrggbb) |
rendered in its own RGB foreground color |
| SemVer | green |
| File path | yellow |
| IP address | blue |
| Base64 | dim, truncated to preview |
| Markdown | first line only + … |
| GeoJSON geometry | green badge with shape name |
| JSON Schema | cyan badge |
| Null | dim — |
The inference engine is value-first (URL scheme, ISO-8601, UUID format, GeoJSON shape check, base64 alphabet, markdown signals) with key-name heuristics as fallback.
Templating (jsaw render)
jsaw render takes any structured data source and a Tera template, then prints the rendered output to stdout. Tera uses Jinja2-style syntax.
The data is available as data in the template context.
jsaw render <file|-> <template.j2>
Example — open todos across a markdown vault:
jsaw db ./vault -c "file.name" -c "md.tasks" -c "md.tasks_open" --json \
| jsaw render - todos.j2
todos.j2:
{% for file in data %}{% if file["md.tasks_open"] and file["md.tasks_open"] > 0 %}
## {{ file["file.name"] }}
{% for t in file["md.tasks"] %}{% if not t.done %} [ ] {{ t.text }}
{% endif %}{% endfor %}{% endif %}{% endfor %}
Output:
## personal
[ ] Call dentist
[ ] Read chapter 4
## project-alpha
[ ] Write design doc
[ ] Review with team
[ ] Set up CI pipeline
Any jsaw command that produces JSON can be piped into jsaw render. Use - as the data argument to read from stdin, or pass a file path directly.
Roadmap
Now — solid foundation
- Semantic type inference (value-first + key-name heuristics)
- Column browser TUI (
jsaw inspect) - Table view, list view, grouped view (
jsaw db) - Clipboard yank (
yto copy selected value) - Comprehensive test coverage for core inference and parsing
- Edge case polish, reliability, perf
Next — power user features
- Column picker — toggle visible columns interactively
- Fuzzy search — cross-column fuzzy match
- Export — write filtered/sorted view as JSON or CSV
- Watch mode —
--watchflag, auto-reload on file change - Clipboard yank for table cells
Later — edit & schema integration
- Inline value editing in tree view
- Schema-constrained editing (enum pickers, required fields)
- Multi-file / cross-file linking
- Schema overlay — field descriptions, required markers, enum hints
Future exploration
- JSON-LD integration — linked data contexts, @id resolution, graph navigation
- HTTP source —
jsaw inspect https://…fetches and renders live - Graph view — force-directed node graph in the terminal
- Diff mode — side-by-side TUI diff for
jsaw diff
Architecture
jsaw/
├── jsaw-core/ # shared logic: data loading, filtering, records, schema
└── jsaw-bin/ # CLI binary (clap); TUI lives here (ratatui + crossterm)
jsaw-core has no UI dependencies. The TUI in jsaw-bin is the primary interactive surface — fast, keyboard-driven, scriptable context around it.
Development
# CLI only
cargo run -p jsaw-bin -- db ./some-dir
# TUI dev loop
cargo run -p jsaw-bin -- db ./testdata
# Run tests
cargo test -p jsaw-core -p jsaw-bin
Philosophy
- Schema-first, not schema-required — schemas unlock contextual rendering, validation, and intelligent editing. jsaw degrades gracefully when none exists.
- The UI is a lens, never the owner — files stay files. TOMLs stay TOMLs. jsaw never holds your data hostage.
- Inference over annotation — a field named
urlwith a URI value doesn't need to be tagged as a link. It already is one. - Unix-friendly — every command pipes in, pipes out. The TUI is opt-in, not mandatory.
- TUI first — the terminal is the right home for a developer data tool. Fast to open, keyboard-driven, scriptable context around it.