Awesome Go

nostromo

CategoryUtilities
SubcategoryUtilities
Stars150

CLI for building powerful aliases

About nostromo

This large README is shown as a plain-text preview. Read the full README at the source

[![CI](https://github.com/pokanop/nostromo/actions/workflows/ci.yml/badge.svg)](https://github.com/pokanop/nostromo/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/pokanop/nostromo)](https://goreportcard.com/report/github.com/pokanop/nostromo) [![Coveralls github](https://img.shields.io/coveralls/github/pokanop/nostromo)](https://coveralls.io/github/pokanop/nostromo) [![GitHub](https://img.shields.io/github/license/pokanop/nostromo)](https://github.com/pokanop/nostromo/blob/master/LICENSE) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)

<p align="center">
  <img src="images/mess-hall.png" alt="mess-hall">
</p>

<p align="left" style="margin: 12px 0px">
  <img src="images/nostromo-drop-ship.png" alt="nostromo">&nbsp;
  <img src="images/nostromo-logo.png" alt="nostromo" style="height: 32px">
</p>

`nostromo` is a CLI to rapidly build declarative aliases making multi-dimensional tools on the fly.

<p align="center">
  <img src="images/intro.gif" alt="intro" style="border-radius: 15px">
</p>

Managing aliases can be tedious and difficult to set up. `nostromo` makes this process easy and reliable. The tool adds shortcuts to your `.bashrc` / `.zshrc` that call into the `nostromo` binary. It reads and manages all aliases within its manifest. This is used to find and execute the actual command as well as swap any substitutions to simplify calls.

`nostromo` can help you build complex tools in a declarative way. Tools commonly allow you to run multi-level commands like `git rebase master branch` or `docker rmi b750fe78269d` which are clear to use. Imagine if you could wrap your aliases / commands / workflow into custom commands that describe things you do often. Well, now you can with nostromo. 🤓

With `nostromo` you can take aliases like these:

```sh
alias ios-build='pushd $IOS_REPO_PATH;xcodebuild -workspace Foo.xcworkspace -scheme foo_scheme'
alias ios-test='pushd $IOS_REPO_PATH;xcodebuild -workspace Foo.xcworkspace -scheme foo_test_scheme'
alias android-build='pushd $ANDROID_REPO_PATH;./gradlew build'
alias android-test='pushd $ANDROID_REPO_PATH;./gradlew test'
```

and turn them into declarative commands like this:

```sh
build ios
build android
test ios
test android
```

The possibilities are endless 🚀 and up to your imagination with the ability to compose commands as you see fit.

> Check out the [examples](https://github.com/pokanop/nostromo/tree/main/examples) folder for sample manifests with commands.

## <img align="left" src="images/sleep-pod.png" alt="sleep pod">&nbsp;Getting Started

### Prerequisites

- Works for MacOS and Linux with `bash`, `zsh`, `fish` and PowerShell (`pwsh`) shells
- Windows with PowerShell should work _but is untested_

### Installation

Every release ships binaries and packages for macOS, Linux and Windows on the [releases](https://github.com/pokanop/nostromo/releases) page. Pick your platform below.

#### macOS

Using `brew`:

```sh
brew install pokanop/pokanop/nostromo
```

#### Linux

Using `brew` (Linuxbrew):

```sh
brew install pokanop/pokanop/nostromo
```

Debian / Ubuntu: download the `.deb` for your architecture from the [latest release](https://github.com/pokanop/nostromo/releases/latest) and run:

```sh
sudo dpkg -i nostromo_<version>_amd64.deb
```

Fedora / RHEL / openSUSE: download the `.rpm` and run:

```sh
sudo rpm -i nostromo-<version>-1.x86_64.rpm
```

Alpine: download the `.apk` and run:

```sh
sudo apk add --allow-untrusted nostromo_<version>_x86_64.apk
```

Arch Linux (AUR, using `yay` or any AUR helper):

```sh
yay -S nostromo-bin
```

or download the `.pkg.tar.zst` from the release and run `sudo pacman -U nostromo-<version>-1-x86_64.pkg.tar.zst`.

Nix (NUR-style repository):

```sh
nix profile install github:pokanop/nur-packages#nostromo
```

Snap (classic confinement):

```sh
sudo snap install nostromo --classic
```

> `arm64` (`aarch64`) and `i386` (`i686`) variants of every Linux package are published alongside the `amd64` / `x86_64` ones.

#### Windows

Using `scoop`:

```powershell
scoop bucket add pokanop https://github.com/pokanop/scoop-bucket
scoop install nostromo
```

Using `winget`:

```powershell
winget install pokanop.nostromo
```

#### From source

Using `go install` (any platform with Go 1.25+):

```sh
go install github.com/pokanop/nostromo@latest
```

> The AUR, Nix, Snap, Scoop and Winget channels are published automatically from each release and become available once their package repositories have been set up (see [#64](https://github.com/pokanop/nostromo/issues/64)). Until then, grab the archive or package for your platform from the [releases](https://github.com/pokanop/nostromo/releases) page.

### Initialization

This command will initialize `nostromo` and create a manifest under `~/.nostromo`:

```sh
nostromo init
```

To customize the directory (and change it from `~/.nostromo`), set the `NOSTROMO_HOME` environment variable to a location of your choosing.

The first time a config is created in an interactive terminal, `nostromo` greets you with an ascii-art banner. It is never printed when output is piped or on subsequent runs; pass `--no-banner` to keep scripted installs quiet. You can bring it back any time with `nostromo version --banner`.

> With every update, it's a good idea to run `nostromo init` to ensure any manifest changes are migrated and commands continue to work. `nostromo` will attempt to perform any migrations as well at this time to files and folders so 🤞

The quickest way to populate your commands database is using the `dock` feature:

```sh
nostromo dock <source>
```

where `source` can be any local or remote file sources. See [Dock, undock and sync](https://nostromo.sh/concepts/distributed-manifests/) for more details.

To destroy the core manifest and start over you can always run:

```sh
nostromo destroy
```

Backups of manifests are automatically taken to prevent data loss in case of shenanigans gone wrong. These are located under `${NOSTROMO_HOME}/cargo`. The maximum number of backups can be configured with the `backupCount` setting.

```sh
nostromo set backupCount 10
```

### Settings

Global settings live in the **spaceport** (`~/.nostromo/spaceport.yaml`), not in any manifest, so they apply to every docked manifest. Use `nostromo set` and `nostromo get` to manage them:

| Key           | Values                                    | Default       |
| ------------- | ----------------------------------------- | ------------- |
| `verbose`     | `true`, `false`                           | `false`       |
| `aliasesOnly` | `true`, `false`                           | `false`       |
| `mode`        | `concatenate`, `independent`, `exclusive` | `concatenate` |
| `backupCount` | number                                    | `10`          |
| `theme`       | `default`, `grayscale`, `emoji`           | `emoji`       |

```yaml
# ~/.nostromo/spaceport.yaml
sequence:
  - manifest
config:
  verbose: false
  aliasesOnly: false
  mode: 0
  backupCount: 10
  theme: 2
```

> Older versions stored a `config` block in the core manifest. Running any command (or `nostromo init`) lifts those settings into the spaceport once; config blocks in docked manifests are ignored.

> Manifest and spaceport keys are written in camelCase (`keyPath`, `aliasOnly`, `backupCount`). Files written by older versions used lowercase keys (`keypath`, `aliasonly`, `backupcount`); these still load and are rewritten in the new format (with a backup in `~/.nostromo/cargo`) the first time `nostromo` runs.

## <img align="left" src="images/derelict-ship.png" alt="derelict ship">&nbsp;Key Features

- [Simplified alias management](#managing-aliases)
- [Scoped commands and substitutions](#scoped-commands-and-substitutions)
- [Build complex command trees](#complex-command-tree)
- [Shell completion support](#shell-completion)
- [Execute code snippets](#execute-code-snippets)
- [Distributed manifests](#distributed-manifests)
- [Powerful tree management](#command-tree-management)
- [Web UI](#web-ui)
- [Neato themes](#themes)

### Managing Aliases

Aliases to commands is one of the core features provided by `nostromo`. Instead of constantly updating shell profiles manually, `nostromo` will automatically keep it updated with the latest additions.

> Given that `nostromo` is not a shell command there are some things to note on how it makes its magic:
>
> - _Commands are generated by `nostromo` and executed using the `eval` method in a shell function._
> - _Commands and changes will be available immediately since `nostromo` reloads completions automatically_
>
> If you want create boring standard **shell aliases** you can do that with an additional flag or a config setting described below.

To add an alias (or command in `nostromo` parlance), simply run:

```sh
nostromo add cmd foo "echo bar"
```

And just like that you can now run `foo` like any other alias.

Descriptions for your commands can easily be added as well:

```sh
nostromo add cmd foo "echo bar" -d "My magical foo command that prints bar"
```

> Your descriptions will show up in the shell when autocompleting!

#### Interactive Mode

You can also add commands and substitutions **interactively** by using just `nostromo add` without any arguments. This command will walk through prompts to guide adding new commands easily.

<p align="center">
  <img src="images/interactive.gif" alt="interactive" style="border-radius: 15px">
</p>

#### Keypaths

`nostromo` uses the concept of keypaths to simplify building commands and accessing the command tree. A keypath is simply a `.` delimited string that represents the path to the command.

For example:

```sh
nostromo add cmd foo.bar.baz 'echo hello'
```

will build the command tree for `foo` 👉 `bar` 👉 `baz` such that any of these commands are now valid (of course the first two do nothing _yet_ 😉):

```sh
foo
foo bar
foo bar baz
```

where the last one will execute the `echo` command.

You can compose several commands together by adding commands at any node of the keypath. The **default** behavior is to concatenate the commands together as you walk the tree. Targeted use of `;` or `&&` can allow for running multiple commands together instead of concatenating. More easily, you can change the command `mode` for any of the commands to do this for you automatically. More info on this later.

#### Finding Commands

Once the tree grows it can be hard to remember what lives where. Use `find` with a keypath to get the details of a single command along with its substitutions:

```sh
nostromo find foo.bar.baz -v
+--------------+-------------+
| keypath      | foo.bar.baz |
| alias        | baz         |
| command      | echo hello  |
| code         | false       |
| mode         | concatenate |
| aliasOnly    | false       |
| disabled     | false       |
| manifest     | manifest    |
+--------------+-------------+
```

Any other argument searches every docked manifest for commands whose name, alias or keypath contain it, as well as matching substitutions, e.g. `nostromo find bar` matches `foo.bar` and `foo.bar.baz`. Add `-v` to print tables including the manifest each match belongs to. Use `--exact` to only accept an exact keypath (handy in scripts since it fails when the command is missing) or `--all` to list every match even if the argument happens to be a keypath.

#### Shell Aliases

`nostromo` allows users to manage shell aliases. By default, all commands are designed to execute the binary and resolve a command to be evaluated in the shell. This allows you to run those declarative commands easily like `foo bar baz` in the shell. It only creates an alias as a shell function for the root command `foo` and passes the remaining arguments to `nostromo eval` to evaluate the command tree. The result of that is executed with `eval` in the shell. Standard shell aliases **do not** get this behavior.

> The use of standard shell aliases provides limited benefit if you only want single tiered aliases. Additionally, commands persist in the shell since they are evaluated (i.e., changing directories via `cd`).

There are two methods for adding aliases to your shell profile that are considered standard aliases:

- Use the `--alias-only` or `-a` flag when using `nostromo add cmd`
- Set the `aliasesOnly` config setting to affect all command additions

For example, you can see both methods here:

```sh
nostromo add cmd foo.bar.baz "cd /tmp" --alias-only

nostromo set aliasesOnly true
nostromo add cmd foo.bar.baz "cd /tmp"
```

Adding a standard alias will produce this line that gets sourced:

```sh
alias foo.bar.baz='cd /tmp'
```

instead of a `nostromo` command which adds a shell function:

```sh
foo() { eval $(nostromo eval foo "$*") }
```

> Notice how the keypath has no affect in building a command tree when using the **alias only** feature. Standard shell aliases can only be root level commands.

### Scoped Commands And Substitutions

Scope affects a tree of commands such that a parent scope is prepended first and then each command in the keypath to the root. If a command is run as follows:

```sh
foo bar baz
```

then the command associated with `foo` is concatenated first, then `bar`, and finally `baz`. So if these commands were configured like this:

```sh
nostromo add cmd foo 'echo oof'
nostromo add cmd foo.bar 'rab'
nostromo add cmd foo.bar.baz 'zab'
```

then the actual execution would result in:

```sh
echo oof rab zab
```

> Standard behavior is to `concatenate` but you can easily change this with the `mode` flag when using `add` or globally. More information under Execution Modes.

#### Substitutions

`nostromo` also provides the ability to add substitutions at each one of these scopes in the command tree. So if you want to shorten common strings that are otherwise long into substitutions, you can attach them to a parent scope and `nostromo` will replace them at execution time for all instances.

A substitution can be added with:

```sh
nostromo add sub foo.bar //some/long/string sls
```

Subsequent calls to `foo bar` would replace the subs before running. This command:

```sh
foo bar baz sls
```

would finally result in the following since the substitution is in scope:

```sh
foo bar baz //some/long/string
```

### Complex Command Tree

Given features like **keypaths** and **scope** you can build a complex set of commands and effectively your own tool 🤯 that performs additive functionality with each command node.

You can get a quick snapshot of the command tree using:

```sh
nostromo show
```

With nostromo, you can also visualize the command tree (or manifest) in several other ways including as `json`, `yaml` and a tree itself.

<p align="center">
  <img src="images/tree.gif" alt="tree" style="border-radius: 15px">
</p>

Setting the `verbose` config setting prints more detailed information as well for all commands.

<p align="center">
  <img src="images/verbose.gif" alt="verbose" style="border-radius: 15px">
</p>

#### Execution Modes

A command's mode indicates how it will be executed. By default, `nostromo` concatenates parent and child commands along the tree. There are 3 modes available to commands:

```sh
  concatenate  Concatenate this command with subcommands exactly as defined
  independent  Execute this command with subcommands using ';' to separate
  exclusive    Execute this and only this command ignoring parent commands
```

The mode can be set when adding a command with the `-m` or `--mode` flag:

```sh
nostromo add cmd foo.bar.baz -m exclusive "echo baz"
```

A global setting can also be set to change the mode from the default `concatenate` with:

```sh
nostromo set mode independent
```

> All subsequent commands would inherit the above mode if set.

#### Platform Specific Commands

Commands can be limited to specific platforms, handy when the same manifest is shared between machines running different operating systems. Pass a comma separated list of Go OS names (`linux`, `darwin`, `windows`, …) or `os/arch` pairs (`linux/arm64`) with the `-p` or `--platforms` flag:

```sh
nostromo add cmd copy.ssh "cat ~/.ssh/id_rsa.pub | pbcopy" --platforms darwin
nostromo add cmd copy.ssh "cat ~/.ssh/id_rsa.pub | xclip -selection clipboard" --platforms linux/amd64,linux/arm64
```

A command with no platforms is available everywhere. Sub commands inherit the restriction of their parents, so limiting `copy` limits `copy.ssh` as well. Commands that are unavailable on the current platform are skipped when generating shell aliases, functions and completions, `nostromo eval` reports `command copy.ssh is not available on linux/amd64`, and `show` and `find` mark them with an `unavailable on <platform>` note. Platform names are validated, so typos like `macos` are rejected.

Change or clear the platforms of an existing command with `nostromo update`. Platforms are kept if the flag is omitted:

```sh
nostromo update copy.ssh --platforms linux,darwin
nostromo update copy.ssh --platforms ""
```

> Set `NOSTROMO_PLATFORM=windows` (or `linux/arm64`) to preview how a manifest behaves on another platform.

#### Environment Variables

Commands can export environment variables before they run, inspired by [Taskfile](https://taskfile.dev/usage/#environment-variables). Pass `KEY=VALUE` pairs with the `-e` or `--env` flag and `.env` files with `--dotenv`, both may be repeated:

```sh
nostromo add cmd app "cd ~/src/app" --dotenv ~/src/app/.env --env APP_ENV=dev
nostromo add cmd app.serve "make serve" --env APP_ENV=prod --env 'GOBIN=$PWD/bin:$PATH'
```

Environment is inherited down the command tree and merged root to leaf, so `app serve` exports everything from `~/src/app/.env`, then `APP_ENV=prod` since a child overrides its parents. On each command the `.env` files load first and the `env` values override them. Values may reference other variables with normal shell syntax like `$HOME` or `${PATH}`, they are quoted for the shell running the command and are exported with `export` for `bash` and `zsh`, `set -gx` for `fish` and `$env:NAME = ...` for PowerShell.

`.env` files are parsed by `nostromo` rather than sourced by the shell so the same file works everywhere. They support `KEY=VALUE` lines, an optional `export` prefix, `#` comments, and single or double quoted values, where `~` and `$VARS` in the file paths are expanded. A file that is missing or malformed is reported as a warning and skipped when the command runs.

The stored values appear in the `env` and `dotenv` fields of `show -v` and `find -v`, and `nostromo env` prints the effective merged environment of a keypath, add `-v` to see where each value came from or `-s <shell>` to print the export statements:

```sh
nostromo env app.serve
nostromo env app.serve -v
nostromo env app.serve -s fish
```

Change the environment of an existing command with `nostromo update`. Vars are merged, `--unset-env` removes them, and `--dotenv` replaces the list of files, pass an empty path to clear it:

```sh
nostromo update app.serve --env APP_ENV=staging --unset-env GOBIN
nostromo update app --dotenv ~/src/app/.env --dotenv ~/src/app/.env.local
nostromo update app --dotenv ""
```

In a manifest the fields look like this:

```yaml
commands:
  app:
    keyPath: app
    name: cd ~/src/app
    alias: app
    env:
      APP_ENV: dev
    dotenv:
      - ~/src/app/.env
    commands:
      serve:
        keyPath: app.serve
        name: make serve
        alias: serve
        env:
          APP_ENV: prod
          GOBIN: $PWD/bin:$PATH
```

> Environment is not supported for alias only commands since the shell runs them directly.

### Shell Completion

`nostromo` provides completion scripts to allow tab completion for `bash`, `zsh`, `fish` and PowerShell. `nostromo init` adds a `# nostromo [section begin]` … `# nostromo [section end]` block to the init files that already exist for these shells:

Frequently Asked Questions

What is nostromo?

nostromo is a Utilities library for the Go programming language. CLI for building powerful aliases

How do I install nostromo?

Install nostromo with the Go module system using `go get pokanop/nostromo`. Check the repository for the current installation instructions.

What category does nostromo belong to?

nostromo is listed under Utilities, specifically Utilities.

← Back to Utilities