[!NOTE] Status: experimental. The command definitions and shell integrations may change before 1.0.
The last line is not output. It is your next prompt, already filled in. jany prints one shell-quoted line on stdout, and the wrapper from jany --init zsh puts it on the command line. Read it, edit it if you like, press Enter.
|
jany generalises jind (jev × find) and jurl (jev × curl) into one binary. Each command is a definition directory — three files, no Rust — and adding a command is a job for an LLM skill, not a new crate.
How it works
- rules — the unambiguous shapes are decided by data in
schema.toml: paths, globs,8080:80,KEY=value,+7d,>10M, table words likefiles/delete/background. If every word resolves, jany never leaves your machine. - jev — anything left over goes to jev (TypeSafe System One, via OpenRouter) in one request: "what is the role of each word?" plus the extra questions the schema declares (which unit? at least or at most? a typo of which table word?). jev only picks from fixed choices and returns probabilities; it never generates the command.
- repair — fixes what jev cannot see word by word: attach
daysto7, letexceptclaim the names after it, pairfirst_name amandainto key and value. - assemble.sh — the command's own script (stdin JSON → stdout JSON) turns the role-tagged words into
argv. It also says how risky the result is. - output — the line goes to stdout, everything else to stderr. When the words can't be turned into a command (unresolved, or below a confidence floor), jany exits non-zero and puts
jany <command> --hinton the prompt instead, with the reason as a comment. Adangerousresult (find-delete) is previewed first with a read-only run. Anunsafeone (curlDELETE, docker--privileged) gets a one-line note.
One jev call is 200–700 ms and under $0.0001.
Setup
# Before the release, install from this checkout:
jany --init does three things: prints the wrapper function, installs the built-in definitions (find, curl, docker run) into ~/.config/jany/cmd/, and installs the /jany-register skill into ~/.agents/skills/ (linked from ~/.claude/skills/ and ~/.codex/skills/ when those exist). It never overwrites a definition you have edited. The skill is in English by default; jany --init zsh --locale ja installs the Japanese one (put the flag in your rc line, since --init rewrites the skill on every shell start).
OPENROUTER_API_KEY in the environment takes precedence; a key saved by jind setup or jurl setup is picked up too. Tested on macOS with zsh.
Usage
jany <command> [words ...] [flags] [-- passthrough args]
| flag | |
|---|---|
--explain |
per-word role, confidence, and whether a rule or jev decided it (stderr) |
--no-jev |
offline only; unresolved words are an error |
--hint |
what you can say to <command> (its roles) and examples from its cases.toml (stderr) |
-- … |
passed through untouched (what that means is up to the command: find options, curl flags, the container command for docker run) |
jany's own actions are flags, so <command> is always the tool's name:
jany --list |
the definitions found, with an example each |
jany --test find |
run a definition's cases.toml (jev answers are mocked) |
/jany-register tar |
create and fill ~/.config/jany/cmd/tar/ with the agent skill |
jany --init zsh|bash|fish |
the wrapper, plus built-ins and the skill (--locale en|ja, default en) |
jany --setup |
save the API key |
Adding a command
A definition lives in ~/.config/jany/cmd/<name>[/<sub>]/:
| file | |
|---|---|
schema.toml |
roles (what jev may choose from), word tables, rules, questions for jev, repair steps, risk settings |
assemble.sh |
role-tagged tokens in, {argv, preview, risk, pipe, error} out; any language, bash + jq is enough |
cases.toml |
words → expected argv, with jev's answers written down; jany --test refuses answers to questions jany did not ask |
The skill reads a reference of every schema key and the two worked examples (find, curl) before writing. The rule of thumb from jind and jurl carries over: cover the 80 % you actually type, pass the rest through after --, and do not trust an assemble.sh that has no cases.
Config (optional)
~/.config/jany/config.toml
[]
= "typesafe/jev-1.13"
= 0.5 # below this, no command: exit non-zero and offer `--hint`
[] # overrides the schema's [defaults]
= "text/plain"
[]
= "~/Downloads"
Where it is weak
- The same weaknesses as jind and jurl: a bare word (
log,app) can be two roles at once, and jev is often only 0.6–0.9 sure. Write the unambiguous form (*.log) to skip jev. - Commands whose vocabulary does not close — arbitrary SQL, jq programs, ffmpeg filter graphs — are not a fit. Cover the common forms and pass the rest through.
- Every word, including ones the rules already decided, is sent to jev as context. Roles that may carry secrets (curl headers, docker
KEY=value) declare amaskso only a placeholder goes out.