Files
tai/research/shell-multiplexer-auto-attach/fishshell-docs-3-4-index-initialization-files.md
T
2026-10-10 09:25:33 +02:00

49 lines
3.7 KiB
Markdown

# fish docs index: initialization files (config.fish is always sourced)
## Metadata
| Field | Value |
|---|---|
| Institute | Molodetz Institute — Research & Retrieval Division |
| Subject | shell-multiplexer-auto-attach |
| Document type | Source Dossier |
| Tier | 1 |
| Source title | fish documentation index (3.4) |
| Source URL | https://fishshell.com/docs/3.4/index.html |
| Source publisher / author | fish-shell project (fishshell.com) |
| Source type | vendor docs |
| Source date (published) | Unknown — not stated |
| Date researched | 2026-10-10 |
| Researched by | tai (agent), model: Claude Sonnet 5, on behalf of retoor |
| Research method | web search synthesis |
| Confidence | High |
| Status | Active |
## Summary
fish's official docs state plainly that its startup files are read "on the startup of every shell, not just interactive ones" — unlike bash's `.bashrc` (interactive-only, non-login) or `.profile`/`.bash_profile` (login-only). `~/.config/fish/config.fish` (respecting `$XDG_CONFIG_HOME`) is read on *every* fish invocation, interactive or not, login or not, and is explicitly the right place to put code that should run unconditionally — with `status is-interactive`/`status is-login` as the documented way to scope behavior within it. Snippets in `~/.config/fish/conf.d/` run before `config.fish`, which runs last so it can override them.
## Key findings
- This is the single most consequential difference from bash/zsh for this project: `.bashrc` and `.zshrc` are themselves gated to interactive shells by the shell's own startup logic (roughly), so the bash/zsh plexer block's `case "$-" in *i*)` guard is a belt-and-suspenders check on top of a file that mostly only gets read in the right context anyway. `config.fish` has no such built-in gating — it runs unconditionally, so the `status is-interactive` guard inside `FISH_PLEXER_BLOCK` is doing *all* of the interactivity-scoping work, not just reinforcing it.
- The fish FAQ (per the search tool's synthesis) explicitly calls out this exact contrast with `.bashrc`/`.profile`, confirming it's a documented, intentional design difference in fish, not an edge case this research happened to stumble on.
- `~/.config/fish/config.fish`'s location follows `$XDG_CONFIG_HOME` — directly informing `shell_rc_path()` in tai.py, which checks `os.environ.get("XDG_CONFIG_HOME")` before falling back to `~/.config`.
## Pros / strengths
- Official documentation stating the behavior plainly and explicitly contrasting it with bash/zsh conventions, removing any ambiguity about whether the interactivity guard is optional.
## Cons / limitations / caveats
- A third-party pyenv wiki page (github-pyenv-wiki-unix-shell-initialization.md, also Tier 1) lists a fuller startup-file ordering (system/user `conf.d`, `vendor_conf.d`, `/etc/fish/config.fish`, then `~/.config/fish/config.fish`) that this search could not independently confirm against the official docs; treated as secondary/unconfirmed per that dossier's own caveat, not relied on for anything load-bearing here.
## Relevance to tai
This is the finding that made the `status is-interactive` guard non-optional in `FISH_PLEXER_BLOCK`: without it, installing the plexer hook into `config.fish` would attempt to `exec tai.py --plexer-wrap` on *every* fish invocation, including scripts, `fish -c`, and tooling that shells out to fish non-interactively — exactly the failure mode the user explicitly wanted to avoid. Confirmed end-to-end by the `FishNonInteractiveSkipTest` integration test in `tests/bashrc.py`, which runs a plain `fish -c 'echo marker'` (no explicit sourcing needed, since config.fish always runs) and asserts no plexer socket gets created.
## Changelog
| Date | Change |
|---|---|
| 2026-10-10 | Initial dossier created. |