claude-dev-env 2.5.0 → 2.7.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.
Files changed (139) hide show
  1. package/CLAUDE.md +20 -57
  2. package/_shared/pr-loop/scripts/code_rules_gate.py +2 -1
  3. package/_shared/pr-loop/scripts/code_rules_gate_parts/CLAUDE.md +12 -2
  4. package/_shared/pr-loop/scripts/code_rules_gate_parts/baseline_import_isolation.py +309 -0
  5. package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_regression.py +540 -0
  6. package/_shared/pr-loop/scripts/code_rules_gate_parts/staged_test_running.py +206 -70
  7. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/__init__.py +1 -0
  8. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/_repo_test_helpers.py +76 -0
  9. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_baseline_import_isolation.py +248 -0
  10. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_regression.py +309 -0
  11. package/_shared/pr-loop/scripts/code_rules_gate_parts/tests/test_staged_test_running.py +91 -58
  12. package/_shared/pr-loop/scripts/pr_loop_shared_constants/code_rules_gate_constants.py +202 -0
  13. package/agents/CLAUDE.md +1 -1
  14. package/agents/code-verifier.md +36 -7
  15. package/bin/codex-compat.mjs +104 -0
  16. package/bin/codex-compat.test.mjs +51 -0
  17. package/codex-capability-map.json +13 -0
  18. package/docs/CODE_RULES.md +2 -0
  19. package/docs/codex-compatibility.md +25 -0
  20. package/docs/nas-ssh-invocation.md +96 -12
  21. package/docs/references/code-review-enforcement.md +31 -6
  22. package/hooks/blocking/CLAUDE.md +3 -0
  23. package/hooks/blocking/config/code_review_enforcement_constants.py +40 -10
  24. package/hooks/blocking/config/test_code_review_enforcement_constants.py +56 -3
  25. package/hooks/blocking/eli11_reply_enforcer.py +479 -0
  26. package/hooks/blocking/gh_body_arg_blocker.py +1 -1
  27. package/hooks/blocking/nas_ssh_binary_enforcer.py +8 -46
  28. package/hooks/blocking/shell_substitution_blocker.py +129 -0
  29. package/hooks/blocking/state_description_blocker.py +1 -1
  30. package/hooks/blocking/stop_dispatcher.py +1 -1
  31. package/hooks/blocking/test_bash_pre_tool_use_dispatcher.py +2 -3
  32. package/hooks/blocking/test_eli11_reply_enforcer.py +457 -0
  33. package/hooks/blocking/test_shell_substitution_blocker.py +124 -0
  34. package/hooks/blocking/test_stop_dispatcher.py +23 -0
  35. package/hooks/blocking/test_unscoped_search_blocker.py +102 -0
  36. package/hooks/blocking/test_verdict_directory_write_blocker.py +4 -8
  37. package/hooks/blocking/unscoped_search_blocker.py +391 -0
  38. package/hooks/git-hooks/CLAUDE.md +3 -0
  39. package/hooks/git-hooks/conftest.py +30 -0
  40. package/hooks/git-hooks/gate_utils.py +2 -2
  41. package/hooks/git-hooks/git_hooks_constants/__init__.py +41 -2
  42. package/hooks/git-hooks/pre_push.py +75 -4
  43. package/hooks/git-hooks/pre_push_base_reference.py +166 -0
  44. package/hooks/git-hooks/test_config.py +0 -15
  45. package/hooks/git-hooks/test_gate_utils.py +3 -15
  46. package/hooks/git-hooks/test_pre_commit.py +1 -15
  47. package/hooks/git-hooks/test_pre_push.py +236 -27
  48. package/hooks/git-hooks/test_pre_push_base_reference.py +339 -0
  49. package/hooks/hooks.json +0 -12
  50. package/hooks/hooks_constants/CLAUDE.md +5 -1
  51. package/hooks/hooks_constants/bash_pre_tool_use_dispatcher_constants.py +4 -4
  52. package/hooks/hooks_constants/eli11_reply_enforcer_constants.py +101 -0
  53. package/hooks/hooks_constants/nas_ssh_binary_enforcer_constants.py +2 -8
  54. package/hooks/hooks_constants/shell_command_segments.py +82 -0
  55. package/hooks/hooks_constants/shell_substitution_blocker_constants.py +67 -0
  56. package/hooks/hooks_constants/stop_dispatcher_constants.py +1 -0
  57. package/hooks/hooks_constants/test_bash_pre_tool_use_dispatcher_constants.py +5 -6
  58. package/hooks/hooks_constants/test_stop_dispatcher_constants.py +1 -0
  59. package/hooks/hooks_constants/unscoped_search_blocker_constants.py +153 -0
  60. package/package.json +4 -2
  61. package/rules/CLAUDE.md +17 -23
  62. package/rules/agent-spawn-protocol.md +6 -6
  63. package/rules/anti-corollary-tests.md +1 -1
  64. package/rules/bdd.md +1 -1
  65. package/rules/cleanup-temp-files.md +10 -4
  66. package/rules/code-standards.md +7 -0
  67. package/rules/conservative-action.md +1 -5
  68. package/rules/context7.md +0 -4
  69. package/rules/destructive-commands.md +47 -0
  70. package/rules/doc-inventory-integrity.md +48 -0
  71. package/rules/doc-prose-cuts.md +58 -0
  72. package/rules/docstring-prose-matches-implementation.md +10 -2
  73. package/rules/durable-post-artifacts.md +0 -4
  74. package/rules/eli11-replies.md +31 -0
  75. package/rules/explore-thoroughly.md +4 -4
  76. package/rules/falsify-before-green.md +68 -0
  77. package/rules/file-global-constants.md +1 -1
  78. package/rules/filesystem-search.md +51 -0
  79. package/rules/gh-cli-conventions.md +27 -0
  80. package/rules/git-workflow.md +26 -0
  81. package/rules/hedging-claims.md +9 -0
  82. package/rules/long-horizon-autonomy.md +0 -4
  83. package/rules/measurement-denominators.md +48 -0
  84. package/rules/nas-ssh-invocation.md +23 -5
  85. package/rules/parallel-tools.md +2 -2
  86. package/rules/plain-illustrative-docstrings.md +3 -7
  87. package/rules/plain-language.md +2 -0
  88. package/rules/proof-of-work-pr-comments.md +0 -4
  89. package/rules/re-stage-before-commit.md +2 -0
  90. package/rules/research-mode.md +10 -0
  91. package/rules/shell-invocation.md +21 -0
  92. package/rules/testing.md +4 -0
  93. package/rules/verified-commit-gate-skip.md +3 -27
  94. package/rules/verify-before-asking.md +5 -0
  95. package/rules/windows-filesystem-safe.md +1 -1
  96. package/rules/workers-done-before-complete.md +4 -0
  97. package/scripts/Migrate-ShellPolicy.ps1 +1 -1
  98. package/scripts/codex_capability_bridge.py +171 -0
  99. package/scripts/codex_compat_materializer.py +1087 -0
  100. package/scripts/codex_compat_watcher.py +502 -0
  101. package/scripts/dev_env_scripts_constants/code_review_constants.py +37 -0
  102. package/scripts/invoke_code_review.py +11 -4
  103. package/scripts/sync_to_cursor/rules.py +0 -10
  104. package/scripts/test_invoke_code_review.py +143 -0
  105. package/scripts/test_invoke_code_review_chain.py +1 -1
  106. package/scripts/test_invoke_code_review_contract.py +1 -1
  107. package/scripts/tests/test_code_review_constants.py +80 -0
  108. package/scripts/tests/test_codex_capability_bridge.py +91 -0
  109. package/scripts/tests/test_codex_compat_materializer.py +632 -0
  110. package/scripts/tests/test_codex_compat_watcher.py +599 -0
  111. package/scripts/tests/test_sync_to_cursor.py +0 -1
  112. package/skills/autoconverge/workflow/converge.mjs +1 -1
  113. package/skills/bugteam/reference/copilot-gap-analysis.md +1 -1
  114. package/skills/condensing-instructions/SKILL.md +42 -51
  115. package/skills/fresh-branch/CLAUDE.md +1 -1
  116. package/skills/fresh-branch/SKILL.md +5 -6
  117. package/skills/fresh-branch/scripts/create_fresh_branch.py +42 -24
  118. package/skills/fresh-branch/scripts/fresh_branch_scripts_constants/fresh_branch_cli_constants.py +1 -3
  119. package/skills/fresh-branch/scripts/test_create_fresh_branch.py +30 -126
  120. package/skills/orchestrator/SKILL.md +23 -9
  121. package/skills/orchestrator-refresh/SKILL.md +20 -1
  122. package/skills/privacy-hygiene/reference/sweep-procedure.md +1 -1
  123. package/skills/session-log/SKILL.md +1 -1
  124. package/rules/claude-md-orphan-file.md +0 -28
  125. package/rules/cleanup-command-forms.md +0 -23
  126. package/rules/code-reviews.md +0 -11
  127. package/rules/env-var-table-code-drift.md +0 -10
  128. package/rules/gh-body-file.md +0 -5
  129. package/rules/gh-paginate.md +0 -3
  130. package/rules/hook-prose-matches-detector.md +0 -15
  131. package/rules/no-historical-clutter.md +0 -26
  132. package/rules/no-inline-destructive-literals.md +0 -9
  133. package/rules/no-justification-noise.md +0 -61
  134. package/rules/package-inventory-stale-entry.md +0 -25
  135. package/rules/right-sized-engineering.md +0 -28
  136. package/rules/self-contained-docs.md +0 -17
  137. package/rules/shell-invocation-policy.md +0 -5
  138. package/rules/state-what-is.md +0 -25
  139. package/rules/tdd.md +0 -7
@@ -1,81 +1,72 @@
1
1
  ---
2
2
  name: condensing-instructions
3
3
  description: >-
4
- Rewrite existing instruction documents or turn first drafts and requirements
5
- into compact, high-information operational instructions without changing or
6
- inventing their contract. Use for prompts, skills, policies, runbooks,
7
- agent-facing documents, reference instructions, token reduction,
8
- deduplication, restructuring, or concise instruction authoring.
4
+ Refine an instruction document for Claude 5 generation models: cut rules the
5
+ model's judgment already covers, move detail behind progressive disclosure,
6
+ and route each remaining piece to the system prompt, CLAUDE.md, a skill, or a
7
+ reference. Use for system prompts, CLAUDE.md files, skills, tool
8
+ descriptions, agent instructions, context engineering, prompt slimming, and
9
+ token reduction.
9
10
  ---
10
11
 
11
12
  # Condensing Instructions
12
13
 
13
- Rewrite an existing instruction document or turn a first draft, notes, or requirements into compact operational instructions. Preserve behavior; reduce length only after the contract is complete and unambiguous.
14
+ Cut an instruction document to what a Claude 5 generation model needs, and move the rest to the surface that loads it on demand. Over 80% of Claude Code's system prompt came out for Claude Opus 5 and Claude Fable 5 with no measurable drop in performance, so treat a long instruction document as a place with room to cut.
14
15
 
15
- ## Preserve the full contract
16
+ ## Clear the conflicts first
16
17
 
17
- Treat every execution-relevant detail as binding: required, prohibited, and permitted behavior; safety and authority boundaries; actors, objects, data or resource kinds, and scope; force, negation, and quantifiers; triggers, defaults, conditions, exceptions, thresholds, and precedence; dependencies, prerequisites, order, timing, duration, persistence, and state; failure and recovery behavior; exact strings, names, paths, URLs, identifiers, commands, flags, numbers, placeholders, schemas, and error text; and input, output, formatting, validation, acceptance, and completion requirements.
18
+ Read the system prompt, the CLAUDE.md, and the skills as one body of text and find the lines that pull against each other "leave documentation as appropriate" sitting beside "DO NOT add comments". A conflict makes the model deliberate at length before it acts. Resolve each pair into one statement, or delete both when neither changes what the model does.
18
19
 
19
- Keep rationale or examples only when they define a decision, boundary, exception, exact value, or required behavior. Preserve required frontmatter, tags, wrappers, templates, schemas, and other machine-read structure.
20
+ ## Trade rules for judgment
20
21
 
21
- When rewriting, change wording and structure, not behavior. When authoring, supply organization, wording, and conventional editorial choices, but do not invent material obligations, permissions, exceptions, or defaults. Ask one concise blocking question when missing, contradictory, or ambiguous information would materially change behavior, safety, authority, scope, precedence, failure handling, or output. Otherwise proceed.
22
+ Delete a rule written to block a worst case, such as file deletion. Claude 5 generation models read the surrounding context and decide well without it, and a rigid rule blocks the user who has a real reason to want the behavior it forbids.
22
23
 
23
- If no instruction material or requirements are provided, respond exactly: `Provide the instructions or draft requirements.`
24
+ State the outcome and the signal the model should read:
24
25
 
25
- ## Build a requirement ledger first
26
+ - Cut: "Default to writing no comments. Never write multi-paragraph docstrings or multi-line comment blocks — one short line max. Don't create planning, decision, or analysis documents unless the user asks for them."
27
+ - Keep: "Write code that reads like the surrounding code: match its comment density, naming, and idiom."
26
28
 
27
- Before deleting, merging, or drafting text, record each atomic commitment internally. Capture its force, actor, trigger, action, object or type, required outcome, scope, timing or persistence, dependencies, defaults, exceptions, precedence, failure behavior, and exact literals when applicable.
29
+ ## Design the interface in place of examples
28
30
 
29
- For an existing document, inventory every behaviorally meaningful statement. Distinguish true duplicates from similar rules that apply to different actors, stages, conditions, or scopes. For a first draft, translate each stated goal into observable behavior or an acceptance condition; mark material gaps instead of silently choosing an answer. Do not promote a preference to a hard rule or average conflicting rules.
31
+ Examples constrain exploration. Carry usage in the tool's own shape: expressive names, expressive parameters, and types that signal intent. A status parameter enumerated as `pending`, `in_progress`, `completed` shows correct use with no example attached.
30
32
 
31
- Do not expose the ledger unless requested.
33
+ ## Load detail at the point of use
32
34
 
33
- ## Group rules by the decisions they control
35
+ Move detail out of always-on text and into a surface the model reaches for:
34
36
 
35
- - Group requirements by function or decision point, not by draft order.
36
- - Default to this sequence when it fits: purpose and scope; inputs and prerequisites; operating defaults; procedures and branches; constraints and safety; outputs and failures; verification. Override it when dependencies require another sequence.
37
- - Place a safety rule or other constraint before the first action it governs.
38
- - Within a group, put prerequisites before actions, general rules before narrow exceptions, and production requirements before their checks.
39
- - Put each exception beside the rule it modifies. State precedence when rules overlap.
40
- - Give each rule one authoritative location. State a shared actor, condition, default, or scope once at the narrowest level that covers every affected rule.
41
- - Let a heading carry scope only when every instruction beneath it clearly inherits that scope. Use the fewest headings that preserve navigation.
37
+ - A skill the model calls when the task calls for it. Code review and verification detail belongs here.
38
+ - A linked file the model opens on demand.
39
+ - A tool with deferred loading, where the model searches for the definition before it uses the tool.
42
40
 
43
- ## Write direct, dense rules
41
+ Keep the always-on context lean and let the model pull the rest.
44
42
 
45
- - Use active, imperative language and concrete verbs. Put a condition before its action and an exception immediately after its default.
46
- - Preserve force and quantifiers. Keep `must`, `never`, `only`, `should`, `may`, `all`, `any`, and exact counts distinct.
47
- - Combine statements only when their actor, force, scope, trigger, timing, persistence, and exceptions align.
48
- - Replace true repetition with one rule and a compact list of affected cases. Keep separate statements when repetition protects distinct stages, scopes, or failure modes.
49
- - Use one sentence per decision. Join clauses only when they form one testable rule.
50
- - Use paragraphs for cohesive rules and lists for parallel obligations, mappings, or branches. Avoid decorative headings and structural ceremony.
51
- - Remove non-operative background, history, rationale, transition text, conversational framing, restatement, setup narration, and examples. Remove inventories or folder maps that merely describe the document.
52
- - Use one term for each concept. Define unfamiliar terms at first use. Do not compress complete sentences into fragments, stacked jargon, or vague shorthand.
53
- - Preserve operational literals character for character, including spelling, case, punctuation, quoting, and placeholders. Preserve whether a list is exhaustive or illustrative; never replace an exact enumeration with `etc.` or a broader category.
43
+ ## Say each thing once
54
44
 
55
- ## Imply only what cannot change behavior
45
+ Put tool usage guidance in the tool description alone. Delete the copy that repeats it in the system prompt.
56
46
 
57
- Rely on ordinary language competence and document conventions only when every reasonable reader would take the same action. State a detail when omitting it could change permission, safety, actor, object or type, scope, force, trigger, sequence, timing, persistence, precedence, failure behavior, exact output, or acceptance.
47
+ ## Let memory carry session facts
58
48
 
59
- Match detail to fragility. Specify exact steps for brittle, high-risk, or order-dependent work. For flexible work, state the required outcome and constraints, then leave the method open.
49
+ Claude's automatic memory captures relevant context and carries it across sessions. Delete hand-written memory notes from CLAUDE.md when memory already holds them.
60
50
 
61
- Never use implication to carry a prohibition, exception, dependency, safety boundary, or exact literal. Do not retain obvious advice that constrains nothing, and do not omit a non-obvious rule because it seems intuitive.
51
+ ## Point at rich references
62
52
 
63
- ## Pass the quality gate
53
+ Include files as references with @mentions. Prefer a reference the model can read with no ambiguity, in this order:
64
54
 
65
- Run these checks silently:
55
+ 1. Code from this or another codebase — the highest fidelity specification available.
56
+ 2. A test suite that pins the behavior.
57
+ 3. An HTML artifact or a mockup.
58
+ 4. A rubric, which lets a verification agent score work against a quality standard.
59
+ 5. Prose description or a screenshot.
66
60
 
67
- 1. **Coverage:** Map every ledger item to a clause in the finished document.
68
- 2. **Support:** Map every material clause back to a stated or confirmed requirement; remove invented behavior.
69
- 3. **Fidelity:** Compare force, negation, quantifiers, actor, object or type, scope, conditions, exceptions, dependencies, order, timing, persistence, failure behavior, outputs, and protected literals. Nothing may be weakened, broadened, narrowed, contradicted, or altered character for character where exactness matters.
70
- 4. **Boundary behavior:** Test the normal case, each branch and exception, prohibited cases, missing dependencies, failures, and acceptance checks when present. Each case must yield the intended action.
71
- 5. **Clarity:** Resolve ambiguous references, hidden precedence, scattered exceptions, inconsistent terms, and unclear qualifier scope.
72
- 6. **Density:** Delete any sentence that changes no behavior, safety boundary, interpretation, or validation result. Merge remaining text only when the boundary stays equally clear.
73
- 7. **Independent use:** Reconstruct the ledger from only the finished document. It must stand alone without background or unstated context.
61
+ ## Route what remains
74
62
 
75
- Do not finish until every check passes. If multiple versions pass, prefer fewer words, fewer sections, and lower lookup cost. Shorter text never compensates for lost behavior or precision.
63
+ | Surface | What belongs there |
64
+ |---|---|
65
+ | System prompt | The product Claude works within and the role it plays. For a custom agent, spend real effort here. |
66
+ | CLAUDE.md | A short line on what the repository is, then the gotchas found inside the codebase. Drop anything the model can read off the file structure. Link to skills for the detail. |
67
+ | Skills | Opinions, knowledge, and practices particular to your team or product, written as a guide the model consults. Split a long skill into several files. Constrain only where it matters. |
68
+ | References | Specs, mockups, and codebases pulled in by @mention. |
76
69
 
77
- ## Deliver the requested artifact
70
+ ## Deliver
78
71
 
79
- Preserve the requested format and required syntactic envelope. If no format is specified, use the leanest clear Markdown structure.
80
-
81
- For text supplied in the conversation, output only the finished instruction document. For file tasks, write only the requested paths: edit an existing file in place, and create a new file only when requested. Report changed paths with a concise behavior summary. Do not include the ledger or process narration unless requested.
72
+ Rewrite the document in place and report what moved to which surface. Offer `claude doctor` as a follow-up pass it rightsizes skills and CLAUDE.md files against these same rules.
@@ -1,6 +1,6 @@
1
1
  # fresh-branch
2
2
 
3
- Creates a new branch from fresh-fetched `origin/main` inside an isolated worktree under `Temp/<agent>/<branch-name>`. Does not push, open a PR, or run `checkout -b` in the caller tree.
3
+ Creates a new branch from fresh-fetched `origin/main` inside an isolated worktree under `<repo-root>/.claude/worktrees/<agent>/<branch-name>`. Does not push, open a PR, or run `checkout -b` in the caller tree.
4
4
 
5
5
  ## Key files
6
6
 
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: fresh-branch
3
3
  description: >-
4
- Fresh git branch from origin/main in an isolated temp worktree (never checkout -b in the caller tree).
4
+ Fresh git branch from origin/main in an isolated worktree under the repo's .claude/worktrees/ (never checkout -b in the caller tree).
5
5
  Triggers: fresh branch, new branch from main, /fresh-branch, start fresh, clean branch off main,
6
6
  worktree branch, branch in temp.
7
7
  ---
8
8
 
9
9
  # fresh-branch
10
10
 
11
- Creates a new branch from a fresh-fetched `origin/main` inside an isolated git worktree under the agent temp root. Shared primitive: other skills invoke `/fresh-branch` when they need a clean branch without touching the caller's dirty tree.
11
+ Creates a new branch from a fresh-fetched `origin/main` inside an isolated git worktree under the repository's `.claude/worktrees/<agent>/` root. Shared primitive: other skills invoke `/fresh-branch` when they need a clean branch without touching the caller's dirty tree.
12
12
 
13
13
  **Announce at start:** "Creating a fresh branch from origin/main."
14
14
 
@@ -62,15 +62,14 @@ Optional flags:
62
62
  | Flag | Role |
63
63
  |------|------|
64
64
  | `--repo <path>` | Source repo (default: current directory) |
65
- | `--agent <slug>` | Temp segment: `claude`, `grok`, `cursor`, `codex`, … |
65
+ | `--agent <slug>` | Worktree-root segment: `claude`, `grok`, `cursor`, `codex`, … |
66
66
  | `--base <ref>` | Base ref (default: `origin/main`) |
67
67
 
68
68
  Agent resolution inside the script: `--agent` → `FRESH_BRANCH_AGENT` env → host markers → `claude`.
69
69
 
70
70
  Worktree path:
71
71
 
72
- - Windows: `${USERPROFILE}/AppData/Local/Temp/<agent>/<branch-name>`
73
- - Else: `${tmpdir}/<agent>/<branch-name>`
72
+ - `<repo-root>/.claude/worktrees/<agent>/<branch-name>`, on every platform
74
73
  - If the path exists, the script suffixes `-2`, `-3`, …
75
74
 
76
75
  On exit 0, stdout is one JSON object:
@@ -101,7 +100,7 @@ Further edits for the new branch belong in `worktree_path`, not in the caller's
101
100
 
102
101
  ## Gotchas
103
102
 
104
- - **Dirty caller cwd blocks `checkout -b` and pollutes the tree.** Phase 3 always uses `git worktree add -b` into `Temp/<agent>/…`. If you reconstruct Phase 3 by hand with `checkout -b` in the session cwd, local modifications block the checkout and leave the user on a half-switched branch.
103
+ - **Dirty caller cwd blocks `checkout -b` and pollutes the tree.** Phase 3 always uses `git worktree add -b` into `<repo-root>/.claude/worktrees/<agent>/…`. If you reconstruct Phase 3 by hand with `checkout -b` in the session cwd, local modifications block the checkout and leave the user on a half-switched branch.
105
104
  - **Caller HEAD must stay put.** After success, the original repo's checked-out branch and dirty files are unchanged; only the new worktree has the new branch.
106
105
  - **Branch name collision.** If the branch already exists, the script exits non-zero with `{"error":...}`. Pick a new name; do not delete remote branches unless the user asks.
107
106
  - **Path already occupied.** A leftover folder at the preferred worktree path gets a numeric suffix (`-2`, …); report the path from JSON, not the path you assumed.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env python3
2
- """Create a fresh branch in an isolated git worktree under the agent scratch root.
2
+ """Create a fresh branch in an isolated git worktree under the repository.
3
3
 
4
4
  ::
5
5
 
@@ -8,9 +8,9 @@
8
8
  "base_commit": "abc...", "agent": "claude", "repo_root": "..."}
9
9
 
10
10
  Never runs ``git checkout -b`` in the caller's working tree. Fetches the base
11
- ref, then ``git worktree add -b --no-track`` into ``Temp/<agent>/<branch>``
12
- (Windows) or ``gettempdir()/<agent>/<branch>`` elsewhere. Exit 0 prints success
13
- JSON; any failure prints ``{"error": ...}`` and exits non-zero.
11
+ ref, then ``git worktree add -b --no-track`` into
12
+ ``<repo-root>/.claude/worktrees/<agent>/<branch>``. Exit 0 prints success JSON;
13
+ any failure prints ``{"error": ...}`` and exits non-zero.
14
14
  """
15
15
 
16
16
  from __future__ import annotations
@@ -20,7 +20,6 @@ import json
20
20
  import os
21
21
  import re
22
22
  import sys
23
- import tempfile
24
23
  from pathlib import Path
25
24
 
26
25
  from fresh_branch_git_commands import (
@@ -33,7 +32,7 @@ from fresh_branch_git_commands import (
33
32
  from fresh_branch_scripts_constants.fresh_branch_cli_constants import (
34
33
  AGENT_SLUG_PATTERN,
35
34
  ALL_AGENT_DETECTION_MARKERS,
36
- ALL_WINDOWS_USER_SCRATCH_PARTS,
35
+ ALL_REPOSITORY_WORKTREE_ROOT_PARTS,
37
36
  DEFAULT_AGENT_SLUG,
38
37
  DEFAULT_BASE_REF,
39
38
  ERROR_AGENT_SLUG_INVALID,
@@ -57,8 +56,6 @@ from fresh_branch_scripts_constants.fresh_branch_cli_constants import (
57
56
  PAYLOAD_KEY_REPO_ROOT,
58
57
  PAYLOAD_KEY_WORKTREE_PATH,
59
58
  UNIQUE_PATH_SUFFIX_START,
60
- USERPROFILE_ENV_VAR,
61
- WINDOWS_PLATFORM_PREFIX,
62
59
  )
63
60
 
64
61
 
@@ -94,28 +91,26 @@ def _detect_agent_slug_from_environment() -> str:
94
91
  return DEFAULT_AGENT_SLUG
95
92
 
96
93
 
97
- def resolve_agent_worktree_root(agent_slug: str) -> Path:
98
- """Return ``Temp/<agent>`` on Windows USERPROFILE, else gettempdir root.
94
+ def resolve_agent_worktree_root(repo_root: Path, agent_slug: str) -> Path:
95
+ """Return the repository's per-agent worktree root.
99
96
 
100
97
  ::
101
98
 
102
- # win32 + USERPROFILE=C:/Users/x -> C:/Users/x/AppData/Local/Temp/grok
103
- resolve_agent_worktree_root("grok")
99
+ # repo_root=/srv/app, agent_slug=grok
100
+ resolve_agent_worktree_root(Path("/srv/app"), "grok")
101
+ # -> /srv/app/.claude/worktrees/grok
102
+
103
+ Every worktree sits under the repository it branches from, so a worktree
104
+ travels with its repository and each agent keeps its own subdirectory.
104
105
 
105
106
  Args:
107
+ repo_root: Absolute path of the repository the branch comes from.
106
108
  agent_slug: Short host label (one path segment).
107
109
 
108
110
  Returns:
109
111
  Directory that should hold per-branch worktree folders.
110
112
  """
111
- if sys.platform.startswith(WINDOWS_PLATFORM_PREFIX):
112
- user_profile = os.environ.get(USERPROFILE_ENV_VAR)
113
- if user_profile:
114
- return Path(user_profile).joinpath(
115
- *ALL_WINDOWS_USER_SCRATCH_PARTS,
116
- agent_slug,
117
- )
118
- return Path(tempfile.gettempdir()) / agent_slug
113
+ return repo_root.joinpath(*ALL_REPOSITORY_WORKTREE_ROOT_PARTS, agent_slug)
119
114
 
120
115
 
121
116
  def resolve_unique_worktree_path(preferred_path: Path) -> Path:
@@ -181,13 +176,33 @@ def create_fresh_branch(
181
176
  ::
182
177
 
183
178
  create_fresh_branch("fix/x", Path("."), "grok", "origin/main")
179
+
180
+ The caller's working tree is never checked out. The worktree lands under
181
+ the repository's ``.claude/worktrees/<agent>/<branch>``, suffixed ``-2``,
182
+ ``-3``, … when that path is already taken.
183
+
184
+ Args:
185
+ branch_name: Branch to create; must be a safe relative path.
186
+ repo_path: Any path inside the repository the branch comes from.
187
+ agent_slug: Short host label naming the worktree-root subdirectory.
188
+ base_ref: Ref the branch starts from, such as ``origin/main``.
189
+
190
+ Returns:
191
+ The success payload: branch, worktree_path, base_ref, base_commit,
192
+ agent, and repo_root.
193
+
194
+ Raises:
195
+ ValueError: When the branch name or the agent slug is unsafe.
196
+ RuntimeError: When git refuses the fetch or the worktree add.
184
197
  """
185
198
  cleaned_branch = _require_safe_branch_name(branch_name)
186
199
  normalized_agent_slug = _normalize_agent_slug(agent_slug)
187
200
  resolved_base_ref, repo_root, base_commit = _resolve_branch_base(
188
201
  repo_path, base_ref,
189
202
  )
190
- worktree_path = _allocate_worktree_path(cleaned_branch, normalized_agent_slug)
203
+ worktree_path = _allocate_worktree_path(
204
+ cleaned_branch, normalized_agent_slug, repo_root,
205
+ )
191
206
  create_worktree_branch(
192
207
  repo_root,
193
208
  branch_name=cleaned_branch,
@@ -241,8 +256,11 @@ def _require_safe_branch_name(branch_name: str) -> str:
241
256
  return cleaned_branch
242
257
 
243
258
 
244
- def _allocate_worktree_path(branch_name: str, agent_slug: str) -> Path:
245
- agent_worktree_root = resolve_agent_worktree_root(agent_slug)
259
+ def _allocate_worktree_path(
260
+ branch_name: str, agent_slug: str, repo_root: Path,
261
+ ) -> Path:
262
+ agent_worktree_root = resolve_agent_worktree_root(repo_root, agent_slug)
263
+ agent_worktree_root.mkdir(parents=True, exist_ok=True)
246
264
  preferred_path = agent_worktree_root / branch_name
247
265
  _assert_path_is_under_agent_root(
248
266
  candidate_path=preferred_path,
@@ -324,7 +342,7 @@ def _parse_arguments() -> argparse.Namespace:
324
342
  parser.add_argument(
325
343
  "--agent",
326
344
  default=None,
327
- help="Host label for Temp/<agent>/ (default: detect from environment).",
345
+ help="Host label for .claude/worktrees/<agent>/ (default: detect from environment).",
328
346
  )
329
347
  parser.add_argument(
330
348
  "--base",
@@ -23,9 +23,7 @@ ALL_AGENT_DETECTION_MARKERS: tuple[tuple[str, str], ...] = (
23
23
  PATH_SEGMENT_CURRENT = "."
24
24
  PATH_SEGMENT_PARENT = ".."
25
25
 
26
- WINDOWS_PLATFORM_PREFIX = "win"
27
- ALL_WINDOWS_USER_SCRATCH_PARTS = ("AppData", "Local", "Temp")
28
- USERPROFILE_ENV_VAR = "USERPROFILE"
26
+ ALL_REPOSITORY_WORKTREE_ROOT_PARTS = (".claude", "worktrees")
29
27
 
30
28
  MAXIMUM_UNIQUE_PATH_ATTEMPTS = 100
31
29
  UNIQUE_PATH_SUFFIX_START = 2