just-x

module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: MIT

README ΒΆ

justx

Go Version


The just companion. πŸ‘Ύ justx is a small Go binary that wraps just and does two things:

  1. Expressive recipe names - type :, !, and ? in recipe names, which just doesn't allow (#2669, #2587). justx translates them to plain names before calling real just.
  2. Scaffolding - j @init detects your stack and writes a justfile from composable modules (fmt, lint, fix, test, build, ci).
j app:test           # runs β†’ just app--test
j build!             # runs β†’ just build-x
j ready?             # runs β†’ just ready-q
j test               # unchanged
j @init              # detect project + scaffold a justfile

Install

Requires Go. The installer builds the binary with go install and adds the j / just aliases to your shell.

git clone https://github.com/amberpixels/just-x.git
cd just-x && ./install.sh

Restart your shell (or source your rc file), then try j @init.

Manual install
go install github.com/amberpixels/just-x/cmd/justx@latest

# then add to ~/.zshrc (zsh) - noglob lets you type `?` unquoted:
alias j='noglob justx'
alias just='noglob justx'

# or ~/.bashrc (bash):
alias j='justx'
alias just='justx'

Expressive Recipe Names

You type Runs Mapping
j app:build just app--build : β†’ --
j dev! just dev-x ! β†’ -x
j ready? just ready-q ? β†’ -q

Name your recipes in the mapped form; type the expressive form in the terminal:

lint--go:           # ← call with: j lint:go
    golangci-lint run

build-x:            # ← call with: j build!  (force rebuild, no cache)
    go build -a ./...

ready-q:            # ← call with: j ready?  (check if ready)
    ./check.sh

j --list (and -l / --summary) reverse-translates the output back to the expressive form, keeping comment alignment intact.

Why the alias? A binary can't intercept the bare word just, and zsh expands ? as a glob before any binary runs. The noglob alias solves both. : and ! need no special handling; in bash, only ? must be quoted (j 'ready?').

Scaffolding with @init

j @init detects your project (Go via go.mod, Node via package.json, shell via scripts in ./, bin/ or scripts/), shows a checkbox form of modules pre-ticked from detection, and writes a justfile. Use --yes to skip the form and accept the pre-ticked set.

Go projects that pin standardgo as a tool dependency get go tool standardgo recipes for fmt / lint / fix; everything else falls back to go fmt and golangci-lint.

Shell projects get shellcheck for correctness and shfmt for formatting. Scripts are discovered at run time by shfmt -f, which matches on extension and on shebang, so an extensionless bin/deploy is covered without being listed anywhere. Shell is detected last, so a Go or Node repo that merely ships a few helper scripts keeps its real stack. There is no test module: no shell test runner is conventional enough to assume.

Each module is written inside provenance fences so a future j @upgrade can re-sync it without touching your edits:

# >>> justx:lint (managed) β€” `j @upgrade` re-syncs; remove these fences to take over
# lint Go code - reports findings, changes nothing
lint:
    golangci-lint run
# <<< justx:lint

@init refuses to overwrite an existing justfile (merging is @upgrade, coming in a later release).

Meta-Commands

Meta-commands live under the @ sigil and are handled by justx, never passed to just:

j @init [--yes]   detect project + scaffold a justfile
j @help           show help
j @version        print version

Planned: @add, @upgrade, @doctor, @templates.

Configuration

Override the character mappings via environment variables (set before the aliases in your rc file):

export JUST_X_BANG="-x"       # ! replacement (default: -x)
export JUST_X_QUESTION="-q"   # ? replacement (default: -q)
export JUST_X_COLON="--"      # : replacement (default: --)

Development

justx scaffolds its own justfile, so the repo is its own smoke test:

j ci               # lint + test, read-only
j fix              # auto-fix what can be fixed
j demo:list        # `--list` through justx: recipe names in expressive form
j demo:init        # scaffold into a throwaway project and print the result
j ready?           # green ci + tidy modules + clean tree

The blocks between the # >>> justx:<id> fences were written by j @init; everything below them is hand-written. Linting comes from standardgo, pinned as a tool dependency in go.mod - there is no local .golangci.yml.

Uninstall

./uninstall.sh

Requirements

Feedback

justx is a solo, opinionated project - but if you stumbled upon it and have ideas, questions, or bug reports, an issue is always welcome :)

License

MIT Β© amberpixels

Directories ΒΆ

Path Synopsis
cmd
justx command
Command justx is the justfile companion: an expressive-name router for `just` plus meta-commands (the `@`-sigil namespace) for scaffolding and upgrading justfiles.
Command justx is the justfile companion: an expressive-name router for `just` plus meta-commands (the `@`-sigil namespace) for scaffolding and upgrading justfiles.
internal
detect
Package detect inspects a directory tree for project signals (go.mod, package.json, …) and reports the stack so @init can pre-tick the right modules.
Package detect inspects a directory tree for project signals (go.mod, package.json, …) and reports the stack so @init can pre-tick the right modules.
meta
Package meta dispatches `@`-sigil meta-commands β€” handled by justx, never passed to `just`.
Package meta dispatches `@`-sigil meta-commands β€” handled by justx, never passed to `just`.
modules
Package modules holds the built-in, data-driven justfile modules.
Package modules holds the built-in, data-driven justfile modules.
router
Package router translates expressive recipe names (`:`, `!`, `?`) into the mappings real `just` understands, then execs `just`.
Package router translates expressive recipe names (`:`, `!`, `?`) into the mappings real `just` understands, then execs `just`.
scaffold
Package scaffold composes selected modules into a justfile, wrapping each module's recipes in `# >>> justx:<id>` / `# <<< justx:<id>` provenance fences so v2's @upgrade can re-sync managed regions without clobbering user edits.
Package scaffold composes selected modules into a justfile, wrapping each module's recipes in `# >>> justx:<id>` / `# <<< justx:<id>` provenance fences so v2's @upgrade can re-sync managed regions without clobbering user edits.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL