Skip to content
Andy Kipp edited this page Mar 17, 2021 · 55 revisions

Welcome to xxh family

Pronounce

Pronounce of xxh is [ˈeks ˈeks aitch].

The ideas behind xxh

You stuffed command shell with aliases, tools and colors but you lose it all when using ssh. The mission of xxh is to bring your favorite shell wherever you go through the ssh without root access and system installations.

To do it carefully and secure we have key ideas:

Portable. Preparing portable shells and plugins occurs locally and then xxh uploads the result to host. No installations or root access on the host required. The security and careful about environment on the host are behind it.

Careful. No blindfold copying config files from local to remote host. Following the privacy and repeatability reasons the better way is to fork the xxh plugin or shell example and pack your config to it.

Hermetic. If you delete ~/.xxh directory from the remote host then xxh has never been on the host. By default your home is .xxh directory and you can choose the hermetic level of your xxh session.

Be open and fork-ready. Every repo could be forked, customized and reused without waiting for package management system, xxh releases or any third party. Currently supported five shells and the count could be grow by community.

Do more. The xxh packages are not only about shells. Any type of tool or code could be behind entrypoint. If you want to run browsh on the remote host just put it as entrypoint.

How it works

Simple answer

When you run xxh myhost command xxh downloads portable shell and store locally to future use. Then if it needed xxh upload the portable shell, init scripts and plugins to the host. Finally xxh make ssh connection to the host and run portable shell without any system installs, root access and affection on the target host.

Detailed workflow with code

When you run xxh myhost +s zsh:

  1. The repo https://github.com/xxh/xxh-shell-zsh will be cloned to local ~/.xxh/shells/xxh-shell-zsh directory and the portable zsh shell will be built in the ~/.xxh/shells/xxh-shell-zsh/build directory. Then xxh upload the build directory to myhost:/home/user/.xxh (by default).
  2. In the build directory there is entrypoint.sh which is the start script for xxh shell.
  3. The entrypoint.sh load xxh prerun plugins written on bash. Prerun plugins common used to load configs for third party tools and indifferent to the xxh shell.
  4. Then entrypoint.sh run xxh shell (zsh in this case) using zshrc file as initialization script.
  5. The zshrc script loads the xxh plugins for zsh.
  6. By default $HOME will be /home/user/.xxh directory to follow the hermetic idea and encourage the tools save the configs and cache in this directory.
  7. As result you'll be on the host in Zsh shell with loaded plugins without root access, installations and affection on the host.

Plugins

Plugin for xxh is the set of scripts which will be run on the host when you go using xxh. It could be tools, shell settings, aliases, environment variables, frameworks, extensions, color themes and everything you need.

There are shell and prerun plugins:

You can search xxh plugin on Github. Feel free to fork it.

Connection speed

The first connection takes time for downloading, building and uploading portable shell. It depends on portable shell size and internet connection speed: from your local host to github (common case) and from your local to the target host. But when xxh is installed on the host and you do just xxh myhost then it works as ordinary ssh connection speed plus speed of initializing the shell you used. You could monitor all process using +vv argument.

Seamless mode

When you run source xxh.**** myhost the script get the environment variables and bring it to the xxh session. For example if you are in Oh My Zsh with agnoster theme with (git docker ubuntu) plugins then command xxh +I xxh-plugin-zsh-ohmyzsh && source xxh.zsh myhost brings you to myhost with appropriate theme and plugins.

Watch seamless mode demo for zsh.

To use seamless mode on xxh AppImage run mv xxh.AppImage xxh && ./xxh ++extract-sourcing-files to extract xxh.*sh files to the current directory then run source xxh.zsh myhost command for seamless connecting.

Config file

To reusing arguments there is ~/.config/xxh/config.xxhc config file in YAML format. The path to the config could be modified by +xc argument.

Example:

hosts:
  ".*":                       # for all hosts
    +s: fish                    # use Fish shell

  myhost:                     # settings for myhost
    -p: 2222                    # set special port
    +s: zsh                     # use zsh shell                         
    +I:                         # install xxh packages (if not installed)
      - xxh-shell-zsh             # install portable Zsh
      - xxh-plugin-zsh-ohmyzsh    # install Oh My Zsh plugin for xxh
    +e:                         # set simple environment variables
      - ZSH_THEME="clean"         # set ohmyzsh theme
      - MYENV="hello world"       # another environment variable
    +hhh: "~"                   # set /home/user as home directory

  "company-.*":               # for all hosts by regex pattern
    +s: xonsh                     # use xonsh shell
    +hh: /tmp/.xxh                # use special xxh home directory
    +if:                          # force install xxh every time
    +hhr:                         # remove host xxh home after disconnect
    +I: xxh-plugin-prerun-core    # midnight commander (mc) config as prerun xxh plugin

The arguments will be automatically added when you run xxh myhost or xxh company-server1.

Packages for xxh

Install shells and plugins

To install a package from https://github.com/xxh/:

xxh +I xxh-shell-example

To install from github use just URL:

xxh +I https://github.com/xxh/xxh-shell-example
xxh +I https://github.com/xxh/xxh-shell-example/tree/mybranch

To install from any git repo use long url <shell name>+git+<url>:

xxh +I xxh-shell-example+git+https://github.com/xxh/xxh-shell-example
xxh +I xxh-shell-example+git+https://github.com/xxh/xxh-shell-example/tree/mybranch

To install from local path use <shell name>+path+</absolute/path/to/xxh-shell-example>

xxh +I xxh-shell-example+path+/home/user/my-xxh-dev/xxh-shell-example

Advanced

How to set /home/user as home on host

Add +hhh '~' argument to the command or to config.xxhc.

By default xxh uses hermetic environment where $HOME is /home/user/.xxh. When you add +hhh '~' argument you set $HOME to your ordinary user home directory on host. Note that XDG directories are still in /home/user/.xxh. This is semihermetic because any tools you use during xxh session that aren't support XDG can write to your home directory.

Finally when you don't need hermetization and you want to use xxh like ssh just add two arguments: +hhh '~' +hhx '~'. By this way you set the XDG directories to user home and any tools you use during ssh and xxh will have the same data, configs and cache.

The table shows an example:

Name xxh command User HOME XDG_CONFIG_HOME
hermetic xxh myhost /home/user/.xxh /home/user/.xxh/.config
semi-hermetic xxh myhost +hhh '~' /home/user /home/user/.xxh/.config
non-hermetic xxh myhost +hhh '~' +hhx '~' /home/user /home/user/.config

Using sudo

The easiest way to run sudo with xxh environment is to install xxh-plugin-prerun-core and run xxh-sudo.

If you need more environment variables than xxh sudo has or you need different add it to xxh sudo or write sudo command manually:

xxh-sudo "MYENV=hello" bash -c 'echo $MYENV && whoami'
sudo env "PATH=$PATH" "MYENV=hello" bash -c 'echo $MYENV && whoami'

Using xxh in xxh session

Install xxh-plugin-prerun-xxh before connect.

Target host is behind another host

Add ProxyCommand or ProxyJump to your ssh config as described and then do ordinary xxh host_internal.

Environment variables

Using arguments:

xxh myhost +e VAR_A=1 +e VAR_B=2 +e VAR_C=3

Using ~/.config/xxh/config.xxhc:

hosts:
  myhost:
    +e:
      - VAR_A=1
      - VAR_B=2
      - VAR_C=3

Development and contribution

The easiest way to debug shell and plugins

Clone the repos, modify and use +RI argument with path in xxh command:

mkdir /tmp/xxh-dev && cd /tmp/xxh-dev
git clone https://github.com/xxh/xxh-shell-bash
git clone https://github.com/xxh/xxh-plugin-bash-vim
# Modify files in /tmp/xxh-dev and connect with reinstall from path before connect:
xxh myhost +s bash +RI xxh-shell-bash+path+/tmp/xxh-dev/xxh-shell-bash +RI xxh-plugin-bash-vim+path+/tmp/xxh-dev/xxh-plugin-bash-vim

Don't forget about verbose mode: +v and +vv arguments.

If you haven't the host where you can test use xde.

Prerun plugins

Prerun plugin is a prerun.sh bash script. It could be created as separate xxh-plugin-prerun-<plugin> or be a part of xxh-plugin-<shell>-<plugin>. Prerun plugin script will be load on entrypoint stage before shell running. To understand how it works try to review the pinned plugins: core (xxh-sudo, xxh-screen), dotfiles, docker, python, xxh, vim.

Change plugin run order

If xxh-shell support pluginrc.* sorting (zsh example) add the prefix with number to the pluginrc.* or prerun.sh file. For example 090-pluginrc.zsh will be called before pluginrc.zsh but after 010-pluginrc.zsh. Don't forget make appropriate changes in plugin's build.sh.

New questions

Ask it here