bug: $env.MYCELIUM_IP not populated in nushell login shells (bash exports in .profile) #112

Closed
opened 2026-04-21 15:25:31 +00:00 by sameh-farouk · 0 comments
Member

Update 2026-04-21: Rebased against upstream refactor that moved per-user mycelium state from /etc/hero-users/<user>.env (shell env format) to ~/hero/cfg/hero_cfg.toml (TOML, [mycelium] section). Workaround and proposed fix updated accordingly. Core issue (nu doesn't read the bash .profile exports) unchanged.

Summary

multi_user_add writes export MYCELIUM_IP="..." and export MYCELIUM_BRIDGE="..." into the new user's .profile and .bashrc, but the login shell it sets for the user is nushell (~/hero/bin/nu). Nushell does not source .profile or .bashrc, so those env vars are never populated in the user's actual shell.

Result: every documented command that uses $env.MYCELIUM_IP errors immediately on a freshly-provisioned account:

~> service_router start --address $env.MYCELIUM_IP
Error: nu::shell::column_not_found
  × Cannot find column 'MYCELIUM_IP'

Users have to manually parse ~/hero/cfg/hero_cfg.toml themselves or add a snippet to config_user.nu to work around it.

Location

tools/modules/installers/multiuser.nu:582–584, 616–617:

$bridge_env_lines = [
    $"export MYCELIUM_BRIDGE=\"($br_name)\""
    $"export MYCELIUM_IP=\"($prefix64)1\""
]
...
$profile | priv_save $"($homedir)/.profile"
$profile | priv_save $"($homedir)/.bashrc"

Bash syntax, written to bash rc files, while the login shell is nu.

Proposed fix

Populate env vars from ~/hero/cfg/hero_cfg.toml in tools/hero_loader.nu, which is already sourced by the nu config.nu generated by install.sh. Centrally maintained, no per-user duplication, kicks in automatically on every hero_skills update:

try {
    let cfg = $"($env.HOME)/hero/cfg/hero_cfg.toml"
    if ($cfg | path exists) {
        let m = (open $cfg | get -o mycelium | default {})
        if (($m | get -o ipv6_address | default "") | is-not-empty) {
            $env.MYCELIUM_IP = ($m | get ipv6_address)
        }
        if (($m | get -o bridge_name | default "") | is-not-empty) {
            $env.MYCELIUM_BRIDGE = ($m | get bridge_name)
        }
    }
}

Workaround for affected users

Add to ~/.config/nushell/config_user.nu:

try {
    let cfg = $"($env.HOME)/hero/cfg/hero_cfg.toml"
    if ($cfg | path exists) {
        let m = (open $cfg | get -o mycelium | default {})
        if (($m | get -o ipv6_address | default "") | is-not-empty) { $env.MYCELIUM_IP = ($m | get ipv6_address) }
        if (($m | get -o bridge_name  | default "") | is-not-empty) { $env.MYCELIUM_BRIDGE = ($m | get bridge_name) }
    }
}

Impact

Low severity, high friction — every new user hits this on their first service_router start and has to figure out the workaround.

> **Update 2026-04-21:** Rebased against upstream refactor that moved per-user mycelium state from `/etc/hero-users/<user>.env` (shell env format) to `~/hero/cfg/hero_cfg.toml` (TOML, `[mycelium]` section). Workaround and proposed fix updated accordingly. Core issue (nu doesn't read the bash `.profile` exports) unchanged. ### Summary `multi_user_add` writes `export MYCELIUM_IP="..."` and `export MYCELIUM_BRIDGE="..."` into the new user's `.profile` and `.bashrc`, but the login shell it sets for the user is **nushell** (`~/hero/bin/nu`). Nushell does not source `.profile` or `.bashrc`, so those env vars are never populated in the user's actual shell. Result: every documented command that uses `$env.MYCELIUM_IP` errors immediately on a freshly-provisioned account: ``` ~> service_router start --address $env.MYCELIUM_IP Error: nu::shell::column_not_found × Cannot find column 'MYCELIUM_IP' ``` Users have to manually parse `~/hero/cfg/hero_cfg.toml` themselves or add a snippet to `config_user.nu` to work around it. ### Location `tools/modules/installers/multiuser.nu:582–584, 616–617`: ```nu $bridge_env_lines = [ $"export MYCELIUM_BRIDGE=\"($br_name)\"" $"export MYCELIUM_IP=\"($prefix64)1\"" ] ... $profile | priv_save $"($homedir)/.profile" $profile | priv_save $"($homedir)/.bashrc" ``` Bash syntax, written to bash rc files, while the login shell is nu. ### Proposed fix Populate env vars from `~/hero/cfg/hero_cfg.toml` in `tools/hero_loader.nu`, which is already sourced by the nu `config.nu` generated by `install.sh`. Centrally maintained, no per-user duplication, kicks in automatically on every hero_skills update: ```nu try { let cfg = $"($env.HOME)/hero/cfg/hero_cfg.toml" if ($cfg | path exists) { let m = (open $cfg | get -o mycelium | default {}) if (($m | get -o ipv6_address | default "") | is-not-empty) { $env.MYCELIUM_IP = ($m | get ipv6_address) } if (($m | get -o bridge_name | default "") | is-not-empty) { $env.MYCELIUM_BRIDGE = ($m | get bridge_name) } } } ``` ### Workaround for affected users Add to `~/.config/nushell/config_user.nu`: ```nu try { let cfg = $"($env.HOME)/hero/cfg/hero_cfg.toml" if ($cfg | path exists) { let m = (open $cfg | get -o mycelium | default {}) if (($m | get -o ipv6_address | default "") | is-not-empty) { $env.MYCELIUM_IP = ($m | get ipv6_address) } if (($m | get -o bridge_name | default "") | is-not-empty) { $env.MYCELIUM_BRIDGE = ($m | get bridge_name) } } } ``` ### Impact Low severity, high friction — every new user hits this on their first `service_router start` and has to figure out the workaround.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_skills#112
No description provided.