Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

pi/agent/skillz/lnx/linux-userland/SKILL.md

Raw
Rendered preview

name: linux-userland os: lnx disable-model-invocation: true description: "Use for Linux user-owned config and environment: HOME/XDG paths, shell, PATH, dotfiles, user systemd, desktop/session settings, caches, state dirs."

Linux Userland

Linux config work inside the user's ownership boundary.

Boundary: operate under $HOME and user managers only. If a fix needs /etc, /usr, /var/lib, packages, kernel settings, devices, or sudo, stop and use linux escalation.

Workflow

  1. Identify app/tool, config file discovery rules, and current user/session.
  2. Resolve XDG paths; do not hard-code ~/.config if env overrides exist.
  3. Read installed docs: man, --help, app config docs in repo/package.
  4. Inspect current config/env/state.
  5. Back up before edits; make minimal change.
  6. Validate with app-specific parser/check command.
  7. Reload/restart only user-owned process/service. Provide rollback.

XDG Paths

Purpose Env Default
Config XDG_CONFIG_HOME $HOME/.config
Data XDG_DATA_HOME $HOME/.local/share
State/logs/history XDG_STATE_HOME $HOME/.local/state
Cache XDG_CACHE_HOME $HOME/.cache
Runtime sockets XDG_RUNTIME_DIR set by login/session

Probe safely:

printf 'HOME=%s\nXDG_CONFIG_HOME=%s\nXDG_DATA_HOME=%s\nXDG_STATE_HOME=%s\nXDG_CACHE_HOME=%s\nXDG_RUNTIME_DIR=%s\n' \
  "$HOME" "${XDG_CONFIG_HOME:-$HOME/.config}" "${XDG_DATA_HOME:-$HOME/.local/share}" \
  "${XDG_STATE_HOME:-$HOME/.local/state}" "${XDG_CACHE_HOME:-$HOME/.cache}" "${XDG_RUNTIME_DIR:-}"

XDG env vars must be absolute paths to be valid.

Shell + Environment Diagnosis

The agent's tool shell may not equal the user's interactive shell. Detect before giving syntax:

printf 'SHELL=%s\n' "$SHELL"
getent passwd "$(id -un)" | awk -F: '{print "login_shell=" $7}'
printf 'PATH=%s\n' "$PATH" | tr ':' '\n'

Startup files by shell:

Shell Common user files PATH/export syntax
bash ~/.bashrc, ~/.bash_profile, ~/.profile export NAME=value
zsh ~/.zshrc, ~/.zprofile, ~/.zshenv export NAME=value
fish ~/.config/fish/config.fish set -gx NAME value; fish_add_path DIR
nushell ~/.config/nushell/env.nu, config.nu $env.NAME = value

Prefer editing the shell's config file over emitting complex copy-paste snippets. If root is needed, do not craft fish/nushell sudo heredocs; use linux script escalation.

User systemd Units

User units live primarily in $XDG_CONFIG_HOME/systemd/user (default ~/.config/systemd/user).

Read:

systemctl --user --no-pager --full list-units --failed
systemctl --user --no-pager --full status UNIT
systemctl --user show UNIT -p LoadState -p ActiveState -p SubState -p Result -p ExecMainStatus
systemctl --user cat UNIT
journalctl --user-unit UNIT -b --no-pager --full -n 200
systemd-analyze --user verify "${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/UNIT"

After editing a user unit:

systemctl --user daemon-reload
systemctl --user status UNIT --no-pager --full
journalctl --user-unit UNIT -b --no-pager --full -n 100

Restart only if the user asked for restart or the service was active before edit:

systemctl --user restart UNIT

Use enable --now only when the user asked for autostart.

Safe Edit Pattern

For an existing regular config file, resolve symlinks first and confirm the target is inside the authorized user-owned boundary. Edit and restore the resolved target, leaving the original symlink intact. A cp -a backup of a symlink copies only the link, not a content snapshot.

file=$(realpath -e -- /path/to/file) || exit 1
[ -f "$file" ] || exit 1
backup=$(mktemp -- "$file.bak.XXXXXX") || exit 1
cp -p -- "$file" "$backup" || exit 1
# edit "$file"
# run validator/reload
# rollback if bad: cp -p -- "$backup" "$file"

Stop on resolution or backup failure; do not create a missing symlink target implicitly.

Validation examples:

  • systemd user unit: systemd-analyze --user verify FILE
  • shell config: run the shell parser if available (bash -n FILE, zsh -n FILE); fish/nushell need shell-specific checks.
  • app config: use the app's documented check, validate, doctor, or dry-run command.

Common Mistakes

Mistake Fix
Editing /etc from userland task Stop; use linux escalation
Assuming bash syntax Detect shell; prefer editing files or POSIX sh scripts
Ignoring XDG overrides Resolve env/defaults first
Restarting system service Only use systemctl --user; escalate otherwise
Changing config without rollback Backup + validate + rollback command
---
name: linux-userland
os: lnx
disable-model-invocation: true
description: "Use for Linux user-owned config and environment: HOME/XDG paths, shell, PATH, dotfiles, user systemd, desktop/session settings, caches, state dirs."
---

# Linux Userland

Linux config work inside the user's ownership boundary.

**Boundary:** operate under `$HOME` and user managers only. If a fix needs `/etc`, `/usr`, `/var/lib`, packages, kernel settings, devices, or `sudo`, stop and use `linux` escalation.

## Workflow

1. Identify app/tool, config file discovery rules, and current user/session.
2. Resolve XDG paths; do not hard-code `~/.config` if env overrides exist.
3. Read installed docs: `man`, `--help`, app config docs in repo/package.
4. Inspect current config/env/state.
5. Back up before edits; make minimal change.
6. Validate with app-specific parser/check command.
7. Reload/restart only user-owned process/service. Provide rollback.

## XDG Paths

| Purpose            | Env               | Default              |
| ------------------ | ----------------- | -------------------- |
| Config             | `XDG_CONFIG_HOME` | `$HOME/.config`      |
| Data               | `XDG_DATA_HOME`   | `$HOME/.local/share` |
| State/logs/history | `XDG_STATE_HOME`  | `$HOME/.local/state` |
| Cache              | `XDG_CACHE_HOME`  | `$HOME/.cache`       |
| Runtime sockets    | `XDG_RUNTIME_DIR` | set by login/session |

Probe safely:

```bash
printf 'HOME=%s\nXDG_CONFIG_HOME=%s\nXDG_DATA_HOME=%s\nXDG_STATE_HOME=%s\nXDG_CACHE_HOME=%s\nXDG_RUNTIME_DIR=%s\n' \
  "$HOME" "${XDG_CONFIG_HOME:-$HOME/.config}" "${XDG_DATA_HOME:-$HOME/.local/share}" \
  "${XDG_STATE_HOME:-$HOME/.local/state}" "${XDG_CACHE_HOME:-$HOME/.cache}" "${XDG_RUNTIME_DIR:-}"
```

XDG env vars must be absolute paths to be valid.

## Shell + Environment Diagnosis

The agent's tool shell may not equal the user's interactive shell. Detect before giving syntax:

```bash
printf 'SHELL=%s\n' "$SHELL"
getent passwd "$(id -un)" | awk -F: '{print "login_shell=" $7}'
printf 'PATH=%s\n' "$PATH" | tr ':' '\n'
```

Startup files by shell:

| Shell   | Common user files                            | PATH/export syntax                        |
| ------- | -------------------------------------------- | ----------------------------------------- |
| bash    | `~/.bashrc`, `~/.bash_profile`, `~/.profile` | `export NAME=value`                       |
| zsh     | `~/.zshrc`, `~/.zprofile`, `~/.zshenv`       | `export NAME=value`                       |
| fish    | `~/.config/fish/config.fish`                 | `set -gx NAME value`; `fish_add_path DIR` |
| nushell | `~/.config/nushell/env.nu`, `config.nu`      | `$env.NAME = value`                       |

Prefer editing the shell's config file over emitting complex copy-paste snippets. If root is needed, do not craft fish/nushell sudo heredocs; use `linux` script escalation.

## User systemd Units

User units live primarily in `$XDG_CONFIG_HOME/systemd/user` (default `~/.config/systemd/user`).

Read:

```bash
systemctl --user --no-pager --full list-units --failed
systemctl --user --no-pager --full status UNIT
systemctl --user show UNIT -p LoadState -p ActiveState -p SubState -p Result -p ExecMainStatus
systemctl --user cat UNIT
journalctl --user-unit UNIT -b --no-pager --full -n 200
systemd-analyze --user verify "${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user/UNIT"
```

After editing a user unit:

```bash
systemctl --user daemon-reload
systemctl --user status UNIT --no-pager --full
journalctl --user-unit UNIT -b --no-pager --full -n 100
```

Restart only if the user asked for restart or the service was active before edit:

```bash
systemctl --user restart UNIT
```

Use `enable --now` only when the user asked for autostart.

## Safe Edit Pattern

For an existing regular config file, resolve symlinks first and confirm the target is inside the authorized user-owned boundary.
Edit and restore the resolved target, leaving the original symlink intact.
A `cp -a` backup of a symlink copies only the link, not a content snapshot.

```bash
file=$(realpath -e -- /path/to/file) || exit 1
[ -f "$file" ] || exit 1
backup=$(mktemp -- "$file.bak.XXXXXX") || exit 1
cp -p -- "$file" "$backup" || exit 1
# edit "$file"
# run validator/reload
# rollback if bad: cp -p -- "$backup" "$file"
```

Stop on resolution or backup failure; do not create a missing symlink target implicitly.

Validation examples:

- systemd user unit: `systemd-analyze --user verify FILE`
- shell config: run the shell parser if available (`bash -n FILE`, `zsh -n FILE`); fish/nushell need shell-specific checks.
- app config: use the app's documented `check`, `validate`, `doctor`, or dry-run command.

## Common Mistakes

| Mistake                           | Fix                                                      |
| --------------------------------- | -------------------------------------------------------- |
| Editing `/etc` from userland task | Stop; use `linux` escalation                             |
| Assuming bash syntax              | Detect shell; prefer editing files or POSIX `sh` scripts |
| Ignoring XDG overrides            | Resolve env/defaults first                               |
| Restarting system service         | Only use `systemctl --user`; escalate otherwise          |
| Changing config without rollback  | Backup + validate + rollback command                     |