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