aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archive/gptel/custom/gptel-prompts.el54
-rw-r--r--archive/gptel/gptel-tools/read_text_file.el4
-rw-r--r--custom/profile-dotemacs.el53
-rw-r--r--custom/titlecase-data.el92
-rw-r--r--custom/utilities/vcf-conversion-helpers.el3
-rw-r--r--modules/ai-term.el124
-rw-r--r--modules/calendar-sync.el74
-rw-r--r--modules/calibredb-epub-config.el45
-rw-r--r--modules/custom-comments.el61
-rw-r--r--modules/dev-fkeys.el47
-rw-r--r--modules/flycheck-config.el39
-rw-r--r--modules/flyspell-and-abbrev.el46
-rw-r--r--modules/font-config.el49
-rw-r--r--modules/jumper.el69
-rw-r--r--modules/keyboard-compat.el90
-rw-r--r--modules/mu4e-org-contacts-integration.el9
-rw-r--r--modules/mu4e-org-contacts-setup.el6
-rw-r--r--modules/music-config.el90
-rw-r--r--modules/org-agenda-config.el49
-rw-r--r--modules/org-webclipper.el47
-rw-r--r--modules/test-runner.el69
-rw-r--r--modules/video-audio-recording.el105
22 files changed, 187 insertions, 1038 deletions
diff --git a/archive/gptel/custom/gptel-prompts.el b/archive/gptel/custom/gptel-prompts.el
index a2b266f27..28197ceba 100644
--- a/archive/gptel/custom/gptel-prompts.el
+++ b/archive/gptel/custom/gptel-prompts.el
@@ -29,58 +29,12 @@
;; Boston, MA 02111-1307, USA.
;;; Commentary:
-
-;; This package provides enhanced prompt management capabilities for GPTel,
-;; allowing you to organize and dynamically load AI prompts from external
-;; files rather than hardcoding them in your Emacs configuration.
-
-;; Key Features:
-;;
-;; * Multi-format prompt support: Load prompts from .txt, .md, .org, .json,
-;; .eld (Emacs Lisp data), .el (Emacs Lisp functions), and .poet/.jinja
-;; (Prompt Poet/Jinja2 templates)
-;;
-;; * Template interpolation: Use Jinja2-style {{variable}} syntax with
-;; customizable variables and dynamic functions
-;;
-;; * File watching: Automatically reload prompts when files change
-;;
-;; * Project-aware prompts: Automatically load project-specific conventions
-;; from CONVENTIONS.md or CLAUDE.md files
;;
-;; * Conversation format support: Handle multi-turn conversations with
-;; system/user/assistant roles
-
-;; Setup:
-;;
-;; (use-package gptel-prompts
-;; :after (gptel)
-;; :custom
-;; (gptel-prompts-directory "~/my-prompts")
-;; :config
-;; (gptel-prompts-update)
-;; ;; Optional: auto-reload on file changes
-;; (gptel-prompts-add-update-watchers))
-
-;; File Formats:
-;;
-;; * Plain text (.txt, .md, .org): Used as-is for system prompts
-;; * JSON (.json): Array of {role: "system/user/assistant", content: "..."}
-;; * Emacs Lisp data (.eld): List format for conversations
-;; * Emacs Lisp code (.el): Lambda functions for dynamic prompts
-;; * Prompt Poet (.poet, .j2, .jinja, .jinja2): YAML + Jinja2 templates
-
-;; Template Variables:
-;;
-;; Use {{variable_name}} in your prompts. Variables can be defined in
-;; `gptel-prompts-template-variables' or generated dynamically by functions
-;; in `gptel-prompts-template-functions'.
-
-;; Project Integration:
+;; Adds file-backed GPTel directives. Prompt files can be plain text, structured
+;; conversations, Elisp data/functions, or Prompt Poet/Jinja templates.
;;
-;; Add `gptel-prompts-project-conventions' to `gptel-directives' to
-;; automatically load project-specific prompts from CONVENTIONS.md or
-;; CLAUDE.md files in your project root.
+;; The library can reload prompt files, interpolate configured template
+;; variables, and expose project-convention prompts from project roots.
;;; Code:
diff --git a/archive/gptel/gptel-tools/read_text_file.el b/archive/gptel/gptel-tools/read_text_file.el
index f35c94941..06a01db12 100644
--- a/archive/gptel/gptel-tools/read_text_file.el
+++ b/archive/gptel/gptel-tools/read_text_file.el
@@ -19,6 +19,10 @@
;; GNU General Public License for more details.
;;; Commentary:
+;;
+;; GPTel tool for safely reading text files under the user's home directory.
+;; It validates the resolved path, rejects directories and unreadable files,
+;; guards large files, and returns metadata alongside content.
;;; Code:
diff --git a/custom/profile-dotemacs.el b/custom/profile-dotemacs.el
index f16e8652f..8baee47b2 100644
--- a/custom/profile-dotemacs.el
+++ b/custom/profile-dotemacs.el
@@ -20,55 +20,16 @@
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
-
-;; This is to easily profile your Emacs init file (or any other
-;; script-like Emacs Lisp file, for that matter).
-
-;; It will go over all sexp's (balanced expressions) in the file and
-;; run them through `benchmark-run'. It will then show the file with
-;; overlays applied in a way that let you easily find out which sexp's
-;; take the most time. Since time is relative, it's not the absolute
-;; value that counts but the percentage of the total running time.
;;
-;; * All other sexp's with a percentage greater than
-;; `profile-dotemacs-low-percentage' will be preceded by a
-;; highlighted line, showing the results from `benchmark-run'.
-;; Also, the more 'reddish' the background of the sexp, the more
-;; time it needs.
-
-;; * All other sexp's will be grayed out to indicate that their
-;; running time is miniscule. You can still see the benchmark
-;; results in the minibuffer by hovering over the sexp with the
-;; mouse.
-
-;; You can only benchmark full sexp's, so if you wrapped large parts
-;; of your init file in some conditional clause, you'll have to remove
-;; that for getting finer granularity.
-
-;;; Usage:
-
-;; Start emacs as follows:
+;; Profiles profile-dotemacs-file by evaluating top-level sexps with
+;; benchmark-run, then overlays the source buffer so expensive forms stand out
+;; by percentage of total runtime.
;;
-;; emacs -Q -l <PATH>/profile-dotemacs.el -f profile-dotemacs
+;; Run with:
+;; emacs -Q -l /path/to/profile-dotemacs.el -f profile-dotemacs
;;
-;; with <PATH> being the path to where this file resides.
-
-;;; Caveats (thanks to Raffaele Ricciardi for reporting those):
-
-;; - The usual `--debug-init' for debugging your init file won't work
-;; with profile-dotemacs, so you'll have to call
-;; `toggle-debug-on-error', either on the commandline or at the
-;; beginning of your init file.
-;; - `load-file-name' is nil when the init file is being loaded
-;; by the profiler. This might matter if you perform the
-;; bulk of initializations in a different file.
-;; - Starting external shells like IELM or eshell in your init file
-;; might mess with overlay creation, so this must not be done.
-
-;;; Download:
-
-;; You can always get the latest version from
-;; http://randomsample.de/profile-dotemacs.el
+;; Full sexps are the unit of measurement; split large conditional blocks before
+;; profiling if finer detail is needed.
;;; Code:
diff --git a/custom/titlecase-data.el b/custom/titlecase-data.el
index a64685861..7415a2104 100644
--- a/custom/titlecase-data.el
+++ b/custom/titlecase-data.el
@@ -18,91 +18,13 @@
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
-
-;; Since the `titlecase' package requires a lot of data, that data lives here so
-;; as to not clog up the main package.
-
-;; Since [[https://github.com/duckwork/titlecase.el/issues/23][Issue #23]] makes
-;; a good point that I should like, make more sense in the commentary and README
-;; of this repository. At the same time, those couple of comments I wrote in
-;; there I don't want to just /delete/, so until I write this up in a proper
-;; blog post, I've included it here, in the data file, because this is where
-;; these implementation notes will be of most interest.
-
-;; The only setting you really should need to set is =titlecase-style=, which
-;; see. Each of these styles has a different set of rules regarding which words
-;; to capitalize in a title. After you've set =titlecase-style=, you can bind
-;; the command =titlecase-dwim= to a key, or call it using M-x, and it will
-;; either title-case your region (if it's active) or the current line.
-
-;; The tricky part is figuring out what words to capitalize in the title.
-
-;; Articles (~a~, ~an~, ~the~) are downcased.
-
-;; The first word of a title and all "important words" (generally nouns,
-;; pronouns, adjectives, verbs, and adverbs) are capitalized. The last word of
-;; a title is always capitalized, but only in Chicago, AP, Bluebook, AMA, NY
-;; Times, and Wikipedia.
-
-;; /All/ prepositions are downcased in Chicago, MLA, AP, NY Times, and
-;; Wikipedia, regardless of length; for APA, Bluebook, AMA, and Wikipedia, only
-;; prepositions shorter than 5 letters are (presumably, capitalize those longer
-;; than 5 letters, however only Wikipedia was clear on that point).
-
-;; Coordinating conjunctions are capitalized in Chicago and APA (presumably),
-;; but downcased in MLA, AP, Bluebook, AMA, NY Times, and Wikipedia.
-
-;; Hyphenated words are tricky: I could possibly figure out a way to have lookup
-;; tables to determine when to capitalize the second part of a hyphenated word,
-;; but I haven't implemented them yet. At any rate, the rules tend to be vague
-;; enough that it's hard to program anyway: For example, Chicago, APA, MLA, and
-;; AP lowercase the second word "after a hyphenated prefix (e.g., Mid-, Anti-,
-;; Super, etc.) in compound modifiers," but MLA and APA capitalize the second
-;; part of "hyphenated major words (e.g., Self-Report not Self-report).
-
-;; Perhaps unsurprisingly, the AMA (American Medical Association, used in the
-;; scientific community) has the most comprehensive capitalization rules around
-;; hyphenated words. I'll just copy-paste the bullet points here:
-
-;; - Lowercase the second word in a hyphenated compound when it is
-;; a prefix or suffix (e.g., "Anti-itch","world-wide") or part of a single word.
-;; - Capitalize the second word in a hyphenated compound if both words are equal
-;; and not suffices or prefixes (e.g., "Cost-Benefit")
-;; - Capitalize the first non-Greek letter after a lowercase Greek letter (e.g.,
-;; "ω-Bromohexanoic")
-;; - Lowercase the first non-Greek letter after a capital Greek letter (e.g.,
-;; "Δ-9-tetrahydrocannabinol") #+end_quote
-
-;; (The AMA also has a rule about capitilizing the genus but not species
-;; epithet, but the lookup on that would be wild as hell, so I trust yall to
-;; know on that one.)
-
-;; ~To~ as an infinitive is downcased in all /except/ AP. This is a rule I
-;; simply cannot implement without knowing whether the /next/ word is a verb,
-;; which would require expensive lookups, which even then wouldn't be foolproof.
-
-;; Now that I'm thinking about it, most styles count phrasal verbs (like "play
-;; with") as important enough to capitalize, when "with" would usually /not/ be
-;; capitalized, but again, open categories like phrasal verbs simply do not work
-;; in a package like this.
-
-;; ALL OF THIS IS TO SAY that titlecase offers a best-effort attempt to
-;; titlecase a line or region of text, but you should absolutely
-;; double-triple-check against the style guide you're writing for if you're
-;; trying for publication or something like that.
-
-;; SEE ALSO:
-
-;; Prior art:
-
-;; - https://emacs.stackexchange.com/questions/66361/#66362
-;; - https://github.com/novoid/title-capitalization.el
-;; - https://hungyi.net/posts/programmers-way-to-title-case/
-
-;; Rules:
-
-;; - https://capitalizemytitle.com/#capitalizationrules
-;; - https://titlecaseconverter.com/rules/
+;;
+;; Data tables for titlecase.el: style-specific lowercase word lists, phrasal
+;; verbs, and exceptions used by the title-casing engine.
+;;
+;; Title casing is best-effort because English style guides disagree and some
+;; cases require grammatical knowledge this package does not model. Proofread
+;; output before publication.
;;; Code:
diff --git a/custom/utilities/vcf-conversion-helpers.el b/custom/utilities/vcf-conversion-helpers.el
index 334edc4e2..d336eac8e 100644
--- a/custom/utilities/vcf-conversion-helpers.el
+++ b/custom/utilities/vcf-conversion-helpers.el
@@ -2,6 +2,9 @@
;;; Commentary:
;;
+;; Helpers for converting exported VCF contacts into org-contacts data. The
+;; cleaner normalizes folded fields, birthdays, item-prefixed email/phone fields,
+;; and removes cards without useful identifying data before import.
;;; Code:
diff --git a/modules/ai-term.el b/modules/ai-term.el
index 03c9a4046..4b2495715 100644
--- a/modules/ai-term.el
+++ b/modules/ai-term.el
@@ -1,4 +1,4 @@
-;;; ai-term.el --- In-Emacs AI-agent launcher with vertical-split terminal -*- lexical-binding: t; -*-
+;;; ai-term.el --- AI-agent terminals backed by EAT and tmux -*- lexical-binding: t; -*-
;; Author: Craig Jennings <c@cjennings.net>
@@ -7,70 +7,18 @@
;; Layer: 3 (Domain Workflow).
;; Category: D.
;; Load shape: eager.
-;; Eager reason: registers four global keys for the AI-agent terminal launcher; a
-;; command-loaded deferral candidate.
-;; Top-level side effects: four global key bindings.
-;; Runtime requires: cl-lib, seq, cj-window-geometry-lib, cj-window-toggle-lib,
-;; host-environment.
+;; Eager reason: binds M-SPC and the C-; a AI-agent prefix.
+;; Top-level side effects: global M-SPC binding and C-; a prefix map.
+;; Runtime requires: cl-lib, seq, window-toggle/geometry helpers, host-environment.
;; Direct test load: yes.
;;
-;; Picks an AI-agent project (a dir under ~/.emacs.d, ~/code/*, or
-;; ~/projects/* containing .ai/protocols.org), opens or reuses a terminal
-;; buffer named "agent [<basename>]", sends the agent's startup
-;; instruction to it, and routes the buffer to a side window via
-;; display-buffer-alist. When the frame already has a window forming the
-;; half the agent would occupy (a right column on a desktop, a bottom row
-;; on a laptop), the agent reuses that slot rather than splitting a third
-;; window in; toggling off restores the displaced buffer to the slot.
-;; Otherwise placement is a host-aware split: a right-side split at 50%
-;; width on a desktop, a bottom split at 75% height on a laptop (see
-;; `cj/--ai-term-default-direction'). Multiple
-;; projects produce multiple coexisting buffers that share the same
-;; slot; switching among them is a buffer-switch, not a
-;; kill-and-recreate.
+;; Opens project-scoped AI agents in EAT buffers backed by tmux sessions. Project
+;; candidates come from configured roots that contain .ai/protocols.org.
;;
-;; Each project's agent runs inside a tmux session named
-;; "<cj/ai-term-tmux-session-prefix><basename>" (default prefix "aiv-").
-;; The prefix lets `tmux ls' be filtered to AI-term's own sessions, so
-;; after an Emacs crash the project picker can match surviving sessions
-;; back to their directories: matched projects sort to the top of the
-;; picker (flagged "[detached]" -- session alive, no Emacs buffer -- or
-;; "[running]" when a live terminal buffer exists), the rest follow in
-;; alphabetical order.
-;;
-;; Four F-key entry points:
-;;
-;; - F9 `cj/ai-term' -- DWIM dispatch. If an agent buffer is
-;; currently displayed in this frame, F9 toggles it off: when it
-;; took over an existing window (a reused slot) the buffer it
-;; displaced returns to that slot, when it was split into its own
-;; window that window is removed, and when it fills the frame it
-;; is buried. Otherwise, if exactly one agent buffer is alive,
-;; F9 re-displays it; if zero or two-plus are alive, F9 falls
-;; through to the project picker.
-;; - C-F9 `cj/ai-term-pick-project' -- always show the project
-;; picker, even when an agent buffer is currently displayed.
-;; Used when the user wants to start a new project session
-;; instead of toggling the current one.
-;; - s-F9 `cj/ai-term-next' -- step to the next active agent in the
-;; queue. The queue is every active agent in buffer-name order
-;; (a stable rotation): attached agents (a live buffer) and
-;; detached ones (a live tmux session with no Emacs buffer).
-;; Stepping onto a detached agent attaches it. When an agent
-;; window is on screen, swap it to the next agent and focus it,
-;; wrapping after the last; when none is shown but agents exist,
-;; show the first. This is the "switch among existing agents"
-;; surface F9 deliberately doesn't provide.
-;; - M-F9 `cj/ai-term-close' -- gracefully close an agent: kill its
-;; tmux session (stopping the agent process), then its terminal
-;; buffer. Its window stays in the layout (swapped to the
-;; working buffer), so closing never collapses a split. Confirms
-;; first. Targets the current agent, the sole live agent, or
-;; prompts among several.
-;;
-;; Existing windmove (Shift-arrows) handles code <-> agent focus
-;; toggling. Buffer-move (C-M-arrows) handles side-swap. Neither
-;; needs anything new from this module.
+;; Agent display reuses the host-appropriate side slot when possible, otherwise
+;; splits right on desktop frames and below on laptop frames. Attached buffers
+;; and detached tmux sessions share the same rotation; selecting a detached
+;; agent recreates its EAT buffer and attaches to the live session.
;;; Code:
@@ -215,7 +163,7 @@ which the step materializes by attaching."
Walks `buffer-list' (most-recently-selected first) and returns the
first buffer that is not an AI-term agent buffer (per
`cj/--ai-term-buffer-p') and is not an internal buffer (name starting
-with a space). Used by the single-window F9 toggle-off so dismissing a
+with a space). Used by the single-window toggle-off so dismissing a
full-frame agent returns to the file the user was working in (e.g.
todo.org) rather than swapping in another agent."
(seq-find (lambda (b)
@@ -287,7 +235,7 @@ looked up in SESSIONS, so the lossy whitespace->hyphen transform in
(defun cj/--ai-term-launch-command (dir)
"Return the shell command line that runs the AI tool in a project tmux session.
-Uses `tmux new-session -A' so a second F9 on the same project reattaches
+Uses `tmux new-session -A' so a second toggle on the same project reattaches
to the running session instead of spawning a new one. The session name
comes from `cj/--ai-term-tmux-session-name'; the first window is named
`cj/ai-term-tmux-window-name' (default \"ai\") so a later hand-opened
@@ -452,7 +400,7 @@ direction applies. Captured at toggle-off by
`cj/--ai-term-display-saved'.")
(defvar cj/--ai-term-last-was-bury nil
- "Non-nil when the last F9 toggle-off used `bury-buffer'.
+ "Non-nil when the last toggle-off used `bury-buffer'.
Set by `cj/ai-term' in its `toggle-off' branch: t when the agent
window was the only window in the frame (so toggle-off buried
@@ -462,7 +410,7 @@ buried agent in the current window (the only one) or splitting per
the saved direction.")
(defvar cj/--ai-term-last-toggle-deleted-split nil
- "Non-nil when the last F9 toggle-off deleted the agent's own split window.
+ "Non-nil when the last toggle-off deleted the agent's own split window.
Set t by `cj/--ai-term-toggle-off' only when it actually `delete-window's
the agent (a multi-window layout where the agent had its own window);
@@ -474,7 +422,7 @@ working window at the edge, displacing its buffer and collapsing the layout
-- the toggle must be reversible (off then on returns the same windows).")
(defvar cj/--ai-term-last-hidden-buffer nil
- "The agent buffer hidden by the most recent F9 toggle-off.
+ "The agent buffer hidden by the most recent toggle-off.
Captured in `cj/ai-term' just before an agent window is torn down, and
consumed by `cj/--ai-term-dispatch' so the next toggle-on reopens the
@@ -520,7 +468,7 @@ cost of not auto-scaling if the frame itself resizes.")
"Capture WINDOW's direction and size into module-level state.
Sets `cj/--ai-term-last-direction' and `cj/--ai-term-last-size'
-so a subsequent F9 display can restore the user's chosen orientation
+so a subsequent display can restore the user's chosen orientation
and size. Called at toggle-off (just before the window is torn
down). The default direction is host-aware via
`cj/--ai-term-default-direction' (used only when WINDOW fills its
@@ -544,7 +492,7 @@ action in the chain runs.
This is more specific than `display-buffer-use-some-window', which
would happily steal any non-selected window (e.g. a code window
above the agent split) when the user is focused in agent and
-swaps projects via C-F9. The selective lookup here keeps non-agent
+swaps projects via C-; a s. The selective lookup here keeps non-agent
windows undisturbed and preserves the user's split geometry across
project changes."
(let ((win (cj/--ai-term-displayed-agent-window)))
@@ -598,10 +546,10 @@ When the prior toggle-off was a bury (single-window state, flagged
via `cj/--ai-term-last-was-bury') and the frame is still single-
window, restore the agent into the selected window in place rather
than splitting -- preserves the user's lone-window layout across
-F9 toggles.
+toggles.
Otherwise delegates to `cj/window-toggle-display-saved' against the
-F9 state vars, falling back to the host-aware defaults from
+toggle state vars, falling back to the host-aware defaults from
`cj/--ai-term-default-direction' and `cj/--ai-term-default-size'."
(cond
((and cj/--ai-term-last-was-bury (one-window-p))
@@ -627,7 +575,7 @@ through four actions in order:
2. `cj/--ai-term-reuse-existing-agent' -- otherwise, if any
window in this frame already shows an agent-prefixed buffer,
swap its buffer for the new one (preserves geometry across
- project changes via C-F9).
+ project changes via C-; a s).
3. `cj/--ai-term-reuse-edge-window' -- otherwise, if the frame
already has a window forming the half the agent would occupy
(the right column on a desktop, the bottom row on a laptop),
@@ -773,17 +721,17 @@ Signals `user-error' when no candidates exist."
(expand-file-name chosen)))))
(defun cj/--ai-term-dispatch ()
- "Compute the F9 (`cj/ai-term') action without performing it.
+ "Compute the `cj/ai-term' (C-; a a) action without performing it.
Returns one of:
- (toggle-off . WINDOW) -- agent is displayed in WINDOW; quit it.
- (redisplay-recent . BUFFER) -- 1+ alive agent buffers; show MRU.
- (pick-project) -- zero alive agent buffers; prompt.
-When 2+ agent buffers are alive, F9 redisplays the most-recently-
-selected one rather than opening the project picker. C-F9 is the
-explicit \"start a different project\" surface; M-F9 is the explicit
-\"switch among existing agents\" surface. F9 keeps a single, simple
+When 2+ agent buffers are alive, C-; a a redisplays the most-recently-
+selected one rather than opening the project picker. C-; a s is the
+explicit \"start a different project\" surface; C-; a n is the explicit
+\"switch among existing agents\" surface. C-; a a keeps a single, simple
job: toggle whichever agent was last in use.
A pure-decision helper so the dispatch logic is exercisable in tests
@@ -816,7 +764,7 @@ buffers; reinvoking on the same project reuses its existing terminal.
With prefix ARG, display the buffer without selecting its window.
-Bound to C-F9 -- always shows the project picker, even when an agent
+Bound to C-; a s -- always shows the project picker, even when an agent
buffer is currently displayed.
EAT renders in terminal frames as well as GUI frames, so this
@@ -842,7 +790,7 @@ the agent itself."
(other-buffer (window-buffer win) t)))))
(defun cj/--ai-term-toggle-off (win)
- "Hide the agent shown in WIN for an F9 toggle-off. Always returns nil.
+ "Hide the agent shown in WIN for a toggle-off. Always returns nil.
Two cases, by window count:
@@ -855,7 +803,7 @@ Two cases, by window count:
force a swap to a non-agent buffer to keep the toggle observable.
- Multi-window: collapse the agent split outright by deleting its window, so
- the working buffer (e.g. todo.org) reclaims the space. F9 is a pure
+ the working buffer (e.g. todo.org) reclaims the space. The toggle is a pure
show/hide toggle of THE agent split -- it must never surface a different
agent. `quit-restore-window' can't guarantee that here: switching among
several agents reuses the one slot via `set-window-buffer' (see
@@ -897,21 +845,21 @@ Two cases, by window count:
nil)
(defun cj/ai-term (&optional arg)
- "Smart F9 dispatch for the AI-term launcher.
+ "DWIM dispatch for the AI-term launcher. Bound to C-; a a.
Behavior depends on the current state:
-- If an AI-term buffer is currently displayed in this frame, F9
+- If an AI-term buffer is currently displayed in this frame, it
quits its window (toggle off, buffer stays alive).
-- Else, if exactly one alive AI-term buffer exists, F9 re-displays
+- Else, if exactly one alive AI-term buffer exists, it re-displays
it (DWIM -- the obvious next step is to look at it).
-- Else (zero or 2+), F9 falls through to `cj/ai-term-pick-project'.
+- Else (zero or 2+), it falls through to `cj/ai-term-pick-project'.
With prefix ARG, display the buffer without selecting its window
when a buffer is being shown (no effect on the toggle-off branch).
-See `cj/ai-term-pick-project' (C-F9) to force the project picker.
-M-F9 closes an agent via `cj/ai-term-close'."
+See `cj/ai-term-pick-project' (C-; a s) to force the project picker.
+C-; a k closes an agent via `cj/ai-term-close'."
(interactive "P")
(pcase (cj/--ai-term-dispatch)
(`(toggle-off . ,win)
@@ -945,7 +893,7 @@ Derives the tmux session name from BUFFER's `default-directory' (the
project dir the terminal was created in) and kills it so the agent
process stops. When BUFFER is shown, swaps its window to a non-agent
buffer (the working file) rather than deleting the window -- closing an
-agent must not collapse the user's window layout; the F9 hide toggle is
+agent must not collapse the user's window layout; the hide toggle is
what collapses the split. Then kills BUFFER (suppressing the
process-still-running prompt -- the session is already down). No-op
when BUFFER isn't an AI-term buffer."
@@ -984,7 +932,7 @@ buffers; nil when none are alive."
Targets the current agent buffer, the sole live agent, or prompts when
several are alive (see `cj/--ai-term-close-target'). Asks for
confirmation first -- this kills the running agent process, which can
-interrupt work in progress. Bound to M-<f9>."
+interrupt work in progress. Bound to C-; a k."
(interactive)
(let ((buffer (cj/--ai-term-close-target)))
(unless buffer
diff --git a/modules/calendar-sync.el b/modules/calendar-sync.el
index c0e0e935a..b684330c8 100644
--- a/modules/calendar-sync.el
+++ b/modules/calendar-sync.el
@@ -8,75 +8,17 @@
;; Layer: 3 (Domain Workflow).
;; Category: D/S.
;; Load shape: eager only when calendar-sync.local.el configures calendars.
-;; Eager reason: daily-driver workflow; calendars are expected synced at the
-;; first session. Timers and network fetches are guarded for batch/test loads.
-;; Top-level side effects: defines a calendar keymap and conditionally registers
-;; it under cj/custom-keymap; timer and network fetches guarded by
-;; config/noninteractive checks.
+;; Eager reason: daily agenda workflow; timers and network fetches are guarded.
+;; Top-level side effects: defines C-; g map; starts sync only when configured.
;; Runtime requires: cl-lib, subr-x, system-lib, cj-org-text-lib, keybindings.
-;; Direct test load: yes (private config optional; degrades cleanly when absent).
+;; Direct test load: yes.
;;
-;; Simple, reliable one-way sync from multiple calendars to Org mode.
-;; Downloads .ics files from calendar URLs (Google, Proton, etc.) and
-;; converts to Org format. No OAuth, no API complexity, just file conversion.
+;; One-way calendar synchronization from configured .ics/API sources into Org
+;; files. Feed URLs may be inline or resolved from auth-source via :secret-host.
;;
-;; Features:
-;; - Multi-calendar support (sync multiple calendars to separate files)
-;; - Pure Emacs Lisp .ics parser (no external dependencies)
-;; - Recurring event support (RRULE expansion)
-;; - Timer-based automatic sync (every 60 minutes, configurable)
-;; - Self-contained in .emacs.d (no cron, portable across machines)
-;; - Read-only (can't corrupt source calendars)
-;; - Works with Chime for event notifications
-;;
-;; Recurring Events (RRULE):
-;;
-;; Calendar recurring events are defined once with an RRULE
-;; (recurrence rule) rather than as individual event instances. This
-;; module expands recurring events into individual org entries.
-;;
-;; Expansion uses a rolling window approach:
-;; - Past: 3 months before today
-;; - Future: 12 months after today
-;;
-;; Every sync regenerates the entire file based on the current date,
-;; so the window automatically advances as time passes. Old events
-;; naturally fall off after 3 months, and new future events appear
-;; as you approach them.
-;;
-;; Supported RRULE patterns:
-;; - FREQ=DAILY: Daily events
-;; - FREQ=WEEKLY;BYDAY=MO,WE,FR: Weekly on specific days
-;; - FREQ=MONTHLY: Monthly events (same day each month)
-;; - FREQ=YEARLY: Yearly events (anniversaries, birthdays)
-;; - INTERVAL: Repeat every N periods (e.g., every 2 weeks)
-;; - UNTIL: End date for recurrence
-;; - COUNT: Maximum occurrences (combined with date range limit)
-;;
-;; Setup:
-;; 1. Configure calendars in your init.el:
-;; (setq calendar-sync-calendars
-;; '((:name "google"
-;; :url "https://calendar.google.com/calendar/ical/.../basic.ics"
-;; :file gcal-file)
-;; (:name "proton"
-;; :url "https://calendar.proton.me/api/calendar/v1/url/.../calendar.ics"
-;; :file pcal-file)))
-;;
-;; 2. Load and start:
-;; (require 'calendar-sync)
-;; (calendar-sync-start)
-;;
-;; 3. Add to org-agenda (optional):
-;; (dolist (cal calendar-sync-calendars)
-;; (add-to-list 'org-agenda-files (plist-get cal :file)))
-;;
-;; Usage:
-;; - M-x calendar-sync-now ; Sync all or select specific calendar
-;; - M-x calendar-sync-start ; Start auto-sync
-;; - M-x calendar-sync-stop ; Stop auto-sync
-;; - M-x calendar-sync-toggle ; Toggle auto-sync
-;; - M-x calendar-sync-status ; Show sync status for all calendars
+;; The parser expands recurring events into a rolling window around today,
+;; regenerates target Org files on each sync, and keeps source calendars
+;; read-only. Commands under C-; g start, stop, toggle, inspect, and run syncs.
;;; Code:
diff --git a/modules/calibredb-epub-config.el b/modules/calibredb-epub-config.el
index f833c2503..cd8101db1 100644
--- a/modules/calibredb-epub-config.el
+++ b/modules/calibredb-epub-config.el
@@ -6,46 +6,17 @@
;; Layer: 4 (Optional).
;; Category: O/D/P.
;; Load shape: eager.
-;; Eager reason: none; optional ebook workflow, a command-loaded deferral
-;; candidate for Phase 4.
-;; Top-level side effects: one add-hook, one advice-add, package config.
-;; Runtime requires: user-constants, subr-x.
+;; Eager reason: none; ebook commands can load by command.
+;; Top-level side effects: one hook, one advice, package config.
+;; Runtime requires: user-constants, subr-x, transient.
;; Direct test load: yes.
;;
-;; This module provides a comprehensive ebook management and reading experience
-;; within Emacs, integrating CalibreDB for library management and Nov for EPUB
-;; reading.
+;; CalibreDB and Nov integration for browsing the Calibre library and reading
+;; EPUBs inside Emacs. The module adds a curated CalibreDB transient, filter
+;; helpers, Nov typography, image centering, and reader-to-library navigation.
;;
-;; FEATURES:
-;; - CalibreDB integration for managing your Calibre ebook library
-;; - Nov mode for reading EPUB files with customized typography and layout
-;; - Seamless navigation between Nov reading buffers and CalibreDB entries
-;; - Image centering in EPUB documents without modifying buffer text
-;; - Quick filtering and searching within your ebook library
-;;
-;; KEY BINDINGS:
-;; - M-B: Open CalibreDB library browser
-;; - In CalibreDB search mode:
-;; - l: Filter by tag
-;; - L: Clear all filters
-;; - In Nov mode:
-;; - z: Open current EPUB in external viewer (zathura)
-;; - C-c C-b: Jump to CalibreDB entry for current book
-;; - m: Set bookmark
-;; - b: List bookmarks
-;;
-;; WORKFLOW:
-;; 1. Press M-B to browse your Calibre library
-;; 2. Use filters (l for tags, L to clear) to narrow results
-;; 3. Open an EPUB to read it in Nov with optimized typography
-;; 4. While reading, use C-c C-b to jump back to the book's metadata
-;; 5. Use z to open in external reader when needed
-;;
-;; CONFIGURATION NOTES:
-;; - Prefers EPUB format when available, falls back to PDF
-;; - Centers images in EPUB documents using display properties
-;; - Applies custom typography with larger fonts for comfortable reading
-;; - Uses visual-fill-column for centered text with appropriate margins
+;; EPUB is preferred when available; external opening remains available for
+;; formats or workflows better handled outside Emacs.
;;; Code:
diff --git a/modules/custom-comments.el b/modules/custom-comments.el
index 231a03860..a2604a558 100644
--- a/modules/custom-comments.el
+++ b/modules/custom-comments.el
@@ -5,62 +5,17 @@
;; Layer: 2 (Core UX).
;; Category: L/C.
;; Load shape: eager.
-;; Eager reason: registers its C-; C comment submap at load. Currently eager by
-;; init order; a deferral candidate for Phase 3/4 (command/autoload +
-;; registration API).
-;; Top-level side effects: defines cj/comment-map, registers it under C-; C.
+;; Eager reason: registers C-; C comment helpers.
+;; Top-level side effects: defines and registers cj/comment-map.
;; Runtime requires: keybindings.
-;; Direct test load: yes (requires keybindings explicitly).
+;; Direct test load: yes.
;;
-;; This module provides custom comment formatting and manipulation utilities for code editing.
-;;
-;; Functions include:
-;; - deleting all comments in a buffer,
-;; - reformatting commented text into single-line paragraphs,
-;; - creating centered comment headers with customizable separator characters,
-;; - creating comment boxes around text
-;; - inserting hyphen-style centered comments.
-;;
-;; These utilities help create consistent, well-formatted code comments and section headers.
-;; Bound to keymap prefix: C-; C
-;;
-;; Comment Style Patterns:
-;;
-;; inline-border:
-;; ========== inline-border ==========
-;;
-;; simple-divider:
-;; ====================================
-;; simple-divider
-;; ====================================
-;;
-;; padded-divider:
-;; ====================================
-;; padded-divider
-;; ====================================
-;;
-;; box:
-;; ************************************
-;; * box *
-;; ************************************
-;;
-;; heavy-box:
-;; ************************************
-;; * *
-;; * heavy-box *
-;; * *
-;; ************************************
-;;
-;; unicode-box:
-;; ┌──────────────────────────────────┐
-;; │ unicode-box │
-;; └──────────────────────────────────┘
-;;
-;; block-banner:
-;; /************************************
-;; * block-banner
-;; ************************************/
+;; Comment editing helpers: delete comments, reflow commented regions, and insert
+;; consistent section headers or boxes using the current mode's comment syntax.
;;
+;; Public commands live under C-; C. Decoration helpers validate single printable
+;; characters before generating comment borders.
+
;;; Code:
(require 'keybindings) ;; provides cj/custom-keymap
diff --git a/modules/dev-fkeys.el b/modules/dev-fkeys.el
index 9fdfa5b3f..80b43600b 100644
--- a/modules/dev-fkeys.el
+++ b/modules/dev-fkeys.el
@@ -5,48 +5,17 @@
;; Layer: 2 (Core UX).
;; Category: C.
;; Load shape: eager.
-;; Eager reason: the F4/F6 developer command entry points.
-;; Top-level side effects: six global F-key bindings; conditionally registers a
-;; C-; P binding.
+;; Eager reason: binds the F4/F6 developer command entry points.
+;; Top-level side effects: global F-key bindings and optional C-; P binding.
;; Runtime requires: cl-lib, system-lib, keybindings.
-;; Direct test load: yes (requires keybindings explicitly).
+;; Direct test load: yes.
;;
-;; Project-aware F-key block for developer workflows:
+;; Project-aware F-key dispatchers. F4 chooses compile/run/clean commands by
+;; project markers; C-F4 and M-F4 are fast paths. F6 runs all project tests or
+;; the current file's tests using language-specific command builders.
;;
-;; F4 completing-read of compile/run candidates filtered by project type
-;; C-F4 fast path: compile only (no-op on interpreted projects)
-;; M-F4 fast path: clean + rebuild (no-op on interpreted projects)
-;; S-F4 recompile (built-in)
-;; F6 completing-read of test candidates: All tests / Current file's tests
-;; C-F6 fast path: current file's tests
-;;
-;; F4 project-type detection runs against the projectile root and falls back
-;; to \\='unknown when no marker matches. Interpreted markers are checked
-;; before compiled markers, so a Python or Node project that also has a
-;; Makefile for tasks classifies as interpreted.
-;;
-;; F6 \"All tests\" delegates to `projectile-test-project'. F6 \"Current
-;; file's tests\" detects the language by extension, derives the runner
-;; command (elisp via the project Makefile, Python via pytest, Go via the
-;; package), and pipes through `compile' from the projectile root.
-;; TypeScript / JavaScript are detected but punted for v1 — the function
-;; signals a user-error rather than guessing a runner.
-;;
-;; M-F6 is reserved for Phase 2b (\"Run a test...\" menu entry with
-;; per-language test-name discovery). Phase 2b also adds buffer-local
-;; last-test memory and tree-sitter-based discovery for Python / Go /
-;; TypeScript. The tree-sitter discovery uses a capture-then-filter pattern
-;; (queries without `:match' / `:equal' / `:pred' predicates, with the
-;; pattern filter applied in Elisp) to sidestep Emacs bug #79687 — Emacs
-;; 30.2 emits unsuffixed `#match' predicates that libtree-sitter 0.26
-;; rejects. The fix lives on Emacs master (commit b0143530) and is
-;; targeted at Emacs 31; it has not been backported to the emacs-30
-;; branch as of 2026-05-03. See Mike Olson's writeup at
-;; https://mwolson.org/blog/emacs/2026-04-20-fixing-typescript-ts-mode-in-emacs-30-2/
-;; for the same workaround applied to font-lock.
-;;
-;; F7 (coverage) is wired in coverage-core.el. F5 is reserved for the debug
-;; ticket and intentionally left unbound here.
+;; Interpreted markers win over compiled markers so task Makefiles do not turn
+;; Python/Node projects into compile-first projects.
;;; Code:
diff --git a/modules/flycheck-config.el b/modules/flycheck-config.el
index 1afd3ae6c..613817444 100644
--- a/modules/flycheck-config.el
+++ b/modules/flycheck-config.el
@@ -6,40 +6,17 @@
;; Layer: 2 (Core UX).
;; Category: C/P.
;; Load shape: eager.
-;; Eager reason: general linting setup; spec target is hook-loaded, a deferral
-;; candidate.
-;; Top-level side effects: package configuration via use-package, binds into
-;; cj/custom-keymap through use-package :map.
+;; Eager reason: linting keymap and mode hooks; could become hook-loaded.
+;; Top-level side effects: package config and C-; ? binding.
;; Runtime requires: keybindings.
-;; Direct test load: yes (requires keybindings explicitly).
+;; Direct test load: yes.
;;
-;; This file configures Flycheck for on-demand syntax and grammar checking.
-;; - Flycheck starts automatically only in sh-mode and emacs-lisp-mode
-
-;; - This binds a custom helper (=cj/flycheck-list-errors=) to "C-; ?"
-;; for popping up Flycheck's error list in another window.
-
-;; - It also customizes Checkdoc to suppress only the "sentence-end-double-space"
-;; and "warn-escape" warnings.
-
-;; - It registers LanguageTool for comprehensive grammar checking of prose files
-;; (text-mode, markdown-mode, gfm-mode, org-mode).
-
-;; Note: Grammar checking is on-demand only to avoid performance issues.
-;; Hitting "C-; ?" runs cj/flycheck-prose-on-demand if in an org buffer.
-
-;; The cj/flycheck-prose-on-demand function:
-;; - Turns on flycheck for the local buffer
-;; - Enables LanguageTool checker
-;; - Triggers an immediate check
-;; - Displays errors in the *Flycheck errors* buffer
-
-;; Installation:
-;; On Arch Linux:
-;; sudo pacman -S languagetool
+;; Flycheck configuration for automatic shell/Elisp linting and on-demand prose
+;; grammar checks. C-; ? opens the Flycheck error list, enabling prose checking
+;; first when appropriate.
;;
-;; The wrapper script at scripts/languagetool-flycheck formats LanguageTool's
-;; JSON output into flycheck-compatible format. It requires Python 3.
+;; LanguageTool uses scripts/languagetool-flycheck to adapt JSON output to
+;; Flycheck's checker protocol.
;;; Code:
diff --git a/modules/flyspell-and-abbrev.el b/modules/flyspell-and-abbrev.el
index 376a9dc51..b73bfdf32 100644
--- a/modules/flyspell-and-abbrev.el
+++ b/modules/flyspell-and-abbrev.el
@@ -6,48 +6,18 @@
;; Layer: 2 (Core UX).
;; Category: C/P.
;; Load shape: eager.
-;; Eager reason: text-mode spelling and abbrev hooks; spec target is hook-loaded.
-;; Top-level side effects: package configuration via use-package (mode hooks).
+;; Eager reason: text-mode spelling and abbrev hooks.
+;; Top-level side effects: package configuration via use-package.
;; Runtime requires: cl-lib.
;; Direct test load: yes.
;;
-;; WORKFLOW:
-;; This module provides intelligent spell checking with automatic abbreviation
-;; creation to prevent repeated misspellings.
+;; On-demand Flyspell workflow with automatic abbrev creation from accepted
+;; corrections. C-' checks/corrects nearby misspellings; C-c f toggles Flyspell
+;; with mode-aware behavior.
;;
-;; KEYBINDINGS:
-;; C-' - Main spell check interface (cj/flyspell-then-abbrev)
-;; C-c f - Toggle flyspell on/off (cj/flyspell-toggle)
-;; M-o - Access 'other options' during correction (save to dictionary, etc.)
-;;
-;; SPELL CHECKING WORKFLOW:
-;; 1. Press C-' to start spell checking
-;; 2. Finds the nearest misspelled word above the cursor
-;; 3. Prompts for correction or allows saving to personal dictionary
-;; 4. Press C-' again to move to the next misspelling
-;; 5. Each correction automatically creates an abbrev for future auto-expansion
-;;
-;; FLYSPELL ACTIVATION:
-;; Flyspell is NOT automatically enabled. You activate it manually:
-;; - C-c f - Toggle flyspell on (uses smart mode detection) or off
-;; - C-' - Runs flyspell-buffer then starts correction workflow
-;;
-;; When enabled, flyspell adapts to the buffer type:
-;; - Programming modes (prog-mode): Only checks comments and strings
-;; - Text modes (text-mode): Checks all text
-;; - Other modes: Must enable manually with C-c f
-;;
-;; ABBREVIATION AUTO-EXPANSION:
-;; Each spell correction creates an abbrev that auto-expands the misspelling
-;; to the correct spelling when you type it in the future. This significantly
-;; increases typing speed over time.
-;;
-;; Original idea from Artur Malabarba:
-;; http://endlessparentheses.com/ispell-and-abbrev-the-perfect-auto-correct.html
-;;
-;; NOTES:
-;; The default flyspell keybinding "C-;" is unbound in this config as it's
-;; used for the custom keymap (cj/custom-keymap).
+;; Flyspell is not enabled globally. Programming buffers check comments/strings
+;; when enabled; prose buffers check all text. The default C-; Flyspell binding
+;; is intentionally left free for cj/custom-keymap.
;;; Code:
diff --git a/modules/font-config.el b/modules/font-config.el
index 3272a946e..cb060b7be 100644
--- a/modules/font-config.el
+++ b/modules/font-config.el
@@ -6,51 +6,18 @@
;; Layer: 2 (Core UX).
;; Category: C/P/S.
;; Load shape: eager.
-;; Eager reason: font setup for the first frame, plus font keybindings.
-;; Top-level side effects: binds five global font keys, runs font-installation
-;; checks, configures packages via use-package.
+;; Eager reason: first-frame font setup and font keybindings.
+;; Top-level side effects: font keys, font checks, package config.
;; Runtime requires: host-environment, keybindings.
;; Direct test load: yes.
;;
-;; This module provides font configuration, including:
-;;
-;; 1. Font Management:
-;; - Dynamic font preset switching via `fontaine' package
-;; - Separate configurations for fixed-pitch and variable-pitch fonts
-;; - Multiple size presets for different viewing contexts
-;; - Per-frame font configuration tracking for daemon mode compatibility
-;;
-;; 2. Icon Support:
-;; - All-the-icons integration with automatic font installation
-;; - Nerd fonts support for enhanced icons in terminals and GUI
-;; - Platform-specific emoji font configuration (Noto, Apple, Segoe)
-;; - Emojify package for emoji rendering and insertion
-;;
-;; 3. Typography Enhancements:
-;; - Programming ligatures via `ligature' package
-;; - Mode-specific ligature rules for markdown and programming
-;; - Text scaling keybindings for quick size adjustments
-;;
-;; 4. Utility Functions:
-;; - `cj/font-installed-p': Check font availability
-;; - `cj/display-available-fonts': Interactive font browser with samples
-;; - Frame-aware font application for client/server setups
-;;
-;; Configuration Notes:
-;; - Default preset: BerkeleyMono Nerd Font; height 120 on laptops, 140 on desktops
-;; - Variable pitch: Lexend in the default preset; Merriweather for fallback presets
-;; - Handles both standalone and daemon mode Emacs instances
-;; - Emoji fonts selected based on OS availability
-;;
-;; Keybindings:
-;; - M-S-f: Select font preset (fontaine-set-preset)
-;; - C-z F: Display available fonts
-;; - C-+/C-=: Increase text scale
-;; - C--/C-_: Decrease text scale
-;; - C-c E i: Insert emoji
-;; - C-c E l: List emojis
-;;
+;; Configures fontaine presets, text scaling keys, icon/emoji fonts, and
+;; programming ligatures. Presets are applied per frame so daemon clients get
+;; the intended fixed/variable pitch sizes.
;;
+;; Also carries font-rendering safeguards for known HarfBuzz/font-cache crashes
+;; triggered by emoji and Arabic shaping in this setup.
+
;;; Code:
(require 'host-environment)
diff --git a/modules/jumper.el b/modules/jumper.el
index 61b6464a5..1fbd1293b 100644
--- a/modules/jumper.el
+++ b/modules/jumper.el
@@ -11,72 +11,17 @@
;; Layer: 4 (Optional).
;; Category: O/L.
;; Load shape: eager.
-;; Eager reason: none; navigation helper, a command-loaded deferral candidate.
-;; Top-level side effects: defines a jumper keymap.
+;; Eager reason: none; jump commands can autoload.
+;; Top-level side effects: defines jumper keymap.
;; Runtime requires: cl-lib.
;; Direct test load: yes.
;;
-;; Jumper provides a simple way to store and jump between locations
-;; in your codebase without needing to remember register assignments.
+;; Small register-backed jump list. Locations are stored in numbered registers,
+;; shown through completion with file/line context, and removed explicitly when
+;; no longer useful.
;;
-;; PURPOSE:
-;;
-;; When working on large codebases, you often need to jump between
-;; multiple related locations: a function definition, its tests, its
-;; callers, configuration files, etc. Emacs registers are perfect for
-;; this, but require you to remember which register you assigned to
-;; which location. Jumper automates register management, letting you
-;; focus on your work instead of bookkeeping.
-;;
-;; WORKFLOW:
-;;
-;; 1. Navigate to an important location in your code
-;; 2. Press M-SPC SPC to store it (automatically assigned to register 0)
-;; 3. Continue working, storing more locations as needed (registers 1-9)
-;; 4. Press M-SPC j to jump back to any stored location
-;; 5. Select from the list using completion (shows file, line, context)
-;; 6. Press M-SPC d to remove locations you no longer need
-;;
-;; RECOMMENDED USAGE:
-;;
-;; Store locations temporarily while working on a feature:
-;; - Store the main function you're implementing
-;; - Store the test file where you're writing tests
-;; - Store the caller that needs updating
-;; - Store the documentation that needs changes
-;; - Jump between them freely as you work
-;; - Clear them when done with the feature
-;;
-;; SPECIAL BEHAVIORS:
-;;
-;; - Duplicate prevention: Storing the same location twice shows a message
-;; instead of wasting a register slot.
-;;
-;; - Single location toggle: When only one location is stored, M-SPC j
-;; toggles between that location and your current position. Perfect for
-;; rapid back-and-forth between two related files.
-;;
-;; - Last location tracking: The last position before each jump is saved
-;; in register 'z', allowing quick "undo" of navigation.
-;;
-;; - Smart selection: With multiple locations, completing-read shows
-;; helpful context: "[0] filename.el:42 - function definition..."
-;;
-;; KEYBINDINGS:
-;;
-;; M-SPC SPC Store current location in next available register
-;; M-SPC j Jump to a stored location (with completion)
-;; M-SPC d Delete a stored location from the list
-;;
-;; CONFIGURATION:
-;;
-;; You can customize the prefix key and maximum locations:
-;;
-;; (setq jumper-prefix-key "C-c j") ; Change prefix key
-;; (setq jumper-max-locations 20) ; Store up to 20 locations
-;;
-;; Note: Changing jumper-max-locations requires restarting Emacs or
-;; manually reinitializing jumper--registers.
+;; A single stored location toggles with the current point; each jump records the
+;; previous point in register z for a quick return path.
;;; Code:
diff --git a/modules/keyboard-compat.el b/modules/keyboard-compat.el
index 914a343a6..172f96c7b 100644
--- a/modules/keyboard-compat.el
+++ b/modules/keyboard-compat.el
@@ -6,90 +6,18 @@
;; Layer: 1 (Foundation).
;; Category: F/S.
;; Load shape: eager.
-;; Eager reason: normalizes terminal/GUI key input so the first session's
-;; keybindings resolve consistently.
-;; Top-level side effects: adds `cj/keyboard-compat-terminal-setup' to
-;; `emacs-startup-hook'.
+;; Eager reason: normalizes terminal/GUI key input before custom bindings matter.
+;; Top-level side effects: adds cj/keyboard-compat-terminal-setup to startup.
;; Runtime requires: host-environment.
-;; Direct test load: yes (registers a startup hook; batch-safe).
+;; Direct test load: yes.
;;
-;; This module fixes keyboard input differences between terminal and GUI Emacs.
+;; Normalizes Meta+Shift bindings across GUI and terminal frames. GUI frames
+;; translate M-uppercase events to explicit M-S-lowercase keys; terminal frames
+;; decode arrow escape sequences before key lookup so ESC O prefixes do not trip
+;; M-S bindings.
;;
-;; THE PROBLEM: Meta+Shift keybindings behave differently in terminal vs GUI
-;; =========================================================================
-;;
-;; In Emacs, there are two ways to express "Meta + Shift + o":
-;;
-;; 1. M-O (Meta + uppercase O) - key code 134217807
-;; 2. M-S-o (Meta + explicit Shift modifier + lowercase o) - key code 167772271
-;;
-;; These are NOT the same key in Emacs!
-;;
-;; GUI Emacs behavior:
-;; When you press Meta+Shift+o on your keyboard, GUI Emacs receives M-O
-;; (uppercase O). It does NOT receive M-S-o. This is because the keyboard
-;; sends Shift+o as uppercase 'O', not as a Shift modifier plus lowercase 'o'.
-;;
-;; Terminal Emacs behavior:
-;; Terminals send escape sequences for special keys. Arrow keys send:
-;; - Up: ESC O A
-;; - Down: ESC O B
-;; - Right: ESC O C
-;; - Left: ESC O D
-;;
-;; The problem: ESC O is interpreted as M-O by Emacs! So if you bind M-O
-;; to a function, pressing the up arrow sends "ESC O A", Emacs sees "M-O"
-;; and triggers your function instead of moving up. Arrow keys break.
-;;
-;; THE SOLUTION: Different handling for each display type
-;; ======================================================
-;;
-;; For terminal mode (handled by cj/keyboard-compat-terminal-setup):
-;; - Use input-decode-map to translate arrow escape sequences BEFORE
-;; any keybinding lookup. ESC O A becomes [up], not M-O followed by A.
-;; - Keybindings use M-S-o syntax (some terminals support explicit Shift)
-;; - Disable graphical icons that show as unicode artifacts
-;;
-;; For GUI mode (handled by cj/keyboard-compat-gui-setup):
-;; - Use key-translation-map to translate M-O to M-S-o BEFORE lookup
-;; - This way, pressing Meta+Shift+o (which sends M-O) gets translated
-;; to M-S-o, matching the keybinding definitions
-;; - All 18 Meta+Shift keybindings work correctly
-;;
-;; WHY NOT JUST USE M-O FOR KEYBINDINGS?
-;; =====================================
-;;
-;; We could bind to M-O directly, but:
-;; 1. Terminal arrow keys would break (ESC O prefix conflict)
-;; 2. We'd need to maintain two sets of bindings (M-O for GUI, something
-;; else for terminal)
-;;
-;; By using M-S-o syntax everywhere and translating M-O -> M-S-o in GUI mode,
-;; we have one consistent set of keybindings that work everywhere.
-;;
-;; KEYBINDINGS AFFECTED:
-;; ====================
-;;
-;; The following M-S- keybindings are translated from M-uppercase in GUI:
-;;
-;; M-O -> M-S-o cj/kill-other-window (undead-buffers.el)
-;; M-M -> M-S-m cj/kill-all-other-buffers-and-windows (undead-buffers.el)
-;; M-Y -> M-S-y yank-media (keybindings.el)
-;; M-F -> M-S-f fontaine-set-preset (font-config.el)
-;; M-W -> M-S-w wttrin (weather-config.el)
-;; M-E -> M-S-e eww (eww-config.el)
-;; M-L -> M-S-l cj/switch-themes (ui-theme.el)
-;; M-R -> M-S-r cj/elfeed-open (elfeed-config.el)
-;; M-V -> M-S-v cj/split-and-follow-right (ui-navigation.el)
-;; M-H -> M-S-h cj/split-and-follow-below (ui-navigation.el)
-;; M-T -> M-S-t toggle-window-split (ui-navigation.el)
-;; M-Z -> M-S-z cj/undo-kill-buffer (ui-navigation.el)
-;; M-U -> M-S-u winner-undo (ui-navigation.el)
-;; M-D -> M-S-d dwim-shell-commands-menu (dwim-shell-config.el)
-;; M-I -> M-S-i edit-indirect-region (text-config.el)
-;; M-C -> M-S-c time-zones (chrono-tools.el)
-;; M-B -> M-S-b calibredb (calibredb-epub-config.el)
-;; M-K -> M-S-k show-kill-ring (show-kill-ring.el)
+;; Also provides terminal-specific display fallbacks, such as hiding icon glyphs
+;; that render poorly outside GUI frames.
;;; Code:
diff --git a/modules/mu4e-org-contacts-integration.el b/modules/mu4e-org-contacts-integration.el
index daa12701a..6062b8cf5 100644
--- a/modules/mu4e-org-contacts-integration.el
+++ b/modules/mu4e-org-contacts-integration.el
@@ -2,8 +2,13 @@
;; author: Craig Jennings <c@cjennings.net>
;;; Commentary:
-;; This module provides seamless integration between org-contacts and mu4e's
-;; email composition, enabling automatic contact completion in email fields.
+;;
+;; Completion-at-point integration between org-contacts and mu4e/org-msg compose
+;; buffers. Header fields complete against org contact email strings; message
+;; bodies keep their normal TAB behavior.
+;;
+;; Dependencies are optional at file load. Activation is a no-op when mu4e or
+;; org-contacts is unavailable so the wider config can still load.
;;; Code:
diff --git a/modules/mu4e-org-contacts-setup.el b/modules/mu4e-org-contacts-setup.el
index 64e9a611f..bfb9b1f24 100644
--- a/modules/mu4e-org-contacts-setup.el
+++ b/modules/mu4e-org-contacts-setup.el
@@ -2,8 +2,10 @@
;; author: Craig Jennings <c@cjennings.net>
;;; Commentary:
-;; Simple setup file to enable org-contacts integration with mu4e.
-;; Add this to your mail-config.el or load it after both mu4e and org-contacts.
+;;
+;; Thin activation wrapper for mu4e-org-contacts-integration. If mu4e is loaded,
+;; enable org-contacts completion and disable mu4e's internal contact collector
+;; so completion has one source of truth.
;;; Code:
diff --git a/modules/music-config.el b/modules/music-config.el
index c62f0c614..86f6eb130 100644
--- a/modules/music-config.el
+++ b/modules/music-config.el
@@ -5,90 +5,18 @@
;; Layer: 4 (Optional).
;; Category: O/D/P/S.
;; Load shape: eager.
-;; Eager reason: none; optional music workflow that registers a music keymap, a
-;; command-loaded deferral candidate. EMMS hooks should run only after EMMS.
-;; Top-level side effects: defines a music keymap under cj/custom-keymap, one
-;; global key, package config.
+;; Eager reason: none; optional music workflow that registers a music keymap.
+;; Top-level side effects: defines C-; m map, one global key, package config.
;; Runtime requires: subr-x, user-constants, keybindings.
-;; Direct test load: yes (requires keybindings explicitly).
+;; Direct test load: yes.
;;
-;; Music management in Emacs via EMMS with MPV backend.
-;; Focus: simple, modular helpers; consistent error handling; streamlined UX.
-;;
-;; Highlights:
-;; - Fuzzy add: select files/dirs; dirs have trailing /; case-insensitive; stable order
-;; - Recursive directory add
-;; - Dired/Dirvish integration (add selection)
-;; - M3U playlist save/load/edit/reload
-;; - Radio station M3U creation (streaming URLs supported)
-;; - Playlist window toggling
-;; - Consume mode (remove tracks after playback)
-;; - MPV as player (no daemon required)
-;;
-;; Keybindings (playlist-mode-map):
-;;
-;; Aligned with ncmpcpp defaults where possible (83% match).
-;; Additional EMMS-specific bindings for features ncmpcpp lacks.
-;;
-;; Key Action ncmpcpp default Match
-;; ─── ────── ─────────────── ─────
-;; Playback
-;; SPC pause add_item *
-;; s stop stop ✓
-;; > / n next track next ✓
-;; < / P previous track previous ✓
-;; p play selected (enter) ✓
-;; f seek forward seek_forward ✓
-;; b seek backward seek_backward ✓
-;;
-;; Toggles
-;; r repeat playlist toggle_repeat ✓
-;; t repeat track (none) +
-;; z random toggle_random ✓
-;; x consume toggle_crossfade *
-;; Z shuffle shuffle ✓
-;;
-;; Volume
-;; + / = volume up volume_up ✓
-;; - volume down volume_down ✓
-;;
-;; Info
-;; i song info show_song_info ✓
-;; o jump to playing jump_to_playing ✓
-;;
-;; Playlist management
-;; a add music (fuzzy) add_selected ✓
-;; c / C clear playlist clear_playlist ✓
-;; S save playlist (none) +
-;; L load playlist (none) +
-;; E edit playlist M3U (none) +
-;; g reload playlist (none) +
-;; A append track to M3U (none) +
-;; q quit/bury quit ✓
-;;
-;; Track reordering
-;; S-up move track up (shift-up) ✓
-;; S-down move track down (shift-down) ✓
-;; C-up move track up (alias) (none) +
-;; C-down move track down (alias) (none) +
-;;
-;; Other
-;; R create radio station (none) +
-;;
-;; Legend: ✓ = matches ncmpcpp default
-;; * = intentional divergence (see below)
-;; + = EMMS-only feature
-;;
-;; Intentional divergences from ncmpcpp defaults:
-;;
-;; SPC/p swap: ncmpcpp defaults p=pause, SPC=add_item_to_playlist.
-;; This config uses SPC=pause (more natural in Emacs) and p=play
-;; selected track. Pause via SPC is a common media player convention.
-;;
-;; x=consume vs crossfade: ncmpcpp's crossfade is an mpd daemon
-;; feature. EMMS uses mpv directly, so consume mode (remove tracks
-;; after playback) is more useful here.
+;; EMMS setup using an mpv subprocess player, M3U playlist helpers, fuzzy
+;; file/directory adds, Dired/Dirvish integration, radio-station creation, and
+;; playlist window toggling.
;;
+;; The playlist keymap intentionally follows ncmpcpp where it maps cleanly, with
+;; EMMS-specific additions for M3U editing and consume mode.
+
;;; Code:
(require 'subr-x)
diff --git a/modules/org-agenda-config.el b/modules/org-agenda-config.el
index 3234cc929..9ccd21d7b 100644
--- a/modules/org-agenda-config.el
+++ b/modules/org-agenda-config.el
@@ -6,51 +6,18 @@
;; Layer: 3 (Domain Workflow).
;; Category: D/S.
;; Load shape: eager.
-;; Eager reason: daily agenda workflow; the user expects agenda available at the
-;; first session.
-;; Top-level side effects: one add-hook and an idle timer that builds the agenda
-;; file cache 10s after startup (guarded; spec tracks the cache lifecycle).
+;; Eager reason: agenda should be available in the first session.
+;; Top-level side effects: agenda hooks plus guarded idle cache build.
;; Runtime requires: user-constants, system-lib, cj-cache-lib.
;; Direct test load: yes.
;;
-;; Performance:
-;; - Caches agenda file list to avoid scanning projects directory on every view
-;; - Cache builds asynchronously 10 seconds after Emacs startup (non-blocking)
-;; - First agenda view uses cache if ready, otherwise builds synchronously
-;; - Subsequent views are instant (cached)
-;; - Cache auto-refreshes after 1 hour
-;; - Manual refresh: M-x cj/org-agenda-refresh-files (e.g., after adding projects)
+;; Org agenda configuration for global, project-scoped, and buffer-scoped task
+;; views. F8 opens the main agenda; modified F8 bindings narrow by project,
+;; current buffer, or task list.
;;
-;; Agenda views are tied to the F8 (fate) key.
-;;
-;; "We are what we repeatedly do.
-;; Excellence, then, is not an act, but a habit"
-;; -- Aristotle
-;;
-;; "...watch your actions, they become habits;
-;; watch your habits, they become character;
-;; watch your character, for it becomes your destiny."
-;; -- Lao Tzu
-;;
-;;
-;; f8 - MAIN AGENDA which organizes all tasks and events into:
-;; - all unfinished priority A tasks
-;; - the weekly schedule, including the habit consistency graph
-;; - all priority B tasks
-;;
-;; C-f8 - PROJECT AGENDA showing the main agenda filtered to a single project.
-;; Prompts for project selection, then shows overdue/hi-pri/schedule/B tasks
-;; scoped to that project's todo.org plus all calendars and inbox.
-;;
-;; s-f8 - TASK LIST containing all tasks from all agenda targets.
-;;
-;; M-f8 - TASK LIST containing all tasks from just the current org-mode buffer.
-;;
-;; NOTE:
-;; Files that contain information relevant to the agenda are: the inbox, the
-;; schedule-file, the synced calendars, and the per-project todo.org files found
-;; in immediate subdirectories of projects-dir. (org-roam notes are refile
-;; targets, not agenda sources -- see org-refile-config.el.)
+;; Agenda files come from inbox, schedule files, synced calendars, and immediate
+;; project todo.org files. The file list is cached and rebuilt asynchronously to
+;; keep normal agenda opens fast.
;;; Code:
(require 'user-constants)
diff --git a/modules/org-webclipper.el b/modules/org-webclipper.el
index f32cad3fd..a51350f51 100644
--- a/modules/org-webclipper.el
+++ b/modules/org-webclipper.el
@@ -5,50 +5,17 @@
;; Layer: 4 (Optional).
;; Category: O/D/P.
;; Load shape: eager.
-;; Eager reason: none; web clipping runs via org-protocol/command, a Phase 4
-;; protocol/command-loaded deferral candidate.
+;; Eager reason: none; protocol and direct clipping can load on command.
;; Top-level side effects: org-protocol handler registration via use-package.
-;; Runtime requires: none (configures packages via use-package).
+;; Runtime requires: none.
;; Direct test load: yes.
;;
-;; This package provides a seamless "fire-and-forget" workflow for clipping
-;; web pages from the browser directly into an Org file using org-protocol
-;; and org-web-tools.
+;; Captures web pages into Org from org-protocol, EWW, or W3M. The protocol path
+;; records URL/title dynamically around org-capture; the direct path clips the
+;; current browser buffer.
;;
-;; Features:
-;; - Browser bookmarklet integration via org-protocol
-;; - Automatic conversion to Org format using eww-readable and Pandoc
-;; - One-click capture from any web page
-;; - Preserves page structure and formatting
-;; - Smart heading adjustment (removes page title, demotes remaining headings)
-;;
-;; Setup:
-;; 1. Ensure this file is loaded in your Emacs configuration
-;; 2. Make sure emacsclient is configured for org-protocol
-;; 3. Add the following bookmarklet to your browser's bookmarks bar:
-;;
-;; javascript:location.href='org-protocol://webclip?url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title);void(0);
-;;
-;; To add the bookmarklet:
-;; a. Create a new bookmark in your browser
-;; b. Set the name to: Clip to Org (or your preference)
-;; c. Set the URL to the JavaScript code above
-;; d. Save it to your bookmarks bar for easy access
-;;
-;; 4. Click the bookmarklet on any web page to clip its content
-;;
-;; The clipped content will be added to the file specified by `webclipped-file`
-;; under the "Webclipped Inbox" heading with proper formatting and metadata.
-;;
-;; Architecture:
-;; - cj/--process-webclip-content: Pure function for content processing
-;; - cj/org-protocol-webclip-handler: Handles URL fetching and capture
-;; - cj/org-webclipper-EWW: Direct capture from EWW/W3M buffers
-;;
-;; Requirements:
-;; - org-web-tools package
-;; - Pandoc installed on your system
-;; - Emacs server running (M-x server-start)
+;; Content is converted to readable Org, normalized, and filed under the
+;; configured webclip inbox heading.
;;; Code:
diff --git a/modules/test-runner.el b/modules/test-runner.el
index 50d4f7e40..48a2b09fe 100644
--- a/modules/test-runner.el
+++ b/modules/test-runner.el
@@ -6,69 +6,18 @@
;; Layer: 2 (Core UX).
;; Category: C/L.
;; Load shape: eager.
-;; Eager reason: the test keymap entry point and project-scoped runner state.
-;; Top-level side effects: defines a test keymap, registers it under cj/custom-keymap.
+;; Eager reason: registers the C-; t test runner entry point and state.
+;; Top-level side effects: defines and registers cj/test-map.
;; Runtime requires: ert, cl-lib, keybindings.
-;; Direct test load: yes (requires keybindings explicitly).
+;; Direct test load: yes.
;;
-;; This module provides a powerful ERT test runner with focus/unfocus workflow
-;; for efficient test-driven development in Emacs Lisp projects.
-;;
-;; PURPOSE:
-;;
-;; When working on large Emacs Lisp projects with many test files, you often
-;; want to focus on running just the tests relevant to your current work without
-;; waiting for the entire suite to run. This module provides a smart test runner
-;; that supports both running all tests and focusing on specific test files.
-;;
-;; WORKFLOW:
-;;
-;; 1. Run all tests initially to establish baseline (C-; t R)
-;; 2. Add test files to focus while working on a feature (C-; t a)
-;; 3. Run focused tests repeatedly as you develop (C-; t r)
-;; 4. Add more test files as needed (C-; t b from within test buffer)
-;; 5. View your focused test list at any time (C-; t v)
-;; 6. Clear focus and run all tests before finishing (C-; t c, then C-; t R)
-;;
-;; PROJECT INTEGRATION:
-;;
-;; - Automatically discovers test directories in Projectile projects
-;; (looks for "test" or "tests" under project root)
-;; - Falls back to ~/.emacs.d/tests if not in a Projectile project
-;; - Test files must match pattern: test-*.el
-;;
-;; SPECIAL BEHAVIORS:
-;;
-;; - Smart test running: Automatically runs all or focused tests based on mode
-;; - Test extraction: Discovers test names via regex to run specific tests
-;; - At-point execution: Run individual test at cursor position (C-; t .)
-;; - Error handling: Continues loading tests even if individual files fail
-;;
-;; KEYBINDINGS:
-;;
-;; C-; t L Load all test files
-;; C-; t R Run all tests (full suite)
-;; C-; t r Run tests smartly (all or focused based on mode)
-;; C-; t . Run test at point
-;; C-; t a Add test file to focus (with completion)
-;; C-; t b Add current buffer's test file to focus
-;; C-; t c Clear all focused test files
-;; C-; t v View list of focused test files
-;; C-; t t Toggle mode between 'all and 'focused
-;;
-;; RECOMMENDED USAGE:
-;;
-;; While implementing a feature:
-;; - Add the main test file for the feature you're working on
-;; - Add any related test files that might be affected
-;; - Use C-; t r to repeatedly run just those focused tests
-;; - This provides fast feedback during development
-;;
-;; Before committing:
-;; - Clear the focus with C-; t c
-;; - Run the full suite with C-; t R to ensure nothing broke
-;; - Verify all tests pass before pushing changes
+;; Project-aware ERT runner with two modes: all tests or a focused file set.
+;; Test roots come from Projectile projects, falling back to the config's tests
+;; directory, and test files are discovered by the test-*.el convention.
;;
+;; Commands under C-; t load tests, run all/focused tests, run the test at point,
+;; and manage the per-project focus list.
+
;;; Code:
(require 'ert)
diff --git a/modules/video-audio-recording.el b/modules/video-audio-recording.el
index 1672529f7..fce3d9033 100644
--- a/modules/video-audio-recording.el
+++ b/modules/video-audio-recording.el
@@ -6,104 +6,19 @@
;; Layer: 4 (Optional).
;; Category: O/D/S.
;; Load shape: eager.
-;; Eager reason: none; registers a recording keymap, but device probing should
-;; run only on command (command-loaded target).
-;; Top-level side effects: defines cj/record-map and conditionally registers it
-;; under C-; r.
+;; Eager reason: none; records only on command, but registers C-; r at load.
+;; Top-level side effects: defines cj/record-map and registers it when possible.
;; Runtime requires: system-lib, keybindings.
-;; Direct test load: yes (requires keybindings explicitly).
+;; Direct test load: yes.
;;
-;; Desktop video and audio recording from within Emacs using ffmpeg.
-;; Records from both microphone and system audio simultaneously, which
-;; makes it suitable for capturing meetings, presentations, and desktop activity.
-;;
-;; Architecture:
-;; - Audio recordings use ffmpeg directly with PulseAudio inputs → M4A/AAC
-;; - Video recordings differ by display server:
-;; - X11: ffmpeg with x11grab + PulseAudio → MKV
-;; - Wayland: wf-recorder piped to ffmpeg for audio mixing → MKV
-;; (wf-recorder captures the compositor, ffmpeg mixes in audio)
-;;
-;; Process lifecycle:
-;; - Start: `start-process-shell-command` creates a shell running the
-;; ffmpeg (or wf-recorder|ffmpeg) pipeline. Process ref is stored in
-;; `cj/video-recording-ffmpeg-process' or `cj/audio-recording-ffmpeg-process'.
-;; - Stop: SIGINT is sent to the shell's process group so all pipeline
-;; children (wf-recorder, ffmpeg) receive it. We then poll until the
-;; process actually exits, giving ffmpeg time to finalize the container.
-;; - Cleanup: A process sentinel auto-clears the process variable and
-;; updates the modeline if the process dies unexpectedly.
-;;
-;; Note: video-recordings-dir and audio-recordings-dir are defined
-;; (and directory created) in user-constants.el
-;;
-;; Quick Start
-;; ===========
-;; 1. Press C-; r s to run quick setup
-;; 2. Pick a microphone from the list
-;; 3. Pick an audio output — [in use] shows which apps are playing
-;; 4. Press C-; r a to start/stop audio recording
-;; 5. Recording starts - you'll see 󰍬 in your modeline
-;; 6. Press C-; r a again to stop (🔴 disappears)
-;;
-;; Device Setup
-;; ============
-;; C-; r a automatically prompts for device selection on first use.
-;; Device selection lasts for the current Emacs session only.
-;;
-;; Manual device selection:
-;;
-;; C-; r s (cj/recording-quick-setup) - RECOMMENDED
-;; Two-step setup: pick a mic, then pick an audio output to capture.
-;; Both steps show status: [in use], [ready], [available], [muted].
-;; Audio outputs also show which apps are playing through them.
-;; Sorted: in use → ready → available → muted.
-;;
-;; C-; r S (cj/recording-select-devices) - ADVANCED
-;; Manual selection: choose mic and monitor separately.
-;; Use when you need different devices for input/output.
-;;
-;; C-; r d (cj/recording-list-devices)
-;; List all available audio devices and current configuration.
-;;
-;; C-; r w (cj/recording-show-active-audio) - DIAGNOSTIC TOOL
-;; Show which apps are currently playing audio and through which device.
-;; Use this DURING a phone call to see if the call audio is going through
-;; the device you think it is. Helps diagnose "missing one side" issues.
-;;
-;; Pre-Recording Validation
-;; ========================
-;; Every time you start a recording, the system audio device is
-;; validated automatically:
-;; 1. If the configured monitor device no longer exists (e.g.
-;; USB DAC unplugged), it's auto-updated to the current
-;; default sink's monitor.
-;; 2. If no audio is currently playing through the monitored sink,
-;; a warning is shown in the echo area. Recording proceeds
-;; without interruption — run C-; r s to see active streams.
-;;
-;; Testing Devices Before Important Recordings
-;; ============================================
-;; Always test devices before important recordings:
-;;
-;; C-; r t b (cj/recording-test-both) - RECOMMENDED
-;; Guided test: mic only, monitor only, then both together.
-;; Catches hardware issues before they ruin recordings!
-;;
-;; C-; r t m (cj/recording-test-mic)
-;; Quick 5-second mic test with playback.
-;;
-;; C-; r t s (cj/recording-test-monitor)
-;; Quick 5-second system audio test with playback.
-;;
-;; To adjust volumes:
-;; - Use =M-x cj/recording-adjust-volumes= (or your keybinding =r l=)
-;; - Or customize permanently: =M-x customize-group RET cj-recording RET=
-;; - Or in your config:
-;; #+begin_src emacs-lisp
-;; (setq cj/recording-mic-boost 1.5) ; 50% louder
-;; (setq cj/recording-system-volume 0.7) ; 30% quieter
+;; Starts and stops ffmpeg-backed audio/video recordings from Emacs. Audio
+;; captures microphone plus system monitor; video uses x11grab on X11 and
+;; wf-recorder piped into ffmpeg on Wayland.
;;
+;; Recording processes are tracked in module variables, stopped with SIGINT so
+;; containers finalize cleanly, and reflected in the modeline. Device selection
+;; is session-local; quick setup and device tests live under C-; r.
+
;;; Code:
(require 'system-lib)