Skip to content

Commit 37b355f

Browse files
Add optional Home Manager and selectable shell installation
1 parent fe4d2b2 commit 37b355f

9 files changed

Lines changed: 479 additions & 137 deletions

File tree

‎.github/workflows/check.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ jobs:
1010
- uses: cachix/install-nix-action@b85815f71a6de0ddee80b8a80a98d43f4bcc66c7
1111
- name: Test bootstrap safety
1212
run: |
13-
python3 -B -m unittest discover -s tests -v
13+
nix develop --command python3 -B -m unittest discover -s tests -v
1414
bash -n install.sh scripts/prerequisites.sh
15-
shellcheck install.sh scripts/prerequisites.sh
15+
nix develop --command shellcheck install.sh scripts/prerequisites.sh
1616
- name: Build example home without activation
1717
run: nix flake check

‎README.md‎

Lines changed: 96 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,127 @@
11
# Commander-os
22

3-
A portable Linux home environment built with Nix and Home Manager. This is an
4-
initial starter, not an operating-system image or a distribution installer.
3+
A Linux terminal environment with a guided installer. Choose **Home Manager** or
4+
**direct installation**, then choose **Fish, Bash, Zsh, or keep your current shell**.
5+
This is a starter project, not an operating system image.
56

6-
The default setup provides Fish, Starship, Neovim, fuzzy finding, directory
7-
navigation, and common CLI tools. Git and Lazygit are optional. It does not change
8-
your bootloader, desktop or backup services. With Fish enabled, activation offers to make Fish
9-
your login shell. Prerequisites may be installed through your package manager.
10-
11-
## Get started
12-
13-
Run the guided installer as your normal user:
7+
## Install
148

159
```sh
1610
git clone https://github.com/Commanderx-code/Commander-os.git
1711
cd Commander-os
1812
./install.sh --apply
1913
```
2014

21-
You can also download and extract this repository using GitHub's **Code →
22-
Download ZIP** button if Git is not installed. Open a terminal in the extracted
23-
folder and run `bash install.sh --apply`.
24-
25-
The script detects missing Python 3, Git, curl and xz, and offers to install them
26-
using apt, dnf or pacman. It shows the package list and asks before using sudo.
27-
On Arch, it uses the existing package database; if installation fails due to stale
28-
mirrors, perform your normal full system update before retrying.
15+
Without Git, download and extract **Code → Download ZIP** on GitHub, then run
16+
`bash install.sh --apply` from the extracted folder. Run as your normal user,
17+
without sudo; the installer requests elevated access only where needed.
18+
19+
The installer asks which installation mode and shell you want before installing
20+
prerequisites. A new configuration defaults to Fish; existing settings are reused
21+
unless you select another shell. It shows a plan and asks for `APPLY` before
22+
activating or writing your shell configuration. Log out and back in after
23+
accepting a login-shell change. Terminal profiles set to run Bash explicitly
24+
must be changed to use the account's default shell.
25+
26+
| Mode | Installation and updates | Configuration recovery |
27+
| --- | --- | --- |
28+
| Home Manager | Installs Nix if needed; pinned packages from `flake.lock` | Home Manager generations and backups of conflicting files |
29+
| Direct | Uses apt, dnf, or pacman; Starship's official installer if needed | Timestamped copies of changed configuration files |
30+
31+
Both modes provide CLI tools, Starship, zoxide, fzf and optional Neovim. Shell
32+
configuration follows your selected shell. Direct development mode installs Git;
33+
Lazygit is currently included only in Home Manager development mode. Direct mode
34+
preserves any existing Neovim configuration. Package versions follow the distro
35+
in direct mode. Home Manager keeps all three supported shell executables installed
36+
so declining a subsequent shell change does not remove your existing login shell.
37+
38+
Direct mode never installs Nix or Home Manager. It refuses an existing Home
39+
Manager profile or symlink-managed target configuration; test it in a separate
40+
account or VM instead of mixing managers. Keeping the current shell skips shell
41+
configuration and login-shell changes; it still installs selected tools. Neither
42+
mode configures your desktop, bootloader or backup services.
43+
44+
## Settings and previews
45+
46+
Settings live outside Git at `~/.config/commander-os/machine.json` (respecting
47+
`XDG_CONFIG_HOME`). The `shell` field accepts `fish`, `bash`, `zsh`, or `keep`.
48+
`features.neovim` and `features.development` control optional tools. Older settings
49+
using `features.fish` remain supported; an explicit `shell` takes precedence.
2950

30-
If Nix is missing, the script offers to download and run the
31-
[official Nix installer](https://nixos.org/download/), then loads Nix into the
32-
current process and continues. Automatic Nix installation supports systemd Linux
33-
with SELinux disabled. Existing broken Nix installations and unsupported systems
34-
stop with guidance instead of modifying the host. Home Manager needs no separate
35-
installation: Nix builds it along with the selected tools.
36-
37-
Settings are created at `~/.config/commander-os/machine.json` (or under your
38-
`XDG_CONFIG_HOME`). Defaults come from your current account. Edit `fish`, `neovim`
39-
and `development` to select features. Use `./install.sh --init` to create settings
40-
before building. Never run the whole script with sudo.
51+
```sh
52+
# Create settings without a Home Manager build:
53+
./install.sh --init --backend home-manager --shell fish
4154

42-
To prepare dependencies and build without activation, run `./install.sh`.
43-
For a preview that must not install prerequisites, use `./install.sh --no-install`.
44-
Package installation, Nix installation, and activation each explain their changes
45-
before asking for confirmation. Declining stops that stage.
55+
# Build a Home Manager preview:
56+
./install.sh --backend home-manager --shell bash
4657

47-
Inspect the printed `home-files` directory to see the generated configuration.
48-
When ready:
58+
# Show the direct-install plan without installing its tools or writing shell files:
59+
./install.sh --backend native --shell zsh
4960

50-
```sh
51-
./install.sh --apply
61+
# Apply direct mode:
62+
./install.sh --apply --backend native --shell fish
5263
```
5364

54-
This builds again, then requires you to type `APPLY`. It replaces any existing
55-
standalone Home Manager profile for this account. Try it in a separate account
56-
or VM first if you already use Home Manager. Unmanaged conflicting files are
57-
backed up with a unique `.commander-os-…` suffix; Home Manager performs its own
58-
collision checks. A build preview does not perform those activation checks.
59-
After activation, accept the default **Y** at the Fish login-shell prompt.
60-
The installer verifies Fish, registers its stable Nix profile path in `/etc/shells`,
61-
and uses `sudo chsh` to set it for your account. Log out of the desktop and back
62-
in for new terminals to inherit it. Run `fish` to try it immediately. A terminal
63-
profile configured to run Bash explicitly must be changed to use the default shell.
64-
Bash is only used to launch the installer on a fresh system; your interactive
65-
configuration, prompt, fzf and zoxide integrations target Fish.
65+
Missing Python may be installed after confirmation, even for a preview. Use
66+
`--no-install` to prohibit dependency installation. Explicit `--backend` selects
67+
a mode without a menu; `--shell` selects and saves a shell choice. Unknown command
68+
arguments fail before dependency installation.
6669

67-
## Privacy and reproducibility
70+
Home Manager mode uses an explicit source-file allowlist and supplies validated
71+
machine settings in a temporary build tree. You do not need to track personal
72+
settings in Git. Nix stores usernames and home paths in its normally readable
73+
store: never put secrets in Nix settings. Preserve `home.stateVersion` on updates.
6874

69-
Machine settings live outside the checkout. The installer copies only the flake,
70-
lock file, example settings and modules into a temporary build tree, then adds
71-
validated machine settings. This avoids Git's untracked-file filtering without
72-
requiring personal settings in commits. Nix stores usernames and home paths in
73-
its normally readable store: **never put secrets in Nix configuration**.
75+
## System prerequisites
7476

75-
The example account is only for validation. Use the installer for your account;
76-
do not directly activate the flake's example configuration. The tracked lock
77-
file pins Nixpkgs and Home Manager. Preserve `home.stateVersion` when upgrading.
77+
The bootstrap supports apt, dnf and pacman. Automatic Nix installation uses the
78+
[official Nix installer](https://nixos.org/download/) and requires systemd Linux
79+
with SELinux disabled. Existing incomplete Nix installations stop with guidance.
80+
Direct mode does not have that Nix requirement. On Arch, package installation uses
81+
the existing package database; do your normal full system update if it is stale.
7882

79-
## Updates and rollback
83+
Direct mode uses the [official Starship installer](https://starship.rs/guide/)
84+
for a missing Starship executable and places it in `~/.local/bin`. Downloads and
85+
package installation happen only after the displayed installation plan is accepted.
8086

81-
Pull source updates and preview before applying:
87+
## Updates and recovery
8288

8389
```sh
8490
git pull --ff-only
85-
./install.sh
8691
./install.sh --apply
8792
```
8893

89-
Maintainers can update dependencies with `nix flake update`, then run the checks
90-
below before committing the changed lock file.
91-
92-
Before replacing an existing profile, record `home-manager generations` and keep
93-
your old configuration checkout. To roll back, find the previous generation
94-
using `home-manager generations` and run its `/nix/store/…-home-manager-generation/activate`
95-
script. Then restore any unmanaged files from their `.commander-os-…` backups as
96-
needed. Generation rollback does not automatically restore those backup files.
97-
Before uninstalling or disabling Fish, change your login shell back using
98-
`chsh -s /bin/bash` (or the path saved in
99-
`~/.local/state/commander-os/previous-shell.txt`). The Fish login shell relies on
100-
the Home Manager profile remaining installed. Generation rollback does not undo
101-
`chsh` or the `/etc/shells` entry.
102-
On a first installation there may be no previous generation; use
103-
`home-manager uninstall`, inspect the affected files, and restore the backups.
104-
105-
See the [Home Manager manual](https://nix-community.github.io/home-manager/) for
106-
profile management. Avoid garbage-collecting previous generations while testing.
107-
108-
## Support and development
109-
110-
The target architectures are x86_64 and aarch64 Linux. The initial build is
111-
validated on x86_64; fresh-machine, ARM and cross-distribution activation testing
112-
are still pending. NixOS users should avoid managing the same home with both a
113-
system Home Manager module and this standalone installer. macOS is not supported.
94+
Before replacing an existing Home Manager configuration, record
95+
`home-manager generations` and keep its configuration checkout. Run a previous
96+
generation's `/nix/store/…-home-manager-generation/activate` to roll back, then
97+
restore unmanaged files from `.commander-os-…` backups as needed. On a first
98+
installation, `home-manager uninstall` can remove the managed home environment.
99+
See the [Home Manager manual](https://nix-community.github.io/home-manager/).
100+
101+
Before removing a Home Manager shell, restore your login shell using
102+
`chsh -s /bin/bash` or the previous path recorded at
103+
`~/.local/state/commander-os/previous-shell.txt` (respecting `XDG_STATE_HOME`).
104+
Generation rollback does not undo `chsh` or `/etc/shells` registration. Do not
105+
remove the profile your login shell points to before changing it back.
106+
107+
Direct mode backs up changed files as `FILE.commander-os-TIMESTAMP`, preserves
108+
existing Bash/Zsh startup contents, and avoids duplicate startup entries on
109+
repeat runs. To undo it, first restore the previous login shell. Restore desired
110+
backup files and remove the Commander-os startup block from `.bashrc` or `.zshrc`,
111+
or remove `~/.config/fish/conf.d/commander-os.fish`. Remove Commander-os's shell
112+
snippets under `~/.config/commander-os/` if no longer needed. Tools installed by
113+
your package manager remain installed; there is no automatic native uninstaller.
114+
115+
## Validation and scope
114116

115117
```sh
116-
python3 -B -m unittest discover -s tests -v
117-
bash -n install.sh scripts/prerequisites.sh
118-
nix --extra-experimental-features 'nix-command flakes' flake check
118+
nix develop --command python3 -B -m unittest discover -s tests -v
119+
nix develop --command shellcheck install.sh scripts/prerequisites.sh
120+
nix flake check
119121
```
120122

121-
Planned next steps: clean-VM installation tests, optional desktop styling, and
122-
optional backup integrations with user-provided destinations and credentials.
123-
No personal repository history, system snapshots, wallet data, or bundled
124-
executables are included.
125-
126-
The guided dependency setup is inspired by the workflow of
127-
[ChrisTitusTech/mybash](https://github.com/ChrisTitusTech/mybash); Commander-os
128-
uses its own installer and manages the home environment through Home Manager.
123+
Targets: x86_64 and aarch64 Linux. Builds are tested on x86_64; clean-machine,
124+
ARM, and cross-distro activation testing remains in progress. macOS is unsupported.
125+
The setup flow is inspired by [ChrisTitusTech/mybash](https://github.com/ChrisTitusTech/mybash),
126+
with independently implemented installers and selectable shells. Fuller visual
127+
themes, Nerd Font setup and desktop integration remain future work.

‎flake.nix‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333
checks = forAllSystems (system: {
3434
home = (makeHome system).activationPackage;
3535
});
36+
devShells = forAllSystems (system: {
37+
default = nixpkgs.legacyPackages.${system}.mkShell {
38+
packages = with nixpkgs.legacyPackages.${system}; [
39+
python3
40+
fish
41+
zsh
42+
shellcheck
43+
];
44+
};
45+
});
3646
formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.nixfmt);
3747
};
3848
}

‎install.sh‎

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,64 @@ project_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
55
source "$project_dir/scripts/prerequisites.sh"
66
init_only=false
77
install_missing=true
8+
backend=''
9+
shell_choice=''
810
args=()
9-
for arg in "$@"; do
10-
case "$arg" in
11+
while (($#)); do
12+
case "$1" in
1113
--help|-h)
12-
echo 'Usage: ./install.sh [--apply] [--init] [--config PATH] [--no-install]'
13-
echo 'Offers to install missing prerequisites and Nix, then builds a preview.'
14-
echo '--apply Ask to activate after building.'
15-
echo '--init Create machine settings only (Python may be installed).'
16-
echo '--no-install Do not install prerequisites or Nix.'
14+
echo 'Usage: ./install.sh [--apply] [--init] [--backend home-manager|native]'
15+
echo ' [--shell bash|fish|zsh|keep] [--config PATH] [--no-install]'
16+
echo 'Interactive setup asks for installation mode and shell before installing anything.'
17+
echo 'Without --apply, native mode shows a plan; Home Manager mode builds a preview.'
1718
exit 0 ;;
18-
--init) init_only=true; args+=("$arg") ;;
19-
--no-install) install_missing=false ;;
20-
*) args+=("$arg") ;;
19+
--init) init_only=true; args+=("$1"); shift ;;
20+
--apply) args+=("$1"); shift ;;
21+
--no-install) install_missing=false; shift ;;
22+
--backend|--shell|--config)
23+
(($# >= 2)) || { echo "Missing value for $1" >&2; exit 1; }
24+
case "$1" in
25+
--backend) backend=$2 ;;
26+
--shell) shell_choice=$2 ;;
27+
--config) args+=("$1" "$2") ;;
28+
esac
29+
shift 2 ;;
30+
*) echo "Unknown argument: $1" >&2; exit 1 ;;
2131
esac
2232
done
2333
[[ $(uname -s) == Linux ]] || { echo 'Only Linux is supported.' >&2; exit 1; }
2434
((EUID != 0)) || { echo 'Run as your normal user, without sudo.' >&2; exit 1; }
25-
if "$install_missing"; then
26-
if "$init_only"; then
27-
ensure_packages python3
35+
if [[ -z "$backend" ]]; then
36+
if [[ -t 0 ]]; then
37+
echo 'How should Commander-os manage your setup?'
38+
echo ' 1) Home Manager — install Nix if needed; pinned packages and generations'
39+
echo ' 2) Direct install — distro packages and backed-up configuration files'
40+
read -r -p 'Choose [1/2, default 1]: ' answer
41+
case "$answer" in ''|1) backend=home-manager ;; 2) backend=native ;; *) exit 1 ;; esac
2842
else
29-
ensure_packages python3 git curl xz
43+
echo 'Specify --backend home-manager or --backend native when not running interactively.' >&2
44+
exit 1
45+
fi
46+
fi
47+
case "$backend" in home-manager|native) ;; *) echo 'Invalid backend.' >&2; exit 1 ;; esac
48+
if [[ -z "$shell_choice" && -t 0 ]]; then
49+
echo 'Shell: 1) Fish 2) Bash 3) Zsh 4) Keep current shell 5) Reuse saved choice'
50+
read -r -p 'Choose [1-5, default 5]: ' answer
51+
case "$answer" in 1) shell_choice=fish ;; 2) shell_choice=bash ;; 3) shell_choice=zsh ;; 4) shell_choice=keep ;; ''|5) ;; *) exit 1 ;; esac
52+
fi
53+
if [[ -n "$shell_choice" ]]; then
54+
case "$shell_choice" in bash|fish|zsh|keep) args+=(--shell "$shell_choice") ;; *) echo 'Invalid shell.' >&2; exit 1 ;; esac
55+
fi
56+
if "$install_missing"; then
57+
ensure_packages python3
58+
if [[ "$backend" == home-manager ]] && ! "$init_only"; then
59+
ensure_packages git curl xz
3060
ensure_nix
3161
fi
3262
fi
3363
command -v python3 >/dev/null || { echo 'Python 3 is missing.' >&2; exit 1; }
64+
if [[ "$backend" == native ]]; then
65+
args+=(--backend native)
66+
"$install_missing" || args+=(--no-install)
67+
fi
3468
exec python3 "$project_dir/scripts/bootstrap.py" "${args[@]}"

0 commit comments

Comments
 (0)