From 5d31ed089d9242d1db90183a5d4b354f5bae523b Mon Sep 17 00:00:00 2001 From: Wong Ding Feng Date: Sat, 4 Apr 2026 14:45:00 +0800 Subject: [PATCH] docs: add AGENTS.md for agentic coding guidelines Add comprehensive guide for agents working in this Doom Emacs config: - Build/lint/test commands (doom sync, doom build, doom doctor) - Emacs Lisp code style guidelines - Doom macro reference (use-package!, add-hook!, map!, after!, load!) - Naming conventions and common patterns - Important workflow notes --- AGENTS.md | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..83e12cf --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,308 @@ +# AGENTS.md — Doom Emacs Configuration + +This is a Doom Emacs 3 personal configuration at `~/.config/doom/`. + +## Repository Structure + +``` +doom/ +├── init.el # Module declarations (doom! macro) +├── config.el # Main config, loads modular files via load! +├── packages.el # Package declarations (package! macro) +├── core.el # Core settings and super-save +├── custom.el # Emacs custom variables (auto-generated) +├── security.el # Security settings +├── org.el # Org-mode configuration +├── metrics.el # Usage tracking (keyfreq) +├── theme.el # Theme configuration +├── inbox.el # Quick capture inbox +├── ai/ +│ ├── agents.el # Claude Code & Gemini CLI configuration +│ └── gptel.el # GPTel (ChatGPT) configuration +├── development/ +│ ├── lsp.el # LSP/LSP-UI configuration +│ ├── cpp.el # C++ development settings +│ ├── nix.el # Nix development settings +│ └── misc.el # Miscellaneous dev settings +├── docs/ +│ └── doom-macros-reference.md # Doom macro documentation +└── snippets/ # Yasnippet snippets +``` + +## Doom Commands + +### Essential Commands + +```bash +# Sync config (run after ANY change to init.el, packages.el, or package configs) +doom sync + +# Rebuild all packages +doom build + +# Diagnose issues +doom doctor + +# Update all packages +doom sync -u + +# Show verbose output +doom -v sync + +# Run in batch mode (for CI/testing) +emacs --batch -l ~/.config/doom/config.el --eval "(message \"test\")" +``` + +### Package Management + +```bash +# Force sync without prompts +doom sync -! + +# Clean up orphaned packages +doom sync --gc + +# Install packages only (no rebuild) +doom install +``` + +### Testing Individual Config Files + +```bash +# Load a specific config file and check for errors +emacs --batch -l ~/.config/emacs/bin/doom -l config.el -l ai/agents.el --eval "(message \"Loaded successfully\")" + +# Check Elisp syntax +emacs --batch --eval "(setq lexical-binding t)" -l ai/agents.el --eval "(message \"Syntax OK\")" +``` + +## Code Style Guidelines (Emacs Lisp) + +### File Headers + +Every `.el` file should start with a standard header: + +```elisp +;;; filename.el -*- lexical-binding: t; -*- + +;;; Commentary: +;;; Description of what this file does + +;;; Code: +``` + +### Lexical Binding + +Always use `lexical-binding: t` (note the dash, not underscore in the file-local variable). + +```elisp +;;; init.el -*- lexical-binding: t; -*- +``` + +### Naming Conventions + +| Element | Convention | Example | +|---------|------------|---------| +| Private functions | `+prefix--name` | `+org--restart-mode-h` | +| Hook functions | `+module-hook-function-h` | `+org-exclude-agenda-buffers-from-workspace-h` | +| Variables | `+module-variable-name` | `+org--restart-mode-h` | +| Package hooks | `-module-hook-function-h` | `-org-exclude-agenda-buffers-from-workspace-h` | +| Doom modules | `:module` | `:lang`, `:completion` | +| Module flags | `+flag` | `+orderless`, `+lsp` | +| Constants | `SCREAMING-SNAKE` | `MAX-HEIGHT` | + +### Keybinding Syntax (map!) + +```elisp +;; Basic keybindings +(map! :n "C-s" #'consult-line) + +;; With lambda +(map! :n "M-s" (lambda () (interactive) (consult-line (thing-at-point 'symbol)))) + +;; Leader key with prefix +(map! :leader + (:prefix ("C" . "claude-code") + :desc "Start Claude" "c" #'claude-code + :desc "Kill Claude" "k" #'claude-code-kill)) + +;; State modifiers: :n (normal), :v (visual), :i (insert), :e (emacs) +(map! :nv "C-j" #'something) +``` + +### use-package! vs use-package + +- Use `use-package!` in Doom configs (macro version) +- Use `use-package` when referring to the built-in package.el macro + +```elisp +;; Doom configuration +(use-package! org-roam + :after org + :custom + (org-roam-directory "~/org/roam") + :config + (org-roam-db-autosync-mode)) + +;; Standard Emacs (when needed) +(use-package org + :init + (setq org-todo-keywords '("TODO" "DONE")) + :config + (org-mode 1)) +``` + +### Hook Registration + +```elisp +;; Anonymous function with defun inside +(add-hook! 'org-agenda-finalize-hook + (defun +org-exclude-agenda-buffers-from-workspace-h () + "Don't associate temporary agenda buffers with current workspace." + (when org-agenda-new-buffers + (persp-remove-buffer org-agenda-new-buffers + (get-current-persp) + nil)))) + +;; :local makes hook buffer-local +(add-hook! :local 'some-mode-hook + (defun my-local-hook () + (do-something))) +``` + +### Conditional Loading + +```elisp +;; After package loads (preferred in Doom) +(after! lsp-ui + (setq lsp-ui-doc-enable t)) + +;; With feature check +(when (featurep! :system 'macos) + (setq mac-command-modifier 'meta)) + +;; After multiple packages +(after! (org org-roam) + (require 'org-roam-protocol)) +``` + +### Defcustom vs Defvar + +- Use `defcustom` for user-configurable settings that belong in `custom.el` +- Use `defvar` or `setq` for internal variables + +```elisp +;; In packages.el (for user customization) +(setq org-directory "~/org/") + +;; Not a defcustom unless it belongs in custom.el +``` + +### Error Handling + +```elisp +;; Use quiet! to suppress output +(quiet! (org-mode-restart)) + +;; Use fn! or #' for function references +(advice-add #'org-capture :around + (lambda (fun &rest args) + (letf! ((#'+org--restart-mode-h #'ignore)) + (apply fun args)))) + +;; Use ignore when function should do nothing +(defalias '+org--restart-mode-h #'ignore) +``` + +### Package Recipes (packages.el) + +```elisp +;; Simple package from Melpa +(package! super-save) + +;; GitHub recipe with custom files +(package! copilot + :recipe (:host github :repo "copilot-emacs/copilot.el" :files ("*.el"))) + +;; GitHub with exclusion patterns +(package! eat + :recipe (:host codeberg + :repo "akib/emacs-eat" + :files ("*.el" ("term" "term/*.el") "*.texi" + "*.ti" ("terminfo/e" "terminfo/e/*") + (:exclude ".dir-locals.el" "*-tests.el")))) + +;; Disable a package +(package! some-package :disable t) +``` + +## Common Patterns + +### Restart/Reload Functions + +```elisp +(defun +org--restart-mode-h () + "Restart org-mode on buffer switch." + (remove-hook 'doom-switch-buffer-hook #'+org--restart-mode-h 'local) + (cl-delete (current-buffer) org-agenda-new-buffers :test 'eq) + (quiet! (org-mode-restart)) + (run-hooks 'find-file-hook)) +``` + +### Advice Around Functions + +```elisp +(advice-add #'org-capture :around + (lambda (fun &rest args) + (letf! ((#'+org--restart-mode-h #'ignore)) + (apply fun args)))) +``` + +### Buffer Display Configuration + +```elisp +(add-to-list 'display-buffer-alist + '("^\\*claude" + (display-buffer-in-side-window) + (side . right) + (window-width . 90))) +``` + +### Environment Variables + +```elisp +;; Unset for subprocess access +(setenv "CLAUDECODE" nil) + +;; Set with path +(setenv "PATH" (concat "/usr/local/bin:" (getenv "PATH"))) +``` + +## Doom Module System + +The `init.el` uses the `doom!` macro to declare enabled modules: + +```elisp +(doom! :category + (module +flag) + :another-category) +``` + +Modules referenced in this config: +- `:completion` — Vertico, Corfu +- `:ui` — Doom dashboard, treemacs, workspaces +- `:editor` — Evil, format+, multiple-cursors +- `:emacs` — Dired, ibuffer, undo +- `:term` — Eshell, vterm +- `:checkers` — Syntax, spell +- `:tools` — LSP, magit, direnv, docker +- `:lang` — Python, Go, Rust, Org, JavaScript, etc. +- `:config` — Default bindings, smartparens + +## Important Notes + +1. Run `doom sync` after ANY change to `init.el`, `packages.el`, or `config.el` +2. Use `doom build` to rebuild if byte-compilation errors occur +3. This config uses straight.el for package management (via Doom) +4. Custom variables are auto-generated to `custom.el` — don't edit manually +5. The `load!` macro loads relative to `doom-private-dir` (this config directory)