├── flake.lock ├── flake.nix ├── README.md └── hover.sh /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-parts": { 4 | "inputs": { 5 | "nixpkgs-lib": [ 6 | "nixpkgs" 7 | ] 8 | }, 9 | "locked": { 10 | "lastModified": 1698579227, 11 | "narHash": "sha256-KVWjFZky+gRuWennKsbo6cWyo7c/z/VgCte5pR9pEKg=", 12 | "owner": "hercules-ci", 13 | "repo": "flake-parts", 14 | "rev": "f76e870d64779109e41370848074ac4eaa1606ec", 15 | "type": "github" 16 | }, 17 | "original": { 18 | "owner": "hercules-ci", 19 | "repo": "flake-parts", 20 | "type": "github" 21 | } 22 | }, 23 | "nixpkgs": { 24 | "locked": { 25 | "lastModified": 1669791787, 26 | "narHash": "sha256-KBfoA2fOI5+wCrm7PR+j7jHqXeTkVRPQ0m5fcKchyuU=", 27 | "owner": "NixOS", 28 | "repo": "nixpkgs", 29 | "rev": "e76c78d20685a043d23f5f9e0ccd2203997f1fb1", 30 | "type": "github" 31 | }, 32 | "original": { 33 | "owner": "NixOS", 34 | "ref": "nixos-unstable", 35 | "repo": "nixpkgs", 36 | "type": "github" 37 | } 38 | }, 39 | "root": { 40 | "inputs": { 41 | "flake-parts": "flake-parts", 42 | "nixpkgs": "nixpkgs" 43 | } 44 | } 45 | }, 46 | "root": "root", 47 | "version": 7 48 | } 49 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Hover - Home overlay"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; 6 | flake-parts = { 7 | url = "github:hercules-ci/flake-parts"; 8 | inputs.nixpkgs-lib.follows = "nixpkgs"; 9 | }; 10 | }; 11 | 12 | outputs = inputs@{ self, nixpkgs, flake-parts }: 13 | flake-parts.lib.mkFlake { inherit inputs; } { 14 | systems = [ "x86_64-linux" "aarch64-linux" ]; 15 | perSystem = { config, self', inputs', pkgs, system, ... }: { 16 | packages.default = let 17 | runtimeInputs = with pkgs; lib.makeBinPath [ 18 | coreutils 19 | dua 20 | fuse-overlayfs 21 | ncurses 22 | ]; 23 | in pkgs.writeShellScriptBin "hover" '' 24 | export HOVER_ORIGINAL_PATH="$PATH" 25 | export PATH="${runtimeInputs}:$PATH" 26 | ${builtins.readFile ./hover.sh} 27 | ''; 28 | }; 29 | 30 | flake = { 31 | nixosModules.default = { pkgs, ... }: { 32 | programs.fuse.userAllowOther = true; 33 | environment.systemPackages = [ self.packages.${pkgs.system}.default ]; 34 | }; 35 | 36 | homeManagerModules.starship = { ... }: { 37 | programs.starship.settings = { 38 | custom.hover = { 39 | when = "[ ! -z \${HOVER_HOME+x} ]"; 40 | symbol = "🏂"; 41 | style = "bold blue"; 42 | format = "via [$symbol hover ]($style)"; 43 | }; 44 | }; 45 | }; 46 | }; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hover - Home overlay 2 | 3 | Tired of programs you don't even intend on keeping vomiting all over your home directory? 4 | Frequent user of `cd $(mktemp -d)`? Read on. 5 | 6 | ## Intro 7 | 8 | Hover creates an overlay directory for your `$HOME`. 9 | The files in your original `$HOME` are all there, but any changes such as 10 | modifying, adding or removing files are lost after exiting Hover. 11 | 12 | ## Installation 13 | 14 | Hover is distributed as a Nix flake. 15 | 16 | Install it into your profile: 17 | ```console 18 | $ nix profile install github:max-privatevoid/hover 19 | ``` 20 | 21 | Try it in a temporary shell 22 | (it won't create any files in your home directory, promise) 23 | ``` 24 | $ nix shell github:max-privatevoid/hover 25 | ``` 26 | 27 | To be able to use this utiliy as non-root, `user_allow_other` must be added to `/etc/fuse.conf`. 28 | 29 | On **NixOS** this can be done using the option `programs.fuse.userAllowOther = true`. 30 | 31 | ## Usage 32 | 33 | Hover has a couple of subcommands, listed here. 34 | 35 | If you are anywhere inside your home directory when executing Hover, 36 | you will automatically be `cd`'d to the same place within the overlay. 37 | 38 | ### `hover shell` 39 | 40 | Runs your `$SHELL` in a Hover environment. Can also be used by running `hover` with no arguments. 41 | 42 | ### `hover run` 43 | 44 | Runs the specified program, as shown in the example below. 45 | Keep in mind that environment variables on the command line are parsed by the 46 | outer shell, so `hover run echo $HOME` will echo your regular home directory. 47 | 48 | ```console 49 | $ hover run printenv HOME 50 | /tmp/tmp.oqwgw6BpC7/home 51 | hover: cleaning up 52 | hover: space consumed by temporary home directory: 53 | 0 B /tmp/tmp.oqwgw6BpC7/.upper 54 | ``` 55 | 56 | ### `hover nix` 57 | 58 | A convenient shortcut for `hover run nix`, so you can do: 59 | ```console 60 | $ hover nix shell github:some-person/tool-you-want-to-test 61 | ``` 62 | 63 | ## Modules 64 | 65 | Hover also provides two modules: 66 | - `nixosModules.default` which adds hover to the system packages and enables `programs.fuse.userAllowOthers`. 67 | - `homeManagerModules.starship` which adds integration with the [starship](https://starship.rs/) prompt. 68 | -------------------------------------------------------------------------------- /hover.sh: -------------------------------------------------------------------------------- 1 | export HOVER_ORIGINAL_HOME="$HOME" 2 | export HOVER_OVERLAY_DIR="$(mktemp -d)" 3 | mkdir $HOVER_OVERLAY_DIR/{home,.upper,.work} 4 | export HOVER_HOME=$HOVER_OVERLAY_DIR/home 5 | 6 | show_help() { 7 | local b=$(tput bold) 8 | local u=$(tput smul) 9 | local n=$(tput sgr0) 10 | echo "Hover - Temporary home directories, 11 | Usage: hover [shell | run ${u}arguments${n} | nix ${u}arguments${n}] 12 | 13 | Options: 14 | • shell 15 | Runs your ${b}\$SHELL${n} in a Hover environment. 16 | Can also be used by running hover with no arguments. 17 | 18 | • run 19 | Runs the specified program. Keep in mind that environment variables on the command line 20 | are parsed by the outer shell, so '${b}hover run echo \$HOME${n}' will echo your regular home directory. 21 | 22 | • nix 23 | A convenient shortcut for '${u}hover run nix${n}', so you can do: 24 | '${b}hover nix shell github:some-person/tool-you-want-to-test${n}' 25 | " 26 | } 27 | 28 | tmp_cleanup() { 29 | # be careful not to rm -rf the original home directory 30 | rmdir $HOVER_OVERLAY_DIR/home 31 | 32 | rm -rf $HOVER_OVERLAY_DIR/.upper 33 | rm -rf $HOVER_OVERLAY_DIR/.work 34 | rmdir $HOVER_OVERLAY_DIR 35 | } 36 | 37 | hover_cleanup() { 38 | echo hover: cleaning up 39 | if ! umount $HOVER_HOME; then 40 | echo "hover: failed to unmount $HOVER_HOME" 41 | exit 1 42 | fi 43 | 44 | echo "hover: space consumed by temporary home directory:" 45 | dua -Ax $HOVER_OVERLAY_DIR/.upper 46 | 47 | tmp_cleanup 48 | } 49 | 50 | hover_execute() { 51 | if ! fuse-overlayfs -o allow_root,lowerdir=$HOVER_ORIGINAL_HOME,workdir=$HOVER_OVERLAY_DIR/.work,upperdir=$HOVER_OVERLAY_DIR/.upper $HOVER_HOME; then 52 | echo "hover: failed to mount overlay" 53 | exit 1 54 | fi 55 | trap hover_cleanup EXIT 56 | HOVER_SAVED_APP_PATH="$PATH" 57 | export HOME=$HOVER_HOME 58 | export PATH="$HOVER_ORIGINAL_PATH" 59 | # change directory to temp home if already in $HOME outside 60 | HOVER_SAVED_PWD="$PWD" 61 | if [[ "$PWD" == "$HOVER_ORIGINAL_HOME" || "$PWD" == "$HOVER_ORIGINAL_HOME/"* ]]; then 62 | HOVER_PWD="${HOVER_HOME}${PWD#${HOVER_ORIGINAL_HOME}}" 63 | cd "$HOVER_PWD" 64 | fi 65 | "$@" 66 | cd "$HOVER_SAVED_PWD" 67 | export PATH="$HOVER_SAVED_APP_PATH" 68 | export HOME=$HOVER_ORIGINAL_HOME 69 | } 70 | 71 | cmd="$1" 72 | shift 73 | case "$cmd" in 74 | nix) hover_execute nix "$@";; 75 | ""|shell) hover_execute "$SHELL" "$@";; 76 | run) hover_execute "$@";; 77 | -h|--help) show_help & tmp_cleanup;; 78 | *) 79 | echo "hover: unknown operation: \"$cmd\"" 80 | tmp_cleanup 81 | exit 1;; 82 | esac 83 | --------------------------------------------------------------------------------