{"id":49671847,"url":"https://github.com/mb1986/jig","last_synced_at":"2026-05-15T01:14:39.243Z","repository":{"id":356168438,"uuid":"1229204412","full_name":"mb1986/jig","owner":"mb1986","description":"🧰 A jig for your command line","archived":false,"fork":false,"pushed_at":"2026-05-10T19:41:21.000Z","size":312,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-11T11:38:34.371Z","etag":null,"topics":["cli","command-runner","developer-tools","kdl","profile","rust","wrapper"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/jig-run","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mb1986.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-04T20:06:00.000Z","updated_at":"2026-05-10T22:16:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mb1986/jig","commit_stats":null,"previous_names":["mb1986/jig"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/mb1986/jig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mb1986%2Fjig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mb1986%2Fjig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mb1986%2Fjig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mb1986%2Fjig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mb1986","download_url":"https://codeload.github.com/mb1986/jig/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mb1986%2Fjig/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33045145,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"online","status_checked_at":"2026-05-14T02:00:06.663Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-runner","developer-tools","kdl","profile","rust","wrapper"],"created_at":"2026-05-07T00:01:21.607Z","updated_at":"2026-05-15T01:14:39.221Z","avatar_url":"https://github.com/mb1986.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jig\n\nRun commands with arguments taken from a declarative configuration\nfile.\n\n`jig` is a profile/preset manager for command-line tools. You write\na small `jig.kdl` describing the commands you run often, the default\narguments they take, and named profiles that override or extend\nthose defaults. Then `jig \u003ccommand\u003e [profile]` assembles the\nargument list and executes.\n\nIt is conceptually adjacent to [`just`][just] but distinct: where\n`just` is a recipe runner that can execute arbitrary shell, `jig`\nonly assembles argument lists. One thing, well.\n\n[just]: https://github.com/casey/just\n\n## Example\n\n`./jig.kdl`:\n\n```kdl\nllama-server \"serve\" {\n    host \"0.0.0.0\"\n    port 8090\n    c 32768\n    flash-attn #true\n\n    qwen-coder {\n        m \"/models/qwen-coder.gguf\"\n        -ngl 999\n        -ts \"0.5,0.5\"\n    }\n\n    llama3 {\n        m \"/models/llama3.gguf\"\n        port 8091\n    }\n}\n```\n\nFrom that directory:\n\n```text\n$ jig --dry-run serve qwen-coder\nllama-server --host 0.0.0.0 --port 8090 -c 32768 --flash-attn -m /models/qwen-coder.gguf -ngl 999 -ts '0.5,0.5'\n\n$ jig serve qwen-coder\n# launches llama-server with those args, inheriting stdio\n```\n\n`jig serve` (no profile) launches with just the defaults; `jig serve\nllama3` overrides `--port` and `-m` per the `llama3` profile.\n\n`--dry-run` output is shell-quoted so you can copy-paste it into a\nterminal and get the same effect.\n\n## Environment variables\n\nTools that take configuration from the environment (Docker, the\n`OLLAMA_*` family, CUDA, ...) can be set up alongside flags. A KDL\nnode bearing the `(env)` type annotation declares an env var rather\nthan a CLI argument; profiles override defaults the same way they\noverride flags, and `(env)NAME #false` unsets a variable on the\nchild:\n\n```kdl\nllama-server \"serve\" {\n    host \"0.0.0.0\"\n    (env)OLLAMA_HOST \"0.0.0.0\"\n    (env)CUDA_VISIBLE_DEVICES \"0,1\"\n\n    qwen-coder {\n        m \"/models/qwen-coder.gguf\"\n        (env)CUDA_VISIBLE_DEVICES \"0\"\n    }\n\n    sandbox {\n        m \"/models/sandbox.gguf\"\n        (env)OLLAMA_HOST #false\n    }\n}\n```\n\n```text\n$ jig --dry-run serve qwen-coder\nenv OLLAMA_HOST=0.0.0.0 CUDA_VISIBLE_DEVICES=0 llama-server --host 0.0.0.0 -m /models/qwen-coder.gguf\n\n$ jig --dry-run serve sandbox\nenv -u OLLAMA_HOST CUDA_VISIBLE_DEVICES='0,1' llama-server --host 0.0.0.0 -m /models/sandbox.gguf\n```\n\nThe `env(1)` prefix is the dry-run rendering only; actual execution\napplies the same outcomes directly to the child via\n`Command::env` / `Command::env_remove`. The child inherits `jig`'s\nenvironment by default; declared sets and unsets layer on top.\n\n## Listing\n\n```text\n$ jig --list\nllama-server (alias: serve)\n  default-args: --host 0.0.0.0 --port 8090 -c 32768 --flash-attn\n  profiles:\n    qwen-coder\n    llama3\n```\n\n## Shell completion\n\n`jig --completions \u003cshell\u003e` writes a completion script to stdout for\nzsh, bash, or fish. The script tab-completes `jig`'s own flags as\nwell as the command names, aliases, and profile names defined in the\n`jig.kdl` of whatever directory you're in (and forwards `--config\n\u003cPATH\u003e` if you've passed one).\n\n```sh\n# zsh — drop into a directory on $fpath, then `compinit`:\njig --completions zsh \u003e \"${fpath[1]}/_jig\"\n\n# bash — source on shell startup:\njig --completions bash \u003e ~/.local/share/bash-completion/completions/jig\n\n# fish:\njig --completions fish \u003e ~/.config/fish/completions/jig.fish\n```\n\n## Install\n\nFrom [crates.io](https://crates.io/crates/jig-run):\n\n```sh\ncargo install jig-run\n# installs the `jig` binary (the crate is published as `jig-run`\n# because the bare `jig` name is taken by an unrelated utility).\n```\n\nOr build from source:\n\n```sh\ngit clone https://github.com/mb1986/jig\ncd jig\ncargo build --release\n# binary lands in target/release/jig\n```\n\nRust 1.85+ (edition 2024). No nightly features.\n\n## Usage\n\n```text\njig [JIG_FLAGS]... \u003ccommand-or-alias\u003e [profile] [PASSTHROUGH]...\n```\n\n`\u003ccommand-or-alias\u003e` matches a command name or alias from `jig.kdl`.\n`[profile]` selects a profile within that command. Anything after is\nappended verbatim to the resolved command line, including a literal\n`--` and tokens that look like flags.\n\n| Flag                    | What it does                                                    |\n|-------------------------|-----------------------------------------------------------------|\n| `-n`, `--dry-run`       | Print the resolved (shell-quoted) command line and exit         |\n| `--config \u003cPATH\u003e`       | Use `\u003cPATH\u003e` instead of `./jig.kdl` / `./.jig.kdl`              |\n| `-l`, `--list`          | List configured commands, aliases, and profiles                 |\n| `--completions \u003cSHELL\u003e` | Emit a completion script (zsh/bash/fish) with dynamic command/profile completion |\n| `-h`, `--help`          | Print help                                                      |\n| `-V`, `--version`       | Print version                                                   |\n\n### Argument model\n\nA KDL node with one value is a **flag**; a node with no value is a\n**positional**. A `host \"0.0.0.0\"` line becomes `--host 0.0.0.0`;\na single-character key like `m \"/path\"` becomes `-m /path`; an\nexplicit-dash key like `-ngl 999` is passed verbatim. KDL booleans\ntoggle flag presence: `flash-attn #true` emits `--flash-attn`,\n`flash-attn #false` suppresses it (even when it would otherwise\ncome from defaults).\n\nA flag key may repeat within a scope — `gcc { I \"/a\"; I \"/b\" }`\nresolves to `gcc -I /a -I /b`, and `-v -v -v` count flags work the\nsame way. When defaults *and* a profile both contribute a single\nunmarked occurrence of the same key, the profile overrides (v1\nbehavior). To force *add* instead of *override* in that single+single\ncase, prefix the profile's key with `+`: `+I \"/proj\"`. See\n[`SPEC.md`](./SPEC.md) for the full table.\n\n### Exit codes\n\n`jig` follows the wrapper-tool exit-code convention used by\n`env(1)`, `timeout(1)`, `nohup(1)`:\n\n| Code | Meaning                                                              |\n|------|----------------------------------------------------------------------|\n| 0    | Successful resolution and execution (or any `--dry-run` / `--list` / `--completions` / `--help` / `--version`) |\n| 125  | `jig` itself failed (missing config, parse / constraint error, unknown command/profile/alias, bad CLI usage) |\n| 126  | The resolved command was found but is not executable                 |\n| 127  | The resolved command was not found                                   |\n| else | Propagated verbatim from the executed command                        |\n\n## Configuration\n\nSee [`SPEC.md`](./SPEC.md) for the behavioral specification, which\ncovers:\n\n- Config-file lookup precedence (`./jig.kdl` then `./.jig.kdl`, or\n  `--config \u003cPATH\u003e`).\n- The argument model — flags vs positionals, booleans, dash-quoted\n  positionals.\n- Prefix synthesis — when keys get `-` vs `--`.\n- Defaults and profiles, and the merge semantics (first-occurrence\n  positioning, repeated flag keys with single-mode vs repeat-mode\n  resolution, `#false` suppression, and the `+` append marker).\n- Constraints (uniqueness, no-leading-dash names).\n- Diagnostic quality — what `jig` errors aim for.\n\n[`IMPLEMENTATION.md`](./IMPLEMENTATION.md) covers the build, type\ndesign, and dependency choices.\n\n## Status\n\n**v1, Unix only.** Tested on Linux and macOS. Windows support is\ndeferred — see [`FUTURE.md`](./FUTURE.md), which also tracks\nenvironment-variable bindings, parent-directory config traversal,\nprofile inheritance, and other ideas surfaced during design.\n\n## License\n\nMIT — see [`LICENSE`](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmb1986%2Fjig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmb1986%2Fjig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmb1986%2Fjig/lists"}