nostromo
is a CLI to rapidly build declarative aliases making multi-dimensional tools on the fly.
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:
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:
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 folder for sample manifests with commands.
ย Getting Started
Prerequisites
- Works for MacOS and
bash
/zsh
shells (other combinations untested but may work)
Installation
Using brew
:
brew install pokanop/pokanop/nostromo
Using go get
:
go get -u github.com/pokanop/nostromo
Initialization
This command will initialize nostromo
and create a manifest under ~/.nostromo
:
nostromo init
To customize the directory (and change it from ~/.nostromo
), set the NOSTROMO_HOME
environment variable to a location of your choosing.
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:
nostromo dock <source>
where source
can be any local or remote file sources. See the Distributed Manifests section for more details.
To destroy the core manifest and start over you can always run:
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
manifest setting.
nostromo set backupCount 10
ย Key Features
- Simplified alias management
- Scoped commands and substitutions
- Build complex command trees
- Shell completion support
- Execute code snippets
- Distributed manifests
- Powerful tree management
- Neato 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 theeval
method in a shell function.- Commands and changes will be available immediately since
nostromo
reloads completions automaticallyIf 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:
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:
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.
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:
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 ๐):
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.
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 usingnostromo add cmd
- Set the
aliasesOnly
config setting to affect all command additions
For example, you can see both methods here:
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:
alias foo.bar.baz='cd /tmp'
instead of a nostromo
command which adds a shell function:
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:
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:
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:
echo oof rab zab
Standard behavior is to
concatenate
but you can easily change this with themode
flag when usingadd
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:
nostromo add sub foo.bar //some/long/string sls
Subsequent calls to foo bar
would replace the subs before running. This command:
foo bar baz sls
would finally result in the following since the substitution is in scope:
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:
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.
Setting the verbose
config setting prints more detailed information as well for all commands.
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:
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:
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:
nostromo set mode independent
All subsequent commands would inherit the above mode if set.
Shell Completion
nostromo
provides completion scripts to allow tab completion. This is added by default to your shell init file:
eval "$(nostromo completion)"
Even your commands added by nostromo
get the full red carpet treatment with shell completion. Be sure to add a description and tab completion will show hints at each junction of your command. Cool right! ๐
Execute Code Snippets
nostromo
provides the ability to supply code snippets in the following languages for execution, in lieu of the standard shell command:
ruby
- runs ruby interpreterpython
- runs python interpreterjs
- runs nodeperl
- runs perl interpreter
nostromo add cmd foo --code 'console.log("hello js")' --language js
For more complex snippets you can edit ~/.nostromo/ships/manifest.yaml
directly but multiline YAML must be escaped correctly to work.
Distributed Manifests
nostromo
now supports keeping multiple manifest sources ๐ช allowing you to organize and distribute your commands as you please. This feature enables synchronization functionality to get remote manifests from multiple data sources including:
- Local Files
- Git
- Mercurial
- HTTP
- Amazon S3
- Google GCS
Details on supported file formats and requirements can be found in the go-getter documentation as
nostromo
uses that for downloading files
Configs can be found in the ~/.nostromo/ships
folder. The core manifest is named manifest.yaml
.
You can add as many additional manifests in the same folder and nostromo
will parse and aggregate all the commands, useful for organizations wanting to build their own command suite.
To add or dock manifests, use the following:
nostromo dock <source>...
And thatโs it! Your commands will now incorporate the new manifest.
To update docked manifests to the latest versions (omit sources to update all manifests), just run:
nostromo sync <name>...
nostromo
syncs manifests using version information in the manifest. It will only update if the version identifier is different. To force update a manifest, run:
nostromo sync -f <name>...
If youโre tired of someone elseโs manifest or it just isnโt making you happy โน๏ธ then just undock it with:
nostromo undock <name>
Command Tree Management
Moving and copying command subtrees can be done easily using nostromo
as well to avoid manual copy pasta with yaml. If you want to move command nodes around just use:
nostromo move cmd <source> <destination>
where the source and destinations are expected to be key paths like foo.bar
.
You can rename a node with:
nostromo rename cmd <source> <name>
Next up, you might want to copy entire nodes around, which can also be done between manifests using copy
. Again use key paths for source
and destination
and nostromo
will attempt to replicate the branch to the new location.
nostromo copy cmd <source> <destination>
So youโve created an awesome suite of commands and you like to share, am I right? Well nostromo
makes it super easy to create manifests with any set of your commands from the tree using the detach
command. It lets you slice and dice your manifests by extracting out a command node into a new manifest.
nostromo detach <name> <key.path>...
By default, this removes the command nodes from the manifest but can be kept intact as well with the -k
option. Additionally, detaching any command nodes from a docked manifest may have unwanted side effects when running nostromo sync
again since the commands will likely be added back from the original source.
Since nostromo
updates manifests if the identifier is unique, there might be times you want to update the yaml
files manually for whatever reason. In this case you can run the handy uuidgen
command to update the identifier so you can push the manifest to others:
nostromo uuidgen <name>
Themes
nostromo
now supports themes to make it look even more neat. Thereโs 3 themes currently which can be set with:
nostromo set theme <name>
where valid themes include:
default
: The basic theme and previous defaultgrayscale
: Gray colored things are sometimes niceemoji
: The new default obviously
Enjoy!
๐ณ๐๐ฅ๐๐๐๐๐๐ต๐๐ป๐๐๐ฅ๐ก๐๐๐ญ๐๐๐๐๐๐๐ผ๐๐ฉ๐๐ฅ
ย Credits
- This tool was bootstrapped using cobra.
- Colored logging provided by aurora.
- Fan art supplied by Ian Stewart.
- Gopher artwork by @egonelbre and original by Renee French.
- File downloader using go-getter
ย Contributing
Contributions are what makes the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
ย License
Distributed under the MIT License.