{"id":50463874,"url":"https://github.com/ubugeeei-prod/ush","last_synced_at":"2026-06-01T06:03:54.683Z","repository":{"id":348015015,"uuid":"1196037231","full_name":"ubugeeei-prod/ush","owner":"ubugeeei-prod","description":"ush is modern sh","archived":false,"fork":false,"pushed_at":"2026-05-25T11:07:02.000Z","size":1045,"stargazers_count":10,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-29T05:24:13.037Z","etag":null,"topics":["posix","shell"],"latest_commit_sha":null,"homepage":"https://ubugeeei-prod.github.io/ush/","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/ubugeeei-prod.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-30T10:02:13.000Z","updated_at":"2026-05-29T03:12:58.000Z","dependencies_parsed_at":"2026-04-04T21:00:51.179Z","dependency_job_id":null,"html_url":"https://github.com/ubugeeei-prod/ush","commit_stats":null,"previous_names":["ubugeeei/ush","ubugeeei-prod/ush"],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/ubugeeei-prod/ush","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ubugeeei-prod%2Fush","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ubugeeei-prod%2Fush/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ubugeeei-prod%2Fush/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ubugeeei-prod%2Fush/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ubugeeei-prod","download_url":"https://codeload.github.com/ubugeeei-prod/ush/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ubugeeei-prod%2Fush/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33762215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"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":["posix","shell"],"created_at":"2026-06-01T06:03:51.392Z","updated_at":"2026-06-01T06:03:54.668Z","avatar_url":"https://github.com/ubugeeei-prod.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ush\n\n[![CI](https://github.com/ubugeeei/ush/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/ubugeeei/ush/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/ubugeeei/ush/actions/workflows/codeql.yml/badge.svg?branch=main)](https://github.com/ubugeeei/ush/actions/workflows/codeql.yml)\n[![Secret scan](https://github.com/ubugeeei/ush/actions/workflows/secret-scan.yml/badge.svg?branch=main)](https://github.com/ubugeeei/ush/actions/workflows/secret-scan.yml)\n[![Shellcheck](https://github.com/ubugeeei/ush/actions/workflows/shellcheck.yml/badge.svg?branch=main)](https://github.com/ubugeeei/ush/actions/workflows/shellcheck.yml)\n[![Dependencies](https://github.com/ubugeeei/ush/actions/workflows/dependencies.yml/badge.svg?branch=main)](https://github.com/ubugeeei/ush/actions/workflows/dependencies.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n\n`ush` is an experimental Rust shell with a simple idea:\n\n- Be POSIX-first. Existing shell scripts and one-liners should keep working.\n- Keep stdio Unix-simple by default, but allow richer human-facing output with `--stylish`.\n- Add a modern `.ush` language, but compile it to portable `sh` instead of inventing a separate runtime.\n- Make the interactive shell feel fast, lightweight, and pleasant to edit in.\n\n\u003e [!WARNING]\n\u003e `ush` is still an early WIP / prototype.\n\u003e Expect rough edges, missing POSIX coverage, incomplete language features, and breaking changes.\n\u003e It is not yet a production shell replacement.\n\n## Concept\n\n`ush` is split into two layers:\n\n- `ush_shell`: an interactive shell runtime with POSIX-friendly execution, REPL UX, stylish mode, and structured helper pipelines\n- `ush_compiler`: a `.ush` to `sh` compiler, where scripts stay portable because execution still happens through POSIX `sh`\n\nThat means the project can explore a more modern shell language without giving up the portability and compatibility of `sh`.\nThe `no_std` target is only the compiler core. The app binary and interactive shell runtime are still intentionally `std`-based because they need processes, terminals, files, and OS integration.\n\nLanguage direction:\n\n- aim for a real small language closer to MoonBit in seriousness than to shell macros\n- keep the everyday feel somewhere between Rust, Zig, and Go\n- prefer strong data modeling and a practical stdlib over clever shell-only tricks\n- keep POSIX `sh` as the lowered runtime contract\n\n## Status\n\nThis repository is an MVP focused on architecture and interaction experiments.\n\nImplemented today:\n\n- Interactive shell REPL in Rust\n- `-c` command execution\n- `.sh` / POSIX scripts executed through `/bin/sh`\n- `.ush` scripts compiled to `sh` and then executed by `/bin/sh`\n- Generated `.ush` output stays within POSIX `sh` syntax and POSIX command usage\n- Prototype typed language features: `type { ... }`, enums, traits, marker `impl`, `match`, typed `fn`, Zig-style error signatures like `Problem!String`, and Rust-like `?` propagation\n- Rust-like tail expressions in value-returning functions, where the final expression returns and `;` keeps it as a statement\n- Rust-like `std::module::function` paths plus `use` imports for selected std helpers, including `std::env`, `std::path`, `std::fs`, `std::command`, `std::string`, `std::http`, and `std::regex` with capture support\n- Labeled function arguments plus parameter attributes such as `#[default(...)]` and `#[alias(\"n\")]`\n- `alias name = \"...\"` declarations in `.ush`\n- `bin.ush` as a generated CLI entrypoint, with flags/defaults/completion derived from the `bin(...)` signature\n- `crates/ush_compiler` builds as `no_std + alloc` with CompactString, SmallVec, bumpalo, memchr, phf, and Fx-hashed maps in the core path\n- `apps/ush` and `crates/ush_shell` remain `std`-based by design\n- Installer patterns such as `curl -fsSL https://... | sh` are detected from the parsed pipeline and executed through POSIX `/bin/sh`\n- `.ush` inline shell escapes via `$ command ...`, alongside `shell expr` for dynamic command strings\n- Builtins: `:`, `.`, `cd`, `pwd`, `echo`, `true`, `false`, `alias`, `unalias`, `jobs`, `wait`, `disown`, `fg`, `bg`, `port`, `stop`, `history`, `export`, `unset`, `confirm`, `input`, `select`, `env`, `command`, `which`, `type`, `test`, `[`, `help`, `source`, `rm`\n- Login/profile startup loading via `--login`, `--profile-file`, `--rc-file`, legacy `~/.ush_profile` / `~/.ushrc`, and rc defaults from `~/.config/ush/.config.ush` or `~/.config.ush`\n- Builtin utility: `sammary` for recursive file and type summaries across paths and globs, with lockfiles excluded by default\n- Safety prompt for dangerous recursive `rm` unless `--yes` or `USH_INTERACTION=false`\n- Stylish renderers for `pwd`, `ls`, `cat`, `ps`, and `kill`\n- Stylish command introspection for `which`, `type`, `command -v`, and `command -V`, with `which` listing every candidate and marking the one `ush` will run\n- Structured helpers: `len`, `lines`, `json`, `xml`, `html`, `car`, `cdr`, `head`, `tail`, `take`, `drop`, `nth`, `enumerate`, `swap`, `fst`, `snd`, `frev`, `fsort`, `funiq`, `fjoin`, `map`, `fmap`, `flat`, `ffmap`, `fzip`, `each`, `filter`, `ffilter`, `any`, `fany`, `some`, `fsome`\n- Environment-variable expansion, `~` expansion, and simple glob expansion\n- Criterion benchmark skeleton for parser/profiling work\n- GitHub Releases, `curl` installer, `nix`, and Docker packaging entry points\n- Emacs-style and opt-in Vi-style REPL editing modes\n- `ush format` and `ush check` commands for formatter and typechecking passes\n- `ush_lsp` with document formatting, diagnostics, and semantic tokens for editor integration\n\nNot there yet:\n\n- Full native POSIX grammar coverage inside the Rust runtime\n- Richer typed structured values beyond text / JSON helpers\n- Broader language features such as HM inference, generics, HKT, modules, `yield`, and real green-thread scheduling\n- Inherent `impl Type { ... }` methods and a Rust-complete type system; the current prototype is still a small subset\n- A truly finished shell UX; editing, completion, and IME behavior are still being tuned\n\nWorkspace layout:\n\n- `apps/ush`: CLI binary\n- `crates/ush_config`: config loading and runtime paths\n- `crates/ush_compiler`: `.ush` to `sh` compiler core, `no_std + alloc` capable\n- `crates/ush_shell`: interactive shell, parser, stylish I/O, helpers\n- `crates/ush_tooling`: formatter, diagnostics, and semantic token generation\n- `apps/ush_lsp`: stdio LSP server for editors\n\n## Usage\n\nQuick install:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ubugeeei/ush/main/install.sh | sh\nexec \"$SHELL\" -l\nush --version\n```\n\nThe installer tries to stay zero-config:\n\n- it installs into the first writable personal bin directory already on your `PATH`\n- otherwise it falls back to `~/.local/bin`\n- if that directory is not on your `PATH`, it appends the export line to `~/.zshrc`, `~/.bashrc`, or `~/.profile`\n\nIf you want an explicit location instead:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ubugeeei/ush/main/install.sh | sh -s -- --bin-dir \"$HOME/.local/bin\"\n```\n\n`nix profile install ...` and the Docker image already expose `ush` on `PATH`.\n\n```bash\ncargo run -p ush\n```\n\nRun a one-liner:\n\n```bash\ncargo run -p ush -- -c 'printf \"a\\nb\\n\" | len'\n```\n\nKill the process that is listening on a port:\n\n```bash\ncargo run -p ush -- -c 'port 3341 | stop'\n```\n\nInspect command resolution order and see which candidate is current:\n\n```bash\ncargo run -p ush -- -s -c 'which echo'\n```\n\nEnable stylish mode:\n\n```bash\ncargo run -p ush -- -s -c 'ls crates'\n```\n\nForce stylish mode globally:\n\n```bash\nexport USH_STYLISH=true\n```\n\nOpt into the Vi-style REPL keymap, which is useful in environments such as Codex Desktop where `Cmd` shortcuts may be intercepted before they reach the shell:\n\n```bash\nexport USH_KEYMAP=vi\n```\n\nDisable interactive confirmations:\n\n```bash\nexport USH_INTERACTION=false\n```\n\nLoad login/profile startup files explicitly:\n\n```bash\ncargo run -p ush -- --login\ncargo run -p ush -- --profile-file ~/.config/ush/profile.sh -c 'echo $PWD'\ncargo run -p ush -- --rc-file ~/.config.ush\n```\n\n## Interactive Editing\n\nThe REPL is tuned around `rustyline`'s Emacs mode with extra bindings for shell-heavy navigation:\n\n- `Ctrl-A` / `Ctrl-E`: jump to line start/end\n- `Ctrl-C`: interrupt the current prompt or child command and return control to `ush`\n- `Ctrl-L`: clear the screen\n- `Ctrl-P` / `Ctrl-N`: previous and next history entry\n- `Ctrl-U` / `Ctrl-K`: kill to the line start/end\n- `Ctrl-W`: kill the previous shell word\n- `Up` / `Down`: previous and next history entry\n- `Shift-Left` / `Shift-Right`: extend a visible character selection\n- `Shift-Up` / `Shift-Down`: behaves like normal history movement when the terminal forwards those keys\n- `Option-Up` / `Option-Down`: prefix history search\n- `Option-Left` / `Option-Right`: word-wise cursor movement\n- `Option-Shift-Left` / `Option-Shift-Right`: extend selection word-by-word\n- `Ctrl-Left` / `Ctrl-Right`: word-wise movement on terminals that send control-arrow escapes\n- `Ctrl-Shift-Up` / `Ctrl-Shift-Down`: select to the line start/end on terminals that map document-edge shortcuts there\n- `Ctrl-Alt-Shift-Left` / `Ctrl-Alt-Shift-Right`: extend selection across big shell tokens\n- `Ctrl-Alt-Shift-Up` / `Ctrl-Alt-Shift-Down`: extra line-edge selection aliases for macOS terminal mappings\n- `Home` / `End`: jump to line start/end, and `Shift-Home` / `Shift-End` selects to the edge\n- `Cmd-Left` / `Cmd-Right`: jump to line start/end when the terminal forwards them as `Super` cursor keys\n- `Cmd-Shift-Left` / `Cmd-Shift-Right`: extend selection to the line edges when the terminal forwards `Super+Shift`, and `Cmd-Shift-Up` / `Cmd-Shift-Down` map to the same line-edge selection inside the single-line REPL\n\nWhen a selection is active, typing replaces it and `Backspace` / `Delete` / `Ctrl-W` / `Ctrl-U` / `Ctrl-K` remove it, so keyboard-only editing feels closer to a native text field even inside the terminal.\n\nTab completion is context-aware instead of just dumping filesystem entries. In particular, `git` commands now complete subcommands, common flags, branch/tag/remote/stash names, recent commits, and pathspecs relative to the current shell directory, while the inline hint shows a short usage reminder for the argument you are typing.\n\nIf you opt into `USH_KEYMAP=vi` or `shell.keymap = \"vi\"`, `ush` switches the REPL to `rustyline`'s Vi editing mode instead. That is the recommended workaround for Codex Desktop, where `Cmd`-modified keys are often intercepted by the host app before the shell can read them.\n\n## Structured Helpers\n\n`ush` keeps normal Unix pipes, but helper stages can operate on structured values:\n\n```bash\nprintf \"alpha\\nbeta\\ngamma\\n\" | filter(\\it -\u003e contains(it, \"a\")) | len\nprintf \"hello\\nworld\\n\" | map(\\it -\u003e upper(it))\nprintf \"hello\\nworld\\n\" | fmap(\\it -\u003e upper(it))\nprintf \"hello\\n\" | map(\\line -\u003e { upper(line) })\nprintf \"alpha\\nbeta\\ngamma\\n\" | car\nprintf \"alpha\\nbeta\\ngamma\\n\" | cdr\nprintf \"alpha\\nbeta\\ngamma\\n\" | take(2)\nprintf \"alpha\\nbeta\\ngamma\\n\" | drop(1)\nprintf \"alpha\\nbeta\\ngamma\\n\" | nth(1)\nprintf \"alpha\\nbeta\\ngamma\\n\" | enumerate(1)\nprintf \"beta\\nalpha\\nbeta\\n\" | fsort | funiq | fjoin(\",\")\nprintf \"alpha\\nbeta\\ngamma\\n\" | flat(\\head, rest -\u003e [head, \"tail\", rest])\nprintf \"alpha\\nbeta\\n\" | fzip([\"1\", \"2\"])\nprintf \"alpha\\nbeta\\n\" | fzip([\"1\", \"2\"]) | swap\nprintf \"alpha\\nbeta\\n\" | fzip([\"1\", \"2\"]) | fst\nprintf \"alpha\\nbeta\\n\" | fzip([\"1\", \"2\"]) | snd\ncat package.json | json | len\ncat feed.xml | xml\ncurl -fsSL https://example.com | html\n```\n\nCurrently supported helper forms:\n\n- `len`\n- `length` (compatibility alias)\n- `lines`\n- `json`\n- `xml`\n- `html`\n- `car`\n- `cdr`\n- `head`\n- `tail`\n- `take(2)`\n- `drop(1)`\n- `nth(1)`\n- `enumerate(1)`\n- `swap`\n- `fst`\n- `snd`\n- `frev`\n- `fsort`\n- `funiq`\n- `fjoin(\",\")`\n- `map(\\it -\u003e upper(it))`\n- `fmap(\\it -\u003e upper(it))`\n- `map(\\it -\u003e lower(it))`\n- `map(\\it -\u003e trim(it))`\n- `map(\\it -\u003e replace(it, \"from\", \"to\"))`\n- `flat(\\head, rest -\u003e [head, rest])`\n- `ffmap(\\head, rest -\u003e [head, rest])`\n- `fzip([\"left\", \"right\"])`\n- `each(\\it -\u003e print(it))`\n- `filter(\\it -\u003e contains(it, \"foo\"))`\n- `ffilter(\\it -\u003e contains(it, \"foo\"))`\n- `filter(\\it -\u003e starts_with(it, \"foo\"))`\n- `filter(\\it -\u003e ends_with(it, \"foo\"))`\n- `any(\\it -\u003e contains(it, \"foo\"))`\n- `fany(\\it -\u003e contains(it, \"foo\"))`\n- `some(\\it -\u003e contains(it, \"foo\"))`\n- `fsome(\\it -\u003e contains(it, \"foo\"))`\n\n`html` writes the current stream into a temporary HTML file and opens it in your default browser.\nIf `json` cannot parse the stream, `ush` falls back to this browser flow instead of failing immediately.\n`xml` pretty-prints valid XML and falls back to the same browser flow if the input is not valid XML.\n`car` and `cdr` are Lisp-style head and tail helpers over the current line stream.\n`head` and `tail` are plain aliases for `car` and `cdr`.\n`take`, `drop`, `nth`, and `enumerate` are Rust-style line-stream helpers, with `nth` using zero-based indexing.\n`fst` and `snd` project the first and second fields from tab-separated pair streams such as `fzip(...)`.\n`swap` flips those tab-separated pair streams.\n`frev`, `fsort`, and `funiq` reverse, lexicographically sort, and de-duplicate line streams.\n`fjoin(\"...\")` collapses the current line stream into one line using a literal delimiter.\n`flat` is a small stream-level flat-map that binds `head` and `rest`, where `rest` splices the remaining lines into the output list.\n`fmap`, `ffmap`, `ffilter`, `fany`, and `fsome` are functional aliases for the corresponding helpers.\n`fzip` zips the current line stream against a literal right-hand list or multiline string and emits tab-separated pairs.\nHelper lambdas also accept `\\name -\u003e expr`, `\\name -\u003e { expr }`, zero-arg forms like `\\-\u003e { \"ok\" }`, and two-arg `flat(\\head, rest -\u003e [...])`.\n\n## Stylish Mode\n\nThe shell-level `-s` / `--stylish` flag swaps some Unix commands into richer output without changing their names:\n\n- `pwd`\n- `ls`\n- `cat`\n- `ps`\n- `kill`\n\nWhen stylish mode is off, `ush` stays close to classic Unix text output.\nCompiled `.ush` scripts keep POSIX stdio and run under `/bin/sh`; stylish rendering is only an interactive shell feature.\n\n## Config\n\nConfig is resolved from:\n\n- `~/.config/ush/config.pkl`\n- `~/.config/ush/config.json`\n\nDefault shell rc loading is separate from structured config. For interactive sessions, `ush` now prefers `~/.config/ush/.config.ush`, falls back to `~/.config.ush`, and still accepts legacy `rc.sh` / `.ushrc`.\n\nExample `config.pkl`:\n\n```pkl\n{\n  shell {\n    stylishDefault = true\n    interaction = true\n    historySize = 10000\n    keymap = \"vi\"\n    prompt = \"ush\u003e \"\n  }\n\n  aliases {\n    ll = \"ls -la\"\n    gs = \"git status -sb\"\n  }\n}\n```\n\nBecause Pkl tooling differs by version, `ush` tries a few `pkl eval` JSON output flag variants before falling back to JSON config.\nLegacy `~/.config/ubsh` config files and `UBSHELL_*` env vars are still accepted for compatibility.\n\n## Ush Scripts\n\n`.ush` files are compiled to `sh`; execution still happens in `/bin/sh`.\n\nSmall example:\n\n```text\nlet greeting = \"hello\"\nprint greeting + \" world\"\n$ printf '%s\\n' from-ush\nmatch greeting {\n  \"hello\" =\u003e print \"matched\"\n  _ =\u003e print \"fallback\"\n}\n```\n\nCurrent highlights:\n\n- `let`, `print`, `match`, typed `fn`, `enum`, `type`, marker `trait`, and Rust-like tail expressions\n- `\"\"\" ... \"\"\"` multiline strings with common-indent dedent\n- `std::env`, `std::path`, `std::fs`, `std::command`, and `std::string` helpers via fully-qualified calls or top-level `use`, plus method-style path/string flows like `path.resolve()`, `path.exists()`, `path.read_text()`, and `name.trim_suffix(\".ush\")`\n- `raise` plus typed error signatures like `Problem!String`, with Rust-like `?` propagation\n- `$ command ...` for inline shell execution and `shell expr` for dynamic command strings\n- `async` / `.await`\n- `bin(...)` entrypoints for generated CLI tools\n- `#|` doc comments for generated `--help`, `--man`, and completion text, including std-like sections such as notes, warnings, errors, and see-also links\n- sectioned sourcemaps with generated-line summaries, reverse source indexes, and runtime failure mapping back to `.ush` lines\n\nUseful commands:\n\n```bash\ncargo run -p ush -- examples/hello.ush\ncargo run -p ush -- scripts/bootstrap.sh --flag value\ncargo run -p ush -- examples/control_flow.ush\ncargo run -p ush -- compile examples/hello.ush\ncargo run -p ush -- test examples/smoke_test.ush\ncargo run -p ush -- compile examples/hello.ush --sourcemap /tmp/hello.sh.map.json\ncargo run -p ush -- format examples/hello.ush --stdout\ncargo run -p ush -- check examples/hello.ush\ncargo run -p ush_lsp\ncargo run -p ush -- examples/std_modules.ush\ncargo run -p ush -- examples/http_regex.ush\ncargo run -p ush -- -c \"sammary 'crates/ush_shell/src'\"\ncargo run -p ush -- -c \"sammary --include-lock .\"\n```\n\n`.ush` files are compiled and then executed by `/bin/sh`; `.sh` files are forwarded straight to `/bin/sh` with their arguments.\n\nStart here for more detail:\n\n- `docs/language-vision.md` for the language design target and ergonomics direction\n- `examples/README.md` for runnable samples\n- `docs/README.md` for guide index\n- `docs/sourcemaps.md` for the sourcemap JSON format, sections, reverse lookup, and runtime diagnostics\n- `docs/typed-errors.md` for a step-by-step walkthrough of `Problem!T`, `raise`, inferred `# raises:`, `?`, and external-command `unknown`\n- `docs/lsp.md` for editor integration with `ush_lsp`\n\n## Install\n\n### curl\n\n`install.sh` downloads the matching GitHub Releases archive and installs `ush` plus `ush_lsp`.\nBy default it picks the first writable personal bin directory already on `PATH`.\nIf none is available, it falls back to `~/.local/bin` and updates your shell rc automatically on POSIX shells.\nIt refuses to install unless it can verify the archive against the release `sha256sums.txt` with `sha256sum`, `shasum`, `openssl`, or `python3`.\nRelease archives are currently published for:\n\n- macOS `x86_64`\n- macOS `aarch64`\n- Linux `x86_64-unknown-linux-gnu`\n- Linux `aarch64-unknown-linux-gnu`\n\nThe Linux archives are built on `ubuntu-latest` (x86_64) and\n`ubuntu-24.04-arm` (aarch64), so the glibc baseline is whatever the\nGitHub Actions image ships at the time of the build. Distributions\nolder than the runner image's glibc require building from source.\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ubugeeei/ush/main/install.sh | sh\n```\n\nPin a release version:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ubugeeei/ush/main/install.sh | sh -s -- --version v0.6.0\n```\n\nInstall into a custom bin directory:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ubugeeei/ush/main/install.sh | sh -s -- --bin-dir \"$HOME/.ush/bin\"\n```\n\nSkip automatic `PATH` updates:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ubugeeei/ush/main/install.sh | sh -s -- --no-modify-path\n```\n\nOverride the checksum manifest URL:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/ubugeeei/ush/main/install.sh | sh -s -- --checksum-url https://example.com/sha256sums.txt\n```\n\n### nix\n\n```bash\nnix profile install github:ubugeeei/ush\n```\n\n### source\n\nIf your platform does not have a prebuilt release archive yet, build from source:\n\n```bash\ncargo build --release -p ush -p ush_lsp\nmkdir -p \"$HOME/.local/bin\"\ninstall -m 755 target/release/ush \"$HOME/.local/bin/ush\"\ninstall -m 755 target/release/ush_lsp \"$HOME/.local/bin/ush_lsp\"\n```\n\n### Docker\n\nThe Docker image is meant to be a distribution target and base image: a small environment where `ush` is already installed and ready to use.\n\n```bash\ndocker build -t ush .\ndocker run --rm -it ush\n```\n\nUse it as a base image:\n\n```dockerfile\nFROM ush\n\nRUN printf \"a\\nb\\n\" | len\nCMD [\"ush\"]\n```\n\n## Benchmarks\n\n```bash\ncargo bench -p ush_shell\n```\n\nThe initial benchmark targets parser + helper-pipeline shapes and is intended as a seed for more aggressive profiling.\n\n## Release\n\nGitHub Actions provides two release paths:\n\n- Push a `v*` tag to run the release pipeline directly\n- Run `Cut Release` from the Actions tab to create and push a tag, then call the same release pipeline\n\n`Cut Release` asks for a version like `v0.2.0` and a target ref such as `main`.\n\nSee [`docs/release-process.md`](./docs/release-process.md) for the full pre-flight checklist, the matrix of published artefacts, and the rollback procedure.\n\n## CI\n\nGitHub Actions runs formatting, the Rust 250-line file limit check, workspace tests, release tests, bench build checks, and the `.ush` async / ADT examples on every pull request and push to `main`.\n\nA separate `Dependencies` workflow watches `vendor/rustyline` against `crates.io` on a weekly cron via [`scripts/check_rustyline_upstream.sh`](./scripts/check_rustyline_upstream.sh) and fails when the pinned tag in [`vendor/rustyline/UPSTREAM`](./vendor/rustyline/UPSTREAM) is behind upstream, so security advisories surface even between human reviews.\n\n## Production readiness\n\n`ush` is still a pre-1.0 prototype (see the warning at the top of this file), but the 0.7.0 line ships with a deliberately strict CI / supply-chain posture so a production-style deployment is feasible inside the supported scope:\n\n- **Correctness gates** — `cargo test --workspace` on Ubuntu and macOS, `cargo test --release` on every published target (Linux `x86_64`/`aarch64`, macOS `x86_64`/`aarch64`), `no_std` test suite, MSRV gate (currently 1.88), rustdoc with `-D warnings`, and `ush check` + `ush format --check` over the committed example corpus.\n- **Static analysis** — clippy `-D warnings`, workspace-wide lints denying `todo!()` / `dbg!()` / `unimplemented!()` / `unused_must_use`, plus CodeQL (Rust, `security-and-quality` query pack) on every PR and a weekly cron.\n- **Supply chain** — `cargo audit`, `cargo deny` (licenses / sources / advisories / bans), weekly Gitleaks secret scan, a vendored-`rustyline` drift watcher, and Dependabot subscribed to GitHub Actions updates so action versions never silently age.\n- **Runtime hardening** — signal helpers use `sigaction(2)` with checked `pid_t` casts; the compiler enforces `match` exhaustiveness at the effects pass; `install.sh` pins HTTPS + TLS 1.2, sets `umask 077`, and best-effort `set -o pipefail`; the docker image runs as a non-root user.\n- **Release pipeline** — tag push (or the `Cut Release` workflow) triggers preflight (tag matches `Cargo.toml`), per-target build + test + attestation, installer smoke-test against the freshly-built archive, and a GitHub Release with `sha256sums.txt`. Procedure is documented in [`docs/release-process.md`](./docs/release-process.md).\n- **Performance gate** — parser and `.ush → sh` compile benchmarks are tracked against the `main` baseline on `gh-pages`; PRs fail when a microbench regresses by more than 25%.\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for the local-CI flow,\nworkspace layout, and PR conventions. The full list of user-visible\nchanges lives in [CHANGELOG.md](./CHANGELOG.md). Security reports go\nthrough the private channel described in [SECURITY.md](./SECURITY.md)\n— please do not open a public issue for them.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fubugeeei-prod%2Fush","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fubugeeei-prod%2Fush","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fubugeeei-prod%2Fush/lists"}