claude-dev-env 2.22.1 → 2.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,13 @@ Run the converging cleanup loop on the target the user names (a PR URL,
13
13
  a branch, or blank for the current branch's diff). Each phase invokes an
14
14
  existing skill and repeats it until a pass returns zero new findings.
15
15
 
16
+ ### Stack context
17
+
18
+ Before any fixes, load and review the full PR stack, from its base through the
19
+ target PR. Read every PR and diff in the stack. Use that full context to judge
20
+ each proposed simplify or code-review fix. Apply a fix only when it fits the
21
+ stack's design, intent, and changes.
22
+
16
23
  ### Phase A — loop simplify
17
24
 
18
25
  1. Invoke the `simplify` skill (or its local equivalent, e.g. `e-simplify`)
@@ -44,6 +51,9 @@ existing skill and repeats it until a pass returns zero new findings.
44
51
 
45
52
  ### Finish
46
53
 
54
+ When both phases are clean, or only fixed nits remain, mark the target PR ready
55
+ with `gh pr ready`. Confirm that it is no longer a draft.
56
+
47
57
  Report: passes run per phase, commits pushed with hashes, fixes applied, and
48
58
  the standing skip list with reasons.
49
59
 
package/AGENTS.md CHANGED
@@ -1,3 +1,5 @@
1
+ less words. small words. few words. always. forever.
2
+
1
3
  Avoid all redundant text for all output. IE: instead of "the review found 2 real issues", simply state "the review found 2 issues".
2
4
 
3
5
  ## User-facing language hierarchy
@@ -10,6 +10,13 @@ tool and repeats it until a pass returns zero new findings.
10
10
  Use `rules/asd-ste100-language.md` for user-facing wording. Keep the loop's
11
11
  cleanup, verification, commit, push, and finish-report fields.
12
12
 
13
+ ## Stack context
14
+
15
+ Before any fixes, load and review the full PR stack, from its base through the
16
+ target PR. Read every PR and diff in the stack. Use that full context to judge
17
+ each proposed simplify or code-review fix. Apply a fix only when it fits the
18
+ stack's design, intent, and changes.
19
+
13
20
  ## Phase A — loop /simplify
14
21
 
15
22
  1. Invoke the `simplify` skill on the target (the same review the user gets
@@ -41,6 +48,9 @@ cleanup, verification, commit, push, and finish-report fields.
41
48
 
42
49
  ## Finish
43
50
 
51
+ When both phases are clean, or only fixed nits remain, mark the target PR ready
52
+ with `gh pr ready`. Confirm that it is no longer a draft.
53
+
44
54
  Report: passes run per phase, commits pushed with hashes, fixes applied, and
45
55
  the standing skip list with reasons.
46
56
 
@@ -22,6 +22,34 @@ A missing or unreadable source root is an error, and the run changes nothing. An
22
22
 
23
23
  Run `codex-compat bridge --surface <name> --payload '<json-object>'`. The bridge exposes the Python translation logic directly. `TaskCreate` and `TaskUpdate` map to `update_plan`; spawn, message, wait, and stop map to multi-agent surfaces. `ScheduleWakeup` is explicitly unsupported and requires manual review.
24
24
 
25
+ ## Per-message context injection (manual wiring)
26
+
27
+ Codex reads the same `hookSpecificOutput.additionalContext` shape as Claude,
28
+ on its own `UserPromptSubmit` event. `hooks/session/style_reminder_prompt.py`
29
+ works for both, as is.
30
+
31
+ The install already points `$CODEX_HOME/hooks` at the shared hooks folder.
32
+ Once installed, the script sits at
33
+ `$CODEX_HOME/hooks/session/style_reminder_prompt.py`.
34
+
35
+ Add this by hand to `$CODEX_HOME/hooks.json` (merge it into an existing file):
36
+
37
+ ```json
38
+ {
39
+ "hooks": {
40
+ "UserPromptSubmit": [
41
+ {
42
+ "command": "python3 $CODEX_HOME/hooks/session/style_reminder_prompt.py"
43
+ }
44
+ ]
45
+ }
46
+ }
47
+ ```
48
+
49
+ Limits:
50
+
51
+ - The installer skips Codex `hooks.json` for now. Wire it by hand.
52
+
25
53
  ## Roots and safety
26
54
 
27
55
  Both roots are caller-supplied. The tool never writes to `.agents` or `CODEX_HOME` automatically; pass those locations explicitly when desired. No personal paths or secrets are embedded in the package.
package/hooks/hooks.json CHANGED
@@ -123,6 +123,18 @@
123
123
  ]
124
124
  }
125
125
  ],
126
+ "UserPromptSubmit": [
127
+ {
128
+ "matcher": "",
129
+ "hooks": [
130
+ {
131
+ "type": "command",
132
+ "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/session/style_reminder_prompt.py",
133
+ "timeout": 10
134
+ }
135
+ ]
136
+ }
137
+ ],
126
138
  "SessionStart": [
127
139
  {
128
140
  "matcher": "",
@@ -81,6 +81,7 @@ Shared constant modules imported by hooks throughout the `hooks/` tree. Each fil
81
81
  | `stale_comment_reference_blocker_constants.py` | Identifier pattern, comment stopwords, and denial text for the stale-comment-reference blocker |
82
82
  | `state_description_blocker_constants.py` | The set of historical/comparative phrases the state-description blocker rejects, plus the docstring-extraction and mention-span patterns for its Python docstring scan |
83
83
  | `stop_dispatcher_constants.py` | Ordered hosted-hook roster and Stop block payload field names for the Stop-chain dispatcher |
84
+ | `style_reminder_prompt_constants.py` | The style reminder text ("small words. few words. always. forever.") for the style_reminder_prompt hook |
84
85
  | `stuttering_check_config.py` | Config for the stuttering (repeated-phrase) check |
85
86
  | `stuttering_import_binding_constants.py` | Import-binding patterns for the stuttering check |
86
87
  | `subprocess_budget_completeness_constants.py` | Required argument names for the subprocess-budget completeness check |
@@ -0,0 +1,9 @@
1
+ """The style reminder text for the style_reminder_prompt hook."""
2
+
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "STYLE_REMINDER_PROMPT",
7
+ ]
8
+
9
+ STYLE_REMINDER_PROMPT = "small words. few words. always. forever."
@@ -1,6 +1,6 @@
1
1
  # hooks/session
2
2
 
3
- SessionStart and SessionEnd hooks for per-session setup and cleanup: removing stale session and plugin-data directories at startup, detecting unregistered repositories, starting the session's task-list maintenance loop, injecting working-style guidance, and clearing PR-author swap state at shutdown.
3
+ SessionStart and SessionEnd hooks for per-session setup and cleanup: removing stale session and plugin-data directories at startup, detecting unregistered repositories, starting the session's task-list maintenance loop, injecting working-style guidance, and clearing PR-author swap state at shutdown. Also holds the UserPromptSubmit hook. It adds a style reminder to each message.
4
4
 
5
5
  The working-style projection uses `~/.claude/rules/asd-ste100-language.md` for
6
6
  user-facing word choice, sentence style, tone, punctuation, and prose form.
@@ -21,6 +21,8 @@ user-facing word choice, sentence style, tone, punctuation, and prose form.
21
21
  | `test_orchestrator_auto_starter.py` | — | Tests for `orchestrator_auto_starter.py` |
22
22
  | `test_issue_tracker_session_starter.py` | — | Tests for `issue_tracker_session_starter.py` |
23
23
  | `working_style_prompt.py` | SessionStart | Emits an `additionalContext` block with the fixed working-style prompt (running ledger, canonical language policy, outcome-first finish, scope discipline). Writes nothing and runs no tools itself. |
24
+ | `style_reminder_prompt.py` | UserPromptSubmit | Adds the style reminder ("small words. few words. always. forever.") to every message, as `hookSpecificOutput.additionalContext`. Codex reads the same shape, so a manually wired Codex `hooks.json` can reuse this script too (see `docs/codex-compatibility.md`). Prints text and stops. |
25
+ | `test_style_reminder_prompt.py` | — | Tests for `style_reminder_prompt.py` |
24
26
  | `test_gh_pr_author_session_cleanup.py` | — | Tests for `gh_pr_author_session_cleanup.py` |
25
27
  | `test_session_edit_tracker_cleanup.py` | — | Tests for `session_edit_tracker_cleanup.py` |
26
28
  | `test_session_env_cleanup.py` | — | Tests for `session_env_cleanup.py` |
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env python3
2
+ """UserPromptSubmit hook. Adds the style reminder to every message.
3
+
4
+ ::
5
+
6
+ user sends a message
7
+ |
8
+ v
9
+ UserPromptSubmit fires -> additionalContext: "small words. few words. always. forever."
10
+ |
11
+ v
12
+ the model sees the reminder this turn, and each turn after
13
+
14
+ Claude Code and Codex CLI both read the same ``additionalContext`` shape on
15
+ their ``UserPromptSubmit`` event. One script serves both. The hook prints
16
+ text and stops.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import json
22
+ import sys
23
+
24
+ import _path_setup # noqa: F401
25
+
26
+ from hooks_constants.style_reminder_prompt_constants import STYLE_REMINDER_PROMPT
27
+
28
+
29
+ def main() -> None:
30
+ """Print the style reminder as UserPromptSubmit additionalContext."""
31
+ payload = {
32
+ "hookSpecificOutput": {
33
+ "hookEventName": "UserPromptSubmit",
34
+ "additionalContext": STYLE_REMINDER_PROMPT,
35
+ }
36
+ }
37
+ sys.stdout.write(json.dumps(payload) + "\n")
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()
@@ -0,0 +1,32 @@
1
+ """Tests for style_reminder_prompt. Checks the hook adds the style reminder."""
2
+
3
+ import json
4
+ import sys
5
+ from io import StringIO
6
+ from pathlib import Path
7
+ from unittest.mock import patch
8
+
9
+ _SESSION_DIR = Path(__file__).resolve().parent
10
+ _HOOKS_ROOT = _SESSION_DIR.parent
11
+ for each_sys_path_entry in (str(_SESSION_DIR), str(_HOOKS_ROOT)):
12
+ if each_sys_path_entry not in sys.path:
13
+ sys.path.insert(0, each_sys_path_entry)
14
+
15
+ import style_reminder_prompt as reminder
16
+ from hooks_constants.style_reminder_prompt_constants import STYLE_REMINDER_PROMPT
17
+
18
+
19
+ def _run_main() -> str:
20
+ """Return the text main() prints."""
21
+ captured_stdout = StringIO()
22
+ with patch("sys.stdout", captured_stdout):
23
+ reminder.main()
24
+ return captured_stdout.getvalue()
25
+
26
+
27
+ class TestStyleReminderPrompt:
28
+ def test_main_emits_user_prompt_submit_hook_specific_output(self) -> None:
29
+ emitted = json.loads(_run_main())
30
+ hook_output = emitted["hookSpecificOutput"]
31
+ assert hook_output["hookEventName"] == "UserPromptSubmit"
32
+ assert hook_output["additionalContext"] == STYLE_REMINDER_PROMPT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-dev-env",
3
- "version": "2.22.1",
3
+ "version": "2.23.0",
4
4
  "description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
5
5
  "type": "module",
6
6
  "bin": {
package/rules/AGENTS.md CHANGED
@@ -29,6 +29,7 @@ Rule files installed into `~/.claude/rules/` by `bin/install.mjs`. A rule withou
29
29
  | `explore-thoroughly.md` | Read relevant files and map existing patterns before proposing a change |
30
30
  | `falsify-before-green.md` | A check's green counts as evidence only after that same check ran red on a named break, with a passing control beside it |
31
31
  | `file-global-constants.md` | File-global constants need at least two same-file references; otherwise move value to `config/` |
32
+ | `few-words.md` | The style reminder. Syncs to Cursor as an always-on `.mdc` rule. |
32
33
  | `filesystem-search.md` | Every filesystem search names a scope; `es.exe`, `Glob`, `Grep`, and `Read` are equally sanctioned, and the `unscoped_search_blocker` denies a walk from a root |
33
34
  | `gh-cli-conventions.md` | `--body-file` for every `gh` body; `--paginate --slurp` piped to external `jq` for every paginated list read |
34
35
  | `git-workflow.md` | PR workflow: always create as draft, one commit per review stage, never commit working docs or images; carries the review-response protocol and a See-also block for its seven siblings |
@@ -0,0 +1,3 @@
1
+ # Few Words
2
+
3
+ small words. few words. always. forever.