HTTPS
https://git.nageyqma.icu/nageyqma/wm.git
SSH
git@git.nageyqma.icu:nageyqma/wm.git
HTTPS 链接可直接 git clone;推送代码请使用 SSH。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
# AGENT.md
This is a local fork of [dwl](https://github.com/djpohly/dwl), the wlroots port
of [dwm](https://dwm.suckless.org/). The owner is customizing it step by step.
The tree started from upstream; every change after that is deliberately a small
layer, not a rewrite.
Read this before editing. If a rule below conflicts with generic "good
engineering" advice, this file wins. The background is
[suckless philosophy](https://suckless.org/philosophy/) and
[suckless coding style](https://suckless.org/coding_style/).
## The project's bar
Two properties matter more than features:
1. **Small.** A line that is not necessary is a line the owner must read and
maintain forever. Prefer no code to a little code, and a config value to a
new function.
2. **Readable.** A stranger who knows C and dwm should understand a change in
one pass. A clever abstraction that saves repetition but costs a jump is a
regression here.
The bar is native: `drawbar()` renders it into a pixman image. The
system-information text is read from `$XDG_RUNTIME_DIR/dwl-status`, written by
`~/scripts/status.sh`; tmux reads the compact `$XDG_RUNTIME_DIR/tmux-status`
written by the same script, and starts the script when dwl is not running. Do
not replace it with an external bar program.
The practical consequences:
- Configuration belongs in `config.h`. If a behavior can be selected there,
implement it there, not as a runtime option.
- Reuse what dwl/wlroots already provides: `spawn`, `SHCMD`, `Arg`, `LISTEN`,
listeners, wlroots helpers. Do not build a second mechanism beside one that
already exists.
- No new dependencies beyond the bar (`fcft`, `pixman`), no new source
files, no build-system layers, no generated code, no configuration parser,
no IPC, no plugin system, no runtime reload, no animation framework.
- Do not generalize for a hypothetical future request. The owner will ask for
the next feature when they want it.
- Prefer deleting a special case to adding a flag. Prefer one fixed path to a
search path. Prefer one command to two blocking/non-blocking variants.
- A change that touches unrelated lines is wrong even if it looks "cleaner".
Reformatting, sorting, and include churn are not welcome.
## How to approach a request
1. Read the relevant code, `config.def.h`, `config.h`, and the man page first.
Search for an existing hook before designing one.
2. Choose the smallest lever, in this order: a `config.h` constant, a call to
an existing function, a small helper, a new file (almost never).
3. Check the side effects: environment (`WAYLAND_DISPLAY`,
`XDG_RUNTIME_DIR`), child processes and shutdown, focus and keyboard
groups, multi-monitor, XWayland, and the status output.
4. Write the diff in the surrounding style. It should be hard to tell your hunk
from upstream code.
5. Build. Do not restart the live session. Report what you verified and what
you did not.
A worked example from this tree: the dwm autostart patch searches three XDG
directories, supports two script names, and distinguishes blocking from
background startup. The actual requirement was "run one known script once".
The small solution is one `SHCMD` entry in `config.h` plus one `spawn()` call
in `run()`; `/bin/sh` already reports a missing script.
## C style
Match the file. In practice that means:
- Tabs for indentation, spaces for alignment; keep lines near the surrounding
width.
- Function return type on its own line, name on the next, opening brace on the
next line. Control-flow braces on the same line.
- Declarations before statements (`-Wdeclaration-after-statement` is on).
- `/* ... */` comments, lowercase names, `static` for file-local functions,
forward declarations near the top, `ecalloc`/`die` as the rest of dwl uses
them.
- No new compiler warnings. Do not silence warnings with casts or pragmas when
the code can simply be written correctly.
- Do not run `clang-format`, sort includes, reorder keybindings, or re-align
existing tables. Touch only the lines the change needs.
- Comments explain *why*, not *what*. Do not narrate the code.
## config.h and config.def.h
`config.h` is the owner's live, git-ignored config. `config.def.h` is the
tracked default. They are edited separately and intentionally differ: the
owner's tag order is not the default order. Never copy one over the other.
When a change is a new default, add it to both files. When it is only the
owner's preference, leave `config.def.h` alone.
Do not touch the owner's existing keybindings, tag order, monitor rules, DRM
device list, or mouse settings while doing an unrelated change. In particular,
the keyboard layout is US Colemak with `caps:escape`; the key table was
deliberately left alone. dwl matches keysyms, so a binding follows the letter,
not the physical QWERTY position. That is intended.
`Arg autostartcmd` and the `spawn(&autostartcmd)` call in `run()` are the
whole autostart implementation. Keep it that way: one command, one path, no
directory search, and no blocking/non-blocking pair. There is no `-s` command
line option; do not reintroduce one.
## Local invariants
- Build against wlroots 0.20 (`config.mk`). Do not migrate, downgrade, or
adopt `wlroots-next` APIs without an explicit request.
- The compositor's startup environment is not this repository's business. Do
not add display-manager, systemd, or login-session integration.
- The live desktop belongs to the owner. This agent does not restart, log out
of, or reconfigure it to test code.
## Build and verify
- `make` is the only build step. Keep it clean.
- Never run `make -B`: the `config.h:` target has no prerequisites, so `-B`
forces `cp config.def.h config.h` and overwrites the owner's live,
git-ignored config. Use plain `make` or `make clean && make`; to force a
rebuild, remove `dwl` or touch `dwl.c`.
- Compile-time checks are the default. Run `git diff` before reporting.
- Do not start, stop, or restart dwl, KDE, the display manager, or the owner's
session to test a change. The owner will test it.
- A headless smoke test is acceptable when it cannot touch the real session:
`WLR_BACKENDS=headless`, a temporary `HOME`, a temporary
`XDG_RUNTIME_DIR`, and a fake autostart script that only writes a marker.
Clean up afterwards. Never run the real `~/scripts/autostart-dwl.sh`
against a throwaway compositor.
- Do not install packages, edit system config, or change the running
environment.
## Git and reporting
- Do not commit unless asked. Do not amend, rebase, force-push, or touch
unrelated branches.
- `config.h`, `patches/`, build products, and generated protocol headers are
ignored; do not "fix" that.
- Report in the language the owner used. Include the files changed, the reason
for the smallest design, what was built and tested, and what was not tested.
Do not claim a live-session test you did not perform.
- If you had to make a tradeoff, say it plainly. Do not hide it in a
changelog entry.
This file is not a changelog. Update it only when the working rules change.
When in doubt, do less, keep the diff obvious, and report the tradeoff.