# `jan config`
Emit shell fragments, symlink (or copy) rc files into `$HOME`, run imperative apply
steps, and check host tools declared as `config:` on command nodes.
```bash
jan config emit --shell zsh -o ~/.config/jan/config.zsh
jan config link
jan config unlink
jan config apply
jan config deps
```
| `emit` | Concatenate all `config.shell` fragments (tree walk order) |
| `link` | Place `config.link` files under `$HOME` (write inline bodies; symlink/copy path sources) |
| `unlink` | Remove destinations that still match managed path/inline content |
| `apply` | Run each `config.apply` argv list |
| `deps` | Report `config.deps` tools missing from `PATH` |
## YAML
```yaml
# config.yaml (index)
commands:
zsh:
include: config/zsh.yaml
emacs:
include: config/emacs.yaml
# config/zsh.yaml — shell fragment inlined on the node
about: zsh history and PATH
config:
shell: |
setopt AUTO_CD
# config/emacs.yaml — file body inlined (written by `jan config link`)
about: write init.el into ~/.emacs.d
config:
link:
~/.emacs.d/init.el: |
(message "hi")
# or path form: ~/.other: config/other.el
# or explicit: ~/.x: { path: config/x } / { content: "…" }
```
| `shell:` (string) | Inline fragment (preferred for short/medium zsh snippets) |
| `shell.path` | File under the preferred jan directory |
| `link` | Map of destination → source. Dest must be absolute or `~/…` under `$HOME` (or `$XDG_CONFIG_HOME`). Value is inline body (`\|` / multiline), a relative path string, `{path: …}`, or `{content: …}`. |
| `apply` | List of argv arrays (no shell interpolation) |
| `deps` | Map of bare command name → optional package/install hint (empty/`~` = name only). Checked by `jan config deps`. |
Nodes may be config-only (no `run`). They appear in `--help` like alias-only nodes; opening a node that declares `config:` shows a **Host configuration (`jan config`)** section (shell path/inline, links, apply count, deps count). Existing `os:` filters still apply.
The node's `about` (or chain) labels each missing group in the `deps` report.
## Relation to `jan alias`
Do not merge schemas. `aliases:` is for typing less (`alias g=git`, extra jan names). `config:` is for host setup (sourced fragments, symlinks, `git config …`, host tool checklists). See [`alias.md`](alias.md).
## Flags
### `emit`
| `--shell sh\|bash\|zsh` | Header dialect (default: `zsh`) |
| `-o`, `--output FILE` | Write to a file instead of stdout |
### `link`
| `--dry-run` | Print planned links without changing the filesystem |
| `--copy` | Copy instead of symlink |
| `--force` | Replace an existing destination (default: warn and skip) |
If the destination path already exists, `jan config link` prints a warning to
stderr and skips that entry (exit 0). It does not overwrite unless `--force` is
passed. An existing symlink that already points at the intended source is treated
as done (`ok (already linked)`). Each run prints a summary:
`created / updated`, `already ok`, and `skipped (exists)`.
### `unlink`
| `--dry-run` | Print planned removals without changing the filesystem |
Removes a destination only when it still matches the managed content (correct
symlink target, or file bytes equal to an inline body). Foreign or modified
files are skipped with a warning. Prints a summary of `removed`,
`already absent`, and `skipped (foreign)`.
### `apply`
| `--dry-run` | Print argv lists without running them |
A non-zero child exit fails the whole `apply`.
### `deps`
| `--strict` | Exit `1` if any listed tool is missing (default: exit `0` and still print the report) |
## Install pattern
Same idea as `jan alias`:
```bash
jan config emit --shell zsh -o ~/.config/jan/config.zsh
source ~/.config/jan/config.zsh
jan config link
jan config apply
jan config deps
```
`libbeagan_dependencies` (when emitted from the preferred tree) is a thin wrapper around `jan config deps`.
## Relation to Incubator/stow / GNU Stow
For `$HOME` rc placement, prefer `jan config link` / `unlink` (declarative
`config.link` in the preferred tree). The Incubator `stow` tool’s import/export
farm is largely superseded for that use case; keep it only if you need
import-from-live-files or non-home system path farms. GNU Stow’s package folding
is intentionally not mirrored here.