Skip to content

Commit f012f2a

Browse files
committed
Add AGENTS.md, generate CLAUDE.md/GEMINI.md stubs, ignore AI settings dirs
AGENTS.md (https://agents.md) is the emerging cross-tool convention for repository instructions to AI coding agents, read natively by Codex, Mistral Vibe, Cursor, Copilot and others. Claude Code and Gemini CLI, however, only look for their own context filename (CLAUDE.md/GEMINI.md) rather than reading AGENTS.md directly, so add Makefile rules generating each as a one-line stub importing it via '@AGENTS.md', the same way modulecmd.tcl or README are generated build artifacts. Also ignore the project-local settings directories these AI coding assistants create (.claude, .codex, .gemini, .vibe), none of which belong in version control. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Xavier Delaruelle <xavier.delaruelle@cea.fr>
1 parent f83b0d2 commit f012f2a

4 files changed

Lines changed: 214 additions & 2 deletions

File tree

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/modulecmd.tcl
22
/ChangeLog*
33
/README
4+
/CLAUDE.md
5+
/GEMINI.md
46
/Makefile.inc
57
/version.inc
68
/modules.log
@@ -60,6 +62,11 @@
6062
/modules-*.tar.bz2
6163
/modules-*-win
6264
/modules-*-win.zip
65+
# ignore local settings directories of AI coding assistants
66+
/.claude
67+
/.codex
68+
/.gemini
69+
/.vibe
6370
# ignore vim swap files
6471
*.swp
6572
*.swo

.hunspell.en.dic

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,3 +1341,18 @@ HTTPS
13411341
mirrorEnvVarChange
13421342
PYTHONPATH
13431343
pythonpath
1344+
aclocal
1345+
claude
1346+
committer's
1347+
envmngt
1348+
gemini
1349+
kernel's
1350+
lookups
1351+
lowerCamelCase
1352+
modeval
1353+
modfind
1354+
portably
1355+
ps1
1356+
rb
1357+
sandboxing
1358+
util

AGENTS.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# AGENTS.md
2+
3+
This file provides guidance to AI coding assistants when working with code
4+
in this repository. Codex and Mistral Vibe read it directly. Claude Code and
5+
Gemini CLI only look for their own `CLAUDE.md`/`GEMINI.md` filename, so both
6+
are generated as stubs that just import this file (see the `CLAUDE.md:` and
7+
`GEMINI.md:` rules in `Makefile`).
8+
9+
## What this is
10+
11+
Modules (`envmodules/modules`) is the `module` command: a Tcl-based tool for
12+
dynamic modification of a user's shell environment via modulefiles. The
13+
runtime engine (`modulecmd.tcl`) is written in Tcl and must stay compatible
14+
with Tcl 8.5+.
15+
16+
## Build
17+
18+
```sh
19+
./configure
20+
make # builds modulecmd.tcl and other install artifacts
21+
make install
22+
```
23+
24+
`configure`/`Makefile` are hand-written (no autoconf/automake despite
25+
`lib/aclocal.m4`, `lib/configure.ac` existing for the optional C helper
26+
library in `lib/`).
27+
28+
### The core script is generated, not hand-edited directly for the final artifact
29+
30+
`modulecmd.tcl` (the actual interpreter installed to `libexecdir`) is built by
31+
`make` by concatenating the files in `tcl/` in a fixed order (see the
32+
`modulecmd.tcl:` rule in `Makefile`):
33+
34+
```
35+
init -> util -> envmngt -> report -> interp -> mfcmd -> modscan ->
36+
modfind -> modeval -> modspec -> cache -> coll -> main -> subcmd
37+
```
38+
39+
Always edit the individual source file in `tcl/` (e.g. `tcl/main.tcl.in`,
40+
`tcl/subcmd.tcl.in`); never edit a built `modulecmd.tcl` output directly.
41+
Files with a `.in` suffix contain `@markname@` substitutions filled in by
42+
`configure`/`Makefile`; files without `.in` (`mfcmd.tcl`, `modeval.tcl`,
43+
`modscan.tcl`, `modspec.tcl`, `syntaxdb.tcl`, `util.tcl`) have no
44+
substitutions.
45+
46+
## Tests
47+
48+
```sh
49+
make test # full suite via DejaGnu (~17,000 cases, ~12 min)
50+
make test QUICKTEST=y # quick mode, most essential tests, ~1 min
51+
make testinstall # test an already-`make install`ed tree
52+
```
53+
54+
Run a subset of tests directly with `script/mt` (reports an expected/actual
55+
diff on failure):
56+
57+
```sh
58+
script/mt 50/470 # runs testsuite/modules.50-cmds/470-*.exp
59+
script/mt --help # full usage/selection syntax
60+
```
61+
62+
Coverage (uses Nagelfar):
63+
64+
```sh
65+
make test COVERAGE=y # then inspect tcl/*.tcl_m for ';# Not covered' lines
66+
script/mt cov 70/{280,290} # coverage run on selected testfiles
67+
```
68+
69+
Lint (Nagelfar for Tcl, ShellCheck for sh/bash/ksh):
70+
71+
```sh
72+
make testlint
73+
script/mt lint 00/030
74+
```
75+
76+
Performance comparison across released versions and current branch
77+
(`script/mb`, stashes local changes, builds `modulecmd.tcl` for each
78+
version):
79+
80+
```sh
81+
script/mb
82+
script/mb profile
83+
```
84+
85+
## Docs
86+
87+
```sh
88+
cd doc && make html # requires Sphinx >= 1.0; output in doc/_build/html
89+
```
90+
91+
## Repository layout
92+
93+
- `tcl/` — Tcl source, split by concern; concatenated into `modulecmd.tcl`
94+
(see Build section). Key files:
95+
- `init.tcl.in` — configuration option definitions (`g_config_defs`) and
96+
state handling
97+
- `main.tcl.in` — top-level `module` procedure, sub-command dispatch/parsing
98+
- `subcmd.tcl.in` — one `cmdModule<Subcmdname>` procedure per sub-command
99+
- `mfcmd.tcl` — modulefile commands (procedures usable *inside* a
100+
modulefile, e.g. `setenv`, `prepend-path`)
101+
- `modeval.tcl` — modulefile evaluation engine
102+
- `modfind.tcl.in` — locating available/loaded modules
103+
- `modscan.tcl` — modulefile scan / extra-match search
104+
- `modspec.tcl` — module specification (name/version/variant) parsing
105+
- `cache.tcl.in`, `coll.tcl.in` — module cache and collection management
106+
- `envmngt.tcl.in` — environment variable manipulation
107+
- `interp.tcl.in` — sub-interpreter management (modulefile sandboxing)
108+
- `report.tcl.in` — all output/error/debug rendering
109+
- `util.tcl` — generic helpers
110+
- `syntaxdb.tcl` — generated Nagelfar syntax DB for linting (do not hand-edit)
111+
- `init/` — per-shell init/wrapper scripts (`bash.in`, `csh.in`, `fish.in`,
112+
`tcsh.in`, `zsh.in`, `pwsh.ps1.in`, `perl.pm.in`, `r.R.in`, `ruby.rb.in`,
113+
`cmake.in`, ...) and shell completion scripts
114+
(`bash_completion.in`, `fish_completion`, `tcsh_completion.in`,
115+
`zsh-functions/_module.in`)
116+
- `script/` — developer/maintainer tooling: `mt` (test runner), `mb`
117+
(benchmark), `mlprof` (profiling), `mrel`/`mpub` (release), `pre-commit`/
118+
`commit-msg` git hooks, `add.modules.in`, `modulecmd.in` wrapper
119+
- `lib/` — optional C helper library (`envmodules.c`) used for things Tcl
120+
can't do portably (e.g. group lookups); has its own `configure.ac`
121+
- `testsuite/` — DejaGnu test suite; `.exp` files grouped by numbered
122+
directory reflecting test category, e.g. `modules.00-init`,
123+
`modules.50-cmds`, `modules.70-maint`, `modules.90-avail`,
124+
`modules.92-spider`, `lint.00-init`, `install.00-init`. Each `.exp` file is
125+
numbered/prefixed (e.g. `470-variant.exp`); `script/mt 50/470` targets it.
126+
`modulefiles*/` subdirectories hold fixture modulefiles used by the tests.
127+
- `share/` — Nagelfar syntax databases, RPM spec, logo assets
128+
- `doc/source/` — Sphinx documentation source
129+
- `design/` — design notes for individual features (one `.rst` per feature)
130+
- `devel/` — maintainer/developer howtos, notably
131+
`add-new-sub-command.rst` and `add-new-config-option.rst`, which give
132+
the exact list of files to touch (core code, init/completion scripts,
133+
Nagelfar syntax db, man pages, testsuite) when adding a sub-command or
134+
config option — follow these when doing either task
135+
- `changes.rst` — in-depth behavior/feature changes per major version
136+
- `*.rst` at top level — man page sources (`module.rst`, `modulefile.rst`,
137+
`modulecmd.rst`, `ml.rst`, `envml.rst`)
138+
139+
## Coding conventions (Tcl)
140+
141+
- Max line length: 78 characters
142+
- Indent with 3 spaces, no tabs
143+
- Tcl minimal escaping style
144+
- Procedure names: `lowerCamelCase`; variable names: `no_case_at_all`
145+
- Brace/bracket placement:
146+
```tcl
147+
if {![isStateDefined already_report]} {
148+
setState already_report 1
149+
}
150+
```
151+
- No trailing whitespace, no misspellings (enforced by the `pre-commit`/
152+
`commit-msg` hooks in `script/`, backed by `codespell` and `hunspell`)
153+
- Code must remain compatible with Tcl 8.5+
154+
155+
## Commit conventions
156+
157+
- Every commit needs a DCO `Signed-off-by:` trailer matching the committer's
158+
git `user.name`/`user.email` — use `git commit -s`.
159+
- Patches (bug fix or feature) should include tests, and the test should be
160+
shown to fail without the patch.
161+
- The project follows the Linux kernel's policy on AI coding assistants (see
162+
"AI coding assistants" in `CONTRIBUTING.rst`): never add a
163+
`Signed-off-by:` trailer on behalf of the AI — only the human committer
164+
signs off — and disclose AI involvement with an `Assisted-by:` trailer,
165+
e.g. `Assisted-by: Claude:claude-sonnet-5`.
166+
167+
## Adding a new `module` sub-command or config option
168+
169+
Don't improvise the file list — `doc/source/devel/add-new-sub-command.rst`
170+
and `doc/source/devel/add-new-config-option.rst` enumerate, in order, every
171+
file that needs a change: core Tcl (`main.tcl.in`/`subcmd.tcl.in` or
172+
`init.tcl.in`), shell completion scripts, Nagelfar syntax db, man pages
173+
(`doc/source/module.rst`, `modulefile.rst`), `doc/source/changes.rst`, and
174+
the specific testsuite files/directories to extend. Read the relevant one
175+
before starting either task.

Makefile

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,19 @@ README:
631631
$(ECHO_GEN)
632632
sed -e '181,187d' -e '1,10d' -e 's|\[\(.*\?\)\]\[[0-9]\]|\1|' $@.md > $@
633633

634+
# AGENTS.md (https://agents.md) is the single source of instructions for AI
635+
# coding assistants working in this repository. Codex and Mistral Vibe read
636+
# it directly, but Claude Code and Gemini CLI only look for their own
637+
# CLAUDE.md/GEMINI.md filename, so generate a stub for each that just
638+
# imports AGENTS.md
639+
CLAUDE.md: AGENTS.md
640+
$(ECHO_GEN)
641+
echo '@AGENTS.md' > $@
642+
643+
GEMINI.md: AGENTS.md
644+
$(ECHO_GEN)
645+
echo '@AGENTS.md' > $@
646+
634647
script/add.modules: script/add.modules.in
635648
$(translate-in-script)
636649
chmod +x $@
@@ -934,6 +947,8 @@ ifeq ($(wildcard .git),.git)
934947
rm -f ChangeLog*
935948
endif
936949
rm -f README
950+
rm -f CLAUDE.md
951+
rm -f GEMINI.md
937952
rm -f modulecmd.tcl
938953
rm -f $(MODULECMDTEST) $(MODULECMDTEST)_i
939954
rm -f tcl/cache.tcl
@@ -1177,8 +1192,8 @@ $(V).SILENT: initdir pkgdoc doc version.inc share/rpm/environment-modules.spec \
11771192
tcl/cache.tcl_i tcl/coll.tcl_i tcl/envmngt.tcl_i tcl/init.tcl_i tcl/interp.tcl_i \
11781193
tcl/main.tcl_i tcl/mfcmd.tcl_i tcl/modfind.tcl_i tcl/modeval.tcl_i \
11791194
tcl/modscan.tcl_i tcl/modspec.tcl_i tcl/report.tcl_i tcl/subcmd.tcl_i \
1180-
tcl/util.tcl_i ChangeLog ChangeLog.gz README script/add.modules \
1181-
script/gitlog2changelog.py script/modulecmd \
1195+
tcl/util.tcl_i ChangeLog ChangeLog.gz README CLAUDE.md GEMINI.md \
1196+
script/add.modules script/gitlog2changelog.py script/modulecmd \
11821197
lib/libtclenvmodules$(SHLIB_SUFFIX) lib/libtestutil-closedir$(SHLIB_SUFFIX) \
11831198
lib/libtestutil-getpwuid$(SHLIB_SUFFIX) lib/libtestutil-getgroups$(SHLIB_SUFFIX) \
11841199
lib/libtestutil-0getgroups$(SHLIB_SUFFIX) lib/libtestutil-mktime$(SHLIB_SUFFIX) \

0 commit comments

Comments
 (0)