π₯οΈ CLI Reference
Usage
fimod s -i <INPUT> -m <MOLD> [OPTIONS]
fimod s -i <INPUT> -e '<EXPRESSION>' [OPTIONS]
fimod s --no-input -m <MOLD> [OPTIONS]
Note
Either -m or -e is required (but not both).
π― Core options
| Option | Short | Description | Default |
|---|---|---|---|
--input |
-i |
Input file path or URL (https://...) |
stdin |
--mold |
-m |
Path, URL, or registered name of the transform script | β |
--expression |
-e |
Inline Python expression (mutually exclusive with -m) |
β |
--output |
-o |
Output file path | stdout |
--in-place |
Modify input file in-place (requires -i, incompatible with -o and URLs) |
β | |
--slurp |
-s |
Read multiple JSON values into a single array | β |
--no-input |
Skip input β data = None in Python |
β | |
--check |
No stdout; exit 0 if result is truthy, 1 if falsy | β | |
--debug |
-d |
Print pipeline diagnostics to stderr | β |
π Format control
| Option | Description |
|---|---|
--input-format |
Explicitly set input format. Auto-detected from extension if omitted. |
--output-format |
Explicitly set output format. Defaults to input format if omitted. |
Supported values: json Β· json-compact Β· ndjson Β· yaml Β· toml Β· csv Β· txt Β· lines Β· raw (output-only) Β· http (input-only)
π Auto-detection
| Extension | Format |
|---|---|
.json |
JSON |
.ndjson, .jsonl |
NDJSON |
.yaml, .yml |
YAML |
.toml |
TOML |
.csv, .tsv |
CSV |
.txt, .text |
TXT |
| (none / stdin) | JSON (default) |
Lines is never auto-detected
Always use --input-format lines explicitly.
π₯ Your input can be an HTTPS request!
Awesome: the input can be an HTTPS request. The -i flag accepts URLs exactly like file paths β fimod fetches, parses, and transforms in a single command. No curl, no wget, no pipes.
# Fetch JSON from an API
fimod s -i https://api.github.com/repos/pytgaen/fimod -e 'data["name"]' --output-format txt
# Multiple URLs in batch mode
fimod s -i https://jsonplaceholder.typicode.com/users/1 https://jsonplaceholder.typicode.com/users/2 -e 'data' -o responses/
Format auto-detection: the response's Content-Type header is used as fallback when --input-format is not set (application/json β JSON, text/csv β CSV, etc.). You can always override explicitly.
--in-place is not allowed with URLs
HTTP options
| Option | Description | Default |
|---|---|---|
--header "Name: Value" |
Custom HTTP header (repeatable) | β |
--timeout <seconds> |
Request timeout | 30 |
--no-follow |
Don't follow HTTP redirects | follows redirects |
--no-cache |
Bypass local cache for remote catalogs and molds | uses cache |
# Authenticated API
fimod s -i https://api.github.com/user \
--http-header "Authorization: Bearer $GITHUB_TOKEN" \
-e 'data["login"]' --output-format txt
# Disable redirects to inspect the Location header
fimod s -i https://github.com/pytgaen/fimod/releases/latest \
--input-format http --no-follow \
-e 'data["headers"]["location"]' --output-format txt
--input-format http β raw HTTP response
When you need the full HTTP response (status code, headers, body), use --input-format http. Instead of parsing the body, fimod gives you a dict:
data = {
"status": 200,
"headers": {"content-type": "application/json", "location": "..."},
"body": "...", # raw response body as a string
"body_size": 1234, # response size in bytes
"content_type": "application/json",
"url": "https://example.com/api/data"
}
# Get the redirect target of a URL
fimod s -i https://github.com/pytgaen/fimod/releases/latest \
--input-format http --no-follow \
-e 'data["headers"]["location"].split("/")[-1]' --output-format txt
# β v0.3.0
# Combine with set_input_format() to re-parse the body
fimod s -i https://api.github.com/repos/pytgaen/fimod/releases/latest \
--input-format http \
-e 'set_input_format("json"); data["body"]' \
-e 'data["tag_name"]' --output-format txt
http is input-only
Using --output-format http will produce an error. HTTP is only meaningful as an input format.
Requires the default build variant
HTTP input needs reqwest, which is included in the default build. Use FIMOD_VARIANT=slim (or cargo build --no-default-features) if you want to opt out.
π₯ Slurp mode (--slurp / -s)
-s has two distinct uses depending on whether you pass a single input or multiple -i entries.
Single input β NDJSON / concatenated JSON
Reads multiple concatenated JSON values from a single source and collects them into an array.
# π Two separate JSON objects β array of two
printf '{"a":1}\n{"b":2}' | fimod s --slurp -e 'len(data)'
# β 2
# π Combine multiple JSON files via cat (JSON only)
cat file1.json file2.json | fimod s --slurp -e '[item for item in data if item.get("active")]'
For non-JSON formats, --slurp wraps the single parsed value in a one-element array.
Multiple inputs β multi-file slurp
When combined with two or more -i flags, -s switches to multi-file slurp mode: all files are parsed (each in their own format) and combined into a single data structure. The mold runs once against the combined result.
Two sub-modes controlled by the -i syntax:
| Syntax | Mode | data shape |
|---|---|---|
-i f1 -i f2 |
list | [parsed_f1, parsed_f2] |
-i f1: -i f2: |
named (auto stem) | {"f1": parsed_f1, "f2": parsed_f2} |
-i f1:alias -i f2:other |
named (explicit) | {"alias": parsed_f1, "other": parsed_f2} |
Rules:
- All entries must use : or none must (mixing β error)
- Auto stem uses the filename without extension; duplicate stems β error (use explicit aliases)
- Incompatible with --in-place and -o <directory>
- URLs cannot carry a :alias suffix (the :// scheme separator collides with the alias delimiter, so URLs are always treated as bare entries). When mixing HTTP inputs with local files, list mode is the only option β access via data[0], data[1], β¦ in input order.
# β List mode β access by index, cross-format (JSON + YAML)
fimod s -i base.json -i override.yaml -s -e 'data[1]["env"]'
# π·οΈ Named mode β auto stem as key
fimod s -i defaults.json: -i prod.toml: -s \
-e 'data["defaults"]["timeout"]'
# π·οΈ Named mode β explicit aliases (resolves stem collisions)
fimod s -i config/base.json:base -i other/base.json:fallback -s \
-e 'data["fallback"]["host"]'
# π Diff two files (with df_ helpers, once implemented)
fimod s -i before.json:old -i after.json:new -s \
-e 'df_diff(data["old"], data["new"])'
# πΎ Write result to a file
fimod s -i a.yaml -i b.yaml -s -e 'data[0]' -o merged.yaml
π« No-input mode (--no-input)
Skip input entirely β data is None in Python. Use to generate data from scratch.
Incompatible with
-i, --input-format, --in-place
fimod s --no-input -e '{"status": "ok", "ts": args["ts"]}' --arg ts="2024-01-01"
fimod s --no-input -m generate.py --arg count=5
# generate.py
def transform(data, args, env, headers):
n = int(args["count"])
return [{"id": i, "value": i * i} for i in range(n)]
β
Check mode (--check)
Suppresses stdout and uses the truthiness of the result as the exit code.
- Exit 0 β result is truthy
- Exit 1 β result is falsy
See Exit Codes for the full truthiness table.
# β
Validate a record
fimod s -i record.json -e 'data.get("email") and data.get("name")' --check
# π Use in a shell conditional
if fimod s -i config.json -m validate.py --check; then
echo "β
Config is valid"
else
echo "β Config has errors" >&2
exit 1
fi
Tip
When a mold calls set_exit(code), that code takes priority over --check truthiness.
βοΈ Setup
fimod setup <category> defaults installs the canonical configuration for a category. It's what the install scripts call after downloading the binary, but you can re-run it at any time.
fimod setup all defaults --yes # π registry + sandbox in one go
fimod setup registry defaults --yes # community registries only
fimod setup sandbox defaults --yes # sandbox policy only
| Flag | Description |
|---|---|
--yes |
Non-interactive (required on CI / non-TTY). |
--force |
Overwrite an existing sandbox.toml (ignored for registry). |
What each target does:
registryβ installs the community registries in~/.config/fimod/sources.toml. Idempotent; safe to re-run. Same effect as the legacyfimod registry setup.sandboxβ writes the recommended sandbox policy to~/.config/fimod/sandbox.toml. Refuses to overwrite without--force.allβ runsregistrythensandbox, stopping at the first error.
See Sandbox policy for what the sandbox file controls and how it is resolved.
ποΈ Mold registries
Registries are named collections of molds (local directories or remote repos).
Use @name or @registry/name with -m to reference a mold by name.
fimod registry add my ~/molds/ # β Add local registry
fimod registry add corp https://github.com/org/molds # β Add GitHub registry
fimod registry list # π List registries
fimod registry show my # π Show details
fimod registry remove my # ποΈ Remove
fimod registry set-priority corp 0 # β Set P0 (highest priority)
fimod registry set-priority mycompany 1 # π Set priority P1
fimod registry set-priority mycompany --clear # π Clear priority
fimod registry build-catalog ./molds # π¦ Generate catalog.toml from a directory
fimod registry build-catalog --registry my # π¦ Generate catalog.toml for a registered registry
fimod registry cache info # π Show cache location and usage
fimod registry cache clear # π§Ή Clear all cached catalogs and molds
Config stored in ~/.config/fimod/sources.toml. Cache stored in ~/.cache/fimod/.
registry setup β first-run onboarding
Deprecated in 0.5.0 β removed in 0.10.0
Use fimod setup registry defaults instead. The legacy form still works but prints a deprecation warning on stderr.
fimod registry setup adds the fimod example molds registry (P99) if not already present. It remains operational for backward compatibility but delegates to the new setup path internally.
fimod registry setup # interactive β asks before adding
fimod registry setup --yes # non-interactive / CI β skips the prompt
Behaviour:
- Already configured (same URL found) β no-op, prints "already configured".
- Legacy "official" registry detected β prompts to migrate it to "examples" (P99).
- Fresh install β adds "examples" at P99 (not default β your own registries take precedence).
- Non-interactive (no TTY) β skips silently unless
--yesis passed.
Priority-based resolution
When you use @mold (without a registry prefix), fimod searches all configured registries in priority order until the mold is found:
| Priority | Source |
|---|---|
| P0 | FIMOD_REGISTRY anonymous entries (env always wins) |
| P0, P1, P2, β¦ | Registries with a [priority] rank |
| β | Remaining registries (file order, after all prioritized ones) |
$ fimod registry list
corp [github] github.com/org/fimod-powered P0
mycompany [http] registry.corp.com/fimod P1
internal [local] /home/user/molds P2
examples [github] github.com/pytgaen/fimod P99
With @registry/mold (explicit prefix), only that specific registry is searched.
set-priority β assign a priority rank
fimod registry set-priority mycompany 1 # Set mycompany to P1
fimod registry set-priority internal 2 # Set internal to P2
fimod registry set-priority mycompany --clear # Remove priority
When the requested rank is already taken, the behaviour depends on context:
-
Swap (default) β if both registries already have a rank, they exchange positions:
-
Cascade β if the source had no prior rank (or
--cascadeis passed), existing entries shift down:
Use --cascade to force cascade behaviour even when both registries already have a rank.
sources.toml format
[priority]
corp = 0
mycompany = 1
internal = 2
examples = 99
[sources.corp]
type = "github"
url = "https://github.com/org/fimod-powered"
[sources.mycompany]
type = "http"
url = "https://registry.corp.com/fimod"
[sources.internal]
type = "local"
path = "/home/user/molds"
[sources.examples]
type = "github"
url = "https://github.com/pytgaen/fimod/tree/main/molds"
The [priority] section is optional. Without it, registries are searched in file order.
FIMOD_REGISTRY β ephemeral registries for CI
In CI/CD or ephemeral environments, use the FIMOD_REGISTRY environment variable instead of fimod registry add. Comma-separated entries, optionally named:
# Anonymous β resolves @mold
FIMOD_REGISTRY=./molds fimod s -i data.json -m @clean
# Named β resolves @ci/mold and @mold
FIMOD_REGISTRY="ci=./molds,staging=https://github.com/org/molds" fimod s -i data.json -m @ci/clean
# Mixed anonymous + named
FIMOD_REGISTRY="ci=./molds,/opt/shared-molds" fimod s -i data.json -m @clean
FIMOD_REGISTRY takes priority over sources.toml (env overrides config, standard Unix convention). Named entries support @name/mold resolution.
# Register a local collection onceβ¦
fimod registry add my ~/molds/
# β¦then reference molds by name
fimod s -i messy.csv -m @cleanup # searches all registries in priority order
fimod s -i messy.csv -m @my/cleanup # explicit registry
Authentication β tokens are resolved automatically, or overridden per-registry:
| Source type | Default token |
|---|---|
github.com |
$GITHUB_TOKEN |
| GitLab | $GITLAB_TOKEN |
| Other HTTP (Gitea, Forgejo, β¦) | $FIMOD_DL_AUTH_TOKEN |
| Custom | --token-env MY_VAR at registry add time |
GitHub URL formats
fimod accepts different URL forms depending on the Git ref type you want to pin to:
| Ref type | URL to pass to registry add |
|---|---|
Branch (main, dev, β¦) |
https://github.com/org/repo/tree/main/molds |
Semver tag (v1.0.0, 2.3.4, β¦) |
https://github.com/org/repo/tree/v1.0.0/molds |
Other tag (stable, latest, β¦) |
https://raw.githubusercontent.com/org/repo/refs/tags/stable/molds |
| Commit SHA | https://github.com/org/repo/tree/abc1234.../molds |
For branches and semver tags, pass the standard github.com/tree/β¦ URL β fimod converts it to a raw URL automatically, using refs/heads/ for branches and refs/tags/ for semver-looking refs.
For non-semver tags (e.g. stable, latest), fimod cannot distinguish them from branch names based on the ref string alone. Pass the raw.githubusercontent.com URL with the full ref path instead:
# Branch β standard github.com URL
fimod registry add mylib https://github.com/org/repo/tree/main/molds
# Semver tag β standard github.com URL
fimod registry add mylib https://github.com/org/repo/tree/v1.2.0/molds
# Non-semver tag β raw URL required
fimod registry add mylib https://raw.githubusercontent.com/org/repo/refs/tags/stable/molds
Browsing available molds
fimod mold list # list molds in all registries
fimod mold list examples # list molds in a specific registry
fimod mold show pick_fields # show metadata for a mold
Both mold list and mold show accept --output-format json for machine-readable output.
For local registries, mold names and descriptions are discovered by scanning .py files.
For remote registries (GitHub, GitLab, HTTP), a catalog.toml must be present at the root of the registry.
Maintainers generate it with:
fimod registry build-catalog ./molds # scans directory and writes catalog.toml
fimod registry build-catalog --registry my # same, resolving path from a registered registry
The catalog.toml is a simple TOML file committed alongside the molds:
[molds.normalize]
description = "Normalise field names to snake_case"
[molds.filter_active]
description = "Keep only active records"
Mold descriptions come from the module-level docstring at the top of each script:
Cache management
Remote catalogs and molds are cached locally in ~/.cache/fimod/ to avoid re-fetching on every invocation.
Catalog caching uses HTTP ETags: on subsequent requests, fimod sends If-None-Match and skips the download on 304 Not Modified.
Mold caching uses content hashes from the catalog: build-catalog computes a hash per mold directory, and the client only re-downloads when the hash changes.
fimod registry cache info # show cache location and disk usage
fimod registry cache clear # wipe all cached data
fimod registry cache clear @name # wipe a specific mold (planned)
fimod s -i data.json -m @mold --no-cache # bypass cache for this invocation
Override the cache directory with FIMOD_CACHE_DIR. For direct-URL molds (not registry-based), cache TTL is controlled by FIMOD_CACHE_TTL (minutes, default 360, 0 = infinite, negative = disabled).
π‘οΈ Sandbox policy
Every fimod s invocation runs the mold under a sandbox that limits what it can do on the host. A policy controls three things:
- Clock access β whether
datetime.now()/date.today()resolve to real values or raise. - Environment access β which
os.getenv(KEY)calls are allowed (glob-matched). - Hard resource limits β wall-clock duration and peak memory.
Resolution
The policy is resolved in this order (first match wins):
--sandbox-file <path>β CLI flag.$FIMOD_SANDBOX_FILEβ environment variable.~/.config/fimod/sandbox.tomlβ per-user canonical config.- (none of the above) β zero-authorization defaults.
Special cases:
--sandbox-file=""(empty string) forces zero-authorization regardless of$FIMOD_SANDBOX_FILEor the canonical file. Portable across Linux/macOS/Windows.- If
$FIMOD_SANDBOX_FILEpoints to a missing path, fimod errors out explicitly rather than falling back silently.
Bootstrap the canonical file with fimod setup sandbox defaults --yes.
Hard limits
Apply even with zero authorization:
| Limit | Default |
|---|---|
max_duration |
2m |
max_memory |
1GB |
On violation, fimod exits with code 137 and a stderr message like:
sandbox.toml schema
[sandbox]
allow_clock = true # allow datetime.now() / date.today()
max_duration = "2m" # "30s", "2m", "unlimited"
max_memory = "1GB" # "500MB", "1GB", "unlimited"
allow_env = ["LANG", "TZ_*"] # glob patterns: "*", "PREFIX_*", "EXACT"
allow_env = [] (default) blocks every os.getenv() call. Patterns match the key name exactly, as a prefix (TZ_*), or anything (*).
Denied calls raise PermissionError inside the mold β catch it if you want a graceful fallback:
import os
lang = None
try:
lang = os.getenv("LANG")
except PermissionError:
pass # sandbox forbids env access
π CSV options
| Option | Description |
|---|---|
--csv-delimiter <char> |
Separator character for input (default: ,). Use \t for tabs. |
--csv-output-delimiter <char> |
Separator for output (defaults to --csv-delimiter). |
--csv-no-input-header |
First line is data, not header. Columns: col0, col1, ... |
--csv-no-output-header |
Don't write header row in output. |
--csv-header "a,b,c" |
Explicit column names (implies no header in file). |
Column order is preserved
No alphabetical sorting through transforms.
When the input CSV has a header row, a headers global is automatically available in your script β see Mold Scripting β CSV headers.
β‘ Inline expressions vs scripts
Best for one-liners:
fimod s -i users.json -e '[u for u in data if u["active"]]'
fimod s -i data.json -e '{"name": data["first"].upper()}'
fimod s -i data.json -e 're_findall(r"\d+", data["text"])'
Multi-statement? Write def transform inside -e.
ποΈ Special output formats
Sometimes you need to control the output format for chaining with other tools, without changing the file extension:
# π¦ Compact JSON: one-line JSON for piping
fimod s -i data.json -e 'data' --output-format json-compact
# {"name":"Alice","age":30}
# π TXT: evaluate string without JSON quotes (ideal for shell variables)
NAME=$(fimod s -i data.json -e 'data["name"]' --output-format txt)
echo "Hello $NAME" # Hello Alice
# π Lines: one array element per line (shell-friendly lists)
fimod s -i users.json -e '[u["email"] for u in data]' --output-format lines
# π₯ Raw: download binary streams or raw bytes (no parsing, bypass pipeline)
fimod shape -i https://example.com/file.bin --output-format raw -o file.bin
π Passing variables (--arg)
fimod s -i users.json --arg threshold=30 -e '
[u for u in data if u["age"] > int(args["threshold"])]
'
# Or via mold:
fimod s -i data.json -m filter.py --arg threshold=30 --arg prefix="A"
Access via args["key"] in the transform(data, args, env, headers) function.
π Format conversion
Pass-through expression for pure format conversion:
fimod s -i config.yaml -e 'data' -o config.toml
fimod s -i data.csv -e 'data' --output-format json
fimod s -i users.json -e 'data' --output-format lines
π Debug mode (--debug / -d)
Prints pipeline diagnostics to stderr (stdout stays clean for piping):
Output includes: input/output format, per-step identification (step N/M (label)), full script, input data, output data, phase timings (parse, execute, serialize, total).
Each step in a chain is logged with its 1-based index, the chain length, and a short label (the raw -m reference, or -e '<expr>' for inline expressions, truncated to ~50 chars). Steps injected at runtime via pipeline.insert_next / pipeline.append are annotated with injected by step P:
[debug] step 1/3 (./normalize.py)
[debug] step 2/3 (@common/flatten)
[debug] step 3/3 (-e 'data', injected by step 2)
The same identifier is prepended to runtime errors, so the failing step is always unambiguous:
Timings are always emitted in seconds with millisecond precision (0.045s) for easy parsing:
# extract execute time of a run
fimod s -i big.json -m heavy.py --debug 2>&1 1>/dev/null \
| awk '/\[debug\] execute:/ {print $3}'
Tip
In debug mode, Python print() statements are also redirected to stderr.
π’ Message verbosity (--quiet / --msg-level)
Control which msg_* functions in mold scripts produce output:
fimod s -i data.json -m transform.py --quiet # errors only
fimod s -i data.json -m transform.py --msg-level=verbose # + msg_verbose()
fimod s -i data.json -m transform.py --msg-level=trace # + msg_trace()
--quiet and --msg-level are mutually exclusive. See built-ins reference for the full visibility table.
βοΈ In-place editing (--in-place)
Modify the input file directly:
Requires -i. Incompatible with -o.
π Watch mode (--watch / -w)
Re-runs the transform whenever the input file or a local mold script changes β handy for iterating on a mold while editing it in another window:
Output goes to the usual destination (-o file or stdout). Status messages stream on stderr, so piping still works:
fimod s -i data.json -m cleanup.py --watch | jq .name
# stderr: [watch] watching data.json, cleanup.py
# stderr: [watch] run #1 ok (42ms)
# stderr: [watch] run #2 ok (38ms) (after editing cleanup.py)
# stdout: "alice"
# stdout: "alice"
A run that fails (Python error, parse error, missing file) is reported but does not exit the watch loop β fix the script and the next save triggers another run:
[watch] run #3 failed (12ms)
in step 1/1 (cleanup.py): Python error in mold:
NameError: name 'foo' is not defined
What is watched:
-i <file>(the input file, must be local β not stdin or HTTP).- Each
-m <file.py>that points to a local file (registry molds@reg/nameand inline-eexpressions are not watched).
Refused combinations (each emits an explicit error):
| Combo | Reason |
|---|---|
--watch + -i - (stdin) |
nothing to watch |
--watch + -i http(s)://β¦ |
HTTP inputs not supported |
--watch + multiple -i (batch) |
watch is single-input only |
--watch + --input-list |
input list mode unsupported |
--watch + --no-input |
no input means no file to watch |
--watch + --in-place |
feedback loop (we'd watch the file we write) |
--watch + --output-format raw |
raw mode bypasses the transform pipeline |
If the input is removed mid-watch (e.g. git checkout of a branch that
deletes it, or a rm between two cp commands), the watcher logs:
and keeps running. The next time the file reappears, a normal re-run fires.
Atomic saves (vim, VSCode tmp + rename pattern) stay silent β only
sustained absence triggers the warning.
Implementation details: events go through a two-level debounce. The
first level (150 ms, hard-coded) absorbs the multiple notify events a
single :w produces. The second level (default 500 ms, override via
FIMOD_WATCH_QUIET_MS=<ms>) waits for the filesystem to be quiet before
firing the re-run β needed under WSL2 / inotify cross-process latency
where event bursts can stretch beyond 400 ms. Parent directories are
watched so atomic-rename editors (vim, VSCode) work correctly. The mold
script is reloaded from disk on every iteration; no in-memory cache to
invalidate.
| Env var | Default | Purpose |
|---|---|---|
FIMOD_WATCH_QUIET_MS |
500 |
Quiet window before firing a re-run after an event. |
The feature can be disabled at compile time with cargo build --no-default-features --features=reqwest (omits notify and ~25 transitive crates). A binary built without watch rejects the flag with a clear error.
π Stdin / stdout
# π₯ Read from stdin
cat data.json | fimod s -e '{"count": len(data)}'
# π Pipe chain
curl -s https://jsonplaceholder.typicode.com/todos | fimod s -e '[d for d in data if d["completed"]]' | jq .
π Monty REPL (fimod monty repl)
Start an interactive Python REPL powered by the embedded Monty engine β no system Python needed.
fimod monty repl
# Monty REPL v0.0.8 β fimod v0.1.0-alpha.1 (exit or Ctrl+D to quit)
# >>> 2 + 2
# 4
# >>> [x ** 2 for x in range(5)]
# [0, 1, 4, 9, 16]
# >>> exit
Features:
>>>/...prompts with automatic multi-line continuation (blocks, implicit line joins)- Command history (arrow keys, via rustyline)
- Exit with
exitor ++ctrl+d++
Same engine as fimod shape
The REPL runs the exact same Monty runtime used by fimod shape, so you can experiment with Python expressions and data structures before putting them into a mold.
π Shell completion
Fimod provides dynamic shell completions: subcommands, flags, format names, mold @references, and registry source names are all completed contextually.
Add one line to your shell rc β fimod setup completions prints the activation script on stdout, you eval it. The shell is auto-detected from $SHELL; pass --shell <SHELL> to override.
Migrating from older snippets
If you previously added source <(COMPLETE=zsh fimod) (or the equivalent for your shell) to your rc, it still works β the underlying mechanism is unchanged. To switch to the new pattern, replace it with the eval "$(fimod setup completions ...)" line above.
What gets completed
| You type | ++tab++ completes |
|---|---|
fimod |
Subcommands: shape, registry, mold, completions⦠|
fimod shape -- |
All flags: --input, --mold, --debug⦠|
fimod shape --input-format |
Format names: json, yaml, csv, ndjson, toml⦠|
fimod shape --output-format |
Same format list |
fimod shape -m @ |
Registry molds: @pick_fields, @examples/flatten_nested⦠|
fimod registry show |
Configured source names |
fimod registry remove |
Configured source names |
fimod registry set-priority |
Configured source names |
fimod registry build-catalog --registry |
Configured source names |
fimod mold list |
Configured source names |
fimod mold show --registry |
Configured source names |
fimod setup completions --shell |
Shell names: bash, zsh, fish, elvish, powershell |