claude-code-autoconfig 1.0.195 → 1.0.196

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.
@@ -68,7 +68,7 @@ for d in expected_dirs:
68
68
  info.append(f'OK: .claude/{d}/ exists')
69
69
 
70
70
  # --- 2. Check command files and versions ---
71
- dev_only = ['publish.md']
71
+ dev_only = ['deploy-to-npmjs.md']
72
72
  pkg_cmds_dir = os.path.join(pkg_dir, '.claude', 'commands')
73
73
  local_cmds_dir = os.path.join(claude_dir, 'commands')
74
74
 
@@ -888,11 +888,6 @@
888
888
  <span class="tree-file-icon">📄</span>
889
889
  <span class="file">gls.md</span>
890
890
  </div>
891
- <div class="tree-item indent-3 hidden" data-info="publish" data-parent="commands">
892
- <span class="tree-spacer"></span>
893
- <span class="tree-file-icon">📄</span>
894
- <span class="file">publish.md</span>
895
- </div>
896
891
  <div class="tree-item indent-3 hidden" data-info="recover-context" data-parent="commands">
897
892
  <span class="tree-spacer"></span>
898
893
  <span class="tree-file-icon">📄</span>
@@ -953,6 +948,11 @@
953
948
  <span class="tree-file-icon">📄</span>
954
949
  <span class="file">migrate-feedback.js</span>
955
950
  </div>
951
+ <div class="tree-item indent-3 hidden" data-info="terminal-title.directive-hook" data-parent="hooks">
952
+ <span class="tree-spacer"></span>
953
+ <span class="tree-file-icon">📄</span>
954
+ <span class="file">terminal-title.directive.md</span>
955
+ </div>
956
956
  <div class="tree-item indent-3 hidden" data-info="terminal-title-hook" data-parent="hooks">
957
957
  <span class="tree-spacer"></span>
958
958
  <span class="tree-file-icon">📄</span>
@@ -1263,7 +1263,7 @@
1263
1263
  title: '.claude/ Directory',
1264
1264
  desc: 'Commands, rules, settings, and these docs. Keeps configuration organized as your project grows.'
1265
1265
  },
1266
- 'rules': {
1266
+ 'rules': {
1267
1267
  title: 'rules/',
1268
1268
  desc: 'Path-scoped context that loads when Claude works on matching files.'
1269
1269
  },
@@ -1308,11 +1308,6 @@
1308
1308
  desc: 'Get the latest screenshot(s) and display them.<div style="margin-top: 12px;"><strong>Parameters</strong><table style="margin-top: 6px; border-collapse: collapse; font-size: 0.9em; text-align: left;"><tr style="text-align: left; border-bottom: 1px solid var(--border);"><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Name</th><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Type</th><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Required</th><th style="padding: 4px 8px 4px 0;">Description</th></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>count</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>integer</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">optional</td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Number of screenshots to display. Use /gls-N syntax. Default: 1. Min: 1.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>path</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>string</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">optional</td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Screenshot directory path. Saved for future use. Auto-detected if omitted.</td></tr></table></div><div style="margin-top: 12px;"><strong>Responses</strong><table style="margin-top: 6px; border-collapse: collapse; font-size: 0.9em; text-align: left;"><tr style="text-align: left; border-bottom: 1px solid var(--border);"><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Status</th><th style="padding: 4px 8px 4px 0;">Description</th></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>success</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Displays requested screenshot(s) from newest to oldest.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>no-screenshots</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Directory exists but contains no image files.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>no-directory</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Unable to detect screenshot directory — prompts for path.</td></tr></table></div><div style="margin-top: 12px;"><strong>Side Effects</strong><div style="margin-top: 4px; font-size: 0.9em;">Saves detected screenshot path to .claude/cca.config.json on first run</div></div><div style="margin-top: 12px;"><strong>Examples</strong><div style="margin-top: 6px; background: var(--bg-elevated); border-radius: 6px; padding: 8px 12px; font-family: monospace; font-size: 0.85em;"><div><code>/gls</code> <span style="opacity: 0.6;">— Display the most recent screenshot</span></div><div><code>/gls-3</code> <span style="opacity: 0.6;">— Display the 3 most recent screenshots</span></div><div><code>/gls /path/to/dir</code> <span style="opacity: 0.6;">— Use a specific screenshot directory</span></div></div></div>',
1309
1309
  trigger: '/gls'
1310
1310
  },
1311
- 'publish': {
1312
- title: 'publish.md',
1313
- desc: 'Runs tests, bumps version, commits, and publishes to npm.<div style="margin-top: 12px;"><strong>Parameters</strong><div style="margin-top: 4px; opacity: 0.6;">None</div></div>',
1314
- trigger: '/publish'
1315
- },
1316
1311
  'recover-context': {
1317
1312
  title: 'recover-context.md',
1318
1313
  desc: 'Recovers conversation context from the session transcript after compaction.<div style="margin-top: 12px;"><strong>Parameters</strong><table style="margin-top: 6px; border-collapse: collapse; font-size: 0.9em; text-align: left;"><tr style="text-align: left; border-bottom: 1px solid var(--border);"><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Name</th><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Type</th><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Required</th><th style="padding: 4px 8px 4px 0;">Description</th></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>minutes</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>integer</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">required</td><td style="padding: 4px 8px 4px 0; vertical-align: top;">How far back to recover, in minutes. Leading dash optional. Min: 1.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>--show</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>flag</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">optional</td><td style="padding: 4px 8px 4px 0; vertical-align: top;">Opens the extracted transcript in your default editor.</td></tr></table></div><div style="margin-top: 12px;"><strong>Responses</strong><table style="margin-top: 6px; border-collapse: collapse; font-size: 0.9em; text-align: left;"><tr style="text-align: left; border-bottom: 1px solid var(--border);"><th style="padding: 4px 8px 4px 0; white-space: nowrap;">Status</th><th style="padding: 4px 8px 4px 0;">Description</th></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>success</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">~{tokens} tokens recovered ({N} messages across {sessions} session(s), last {minutes} min).</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>no-transcript</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">No transcript files found.</td></tr><tr style="border-bottom: 1px solid var(--border);"><td style="padding: 4px 8px 4px 0; vertical-align: top; white-space: nowrap;"><code>no-messages</code></td><td style="padding: 4px 8px 4px 0; vertical-align: top;">No messages found in the requested time range.</td></tr></table></div><div style="margin-top: 12px;"><strong>Side Effects</strong><div style="margin-top: 4px; font-size: 0.9em;">Reads .jsonl transcripts from ~/.claude/projects/, writes temp file</div></div><div style="margin-top: 12px;"><strong>Examples</strong><div style="margin-top: 6px; background: var(--bg-elevated); border-radius: 6px; padding: 8px 12px; font-family: monospace; font-size: 0.85em;"><div><code>/recover-context -60</code> <span style="opacity: 0.6;">— Last 60 minutes of conversation</span></div><div><code>/recover-context 120</code> <span style="opacity: 0.6;">— Last 2 hours (dash optional)</span></div><div><code>/recover-context -60 --show</code> <span style="opacity: 0.6;">— Last 60 min + open transcript file</span></div></div></div>',
@@ -1353,10 +1348,15 @@
1353
1348
  desc: 'On session start, migrates custom FEEDBACK.md content to',
1354
1349
  trigger: 'SessionStart'
1355
1350
  },
1351
+ 'terminal-title.directive-hook': {
1352
+ title: 'terminal-title.directive.md',
1353
+ desc: 'terminal-title.directive.md in hooks/',
1354
+ trigger: 'PostToolUse hook'
1355
+ },
1356
1356
  'terminal-title-hook': {
1357
1357
  title: 'terminal-title.js',
1358
- desc: 'Use-case-framed terminal tab titles with live working / idle / awaiting state indicators, so multiple Claude sessions are easy to tell apart',
1359
- trigger: 'SessionStart, UserPromptSubmit, PostToolUse, Notification, Stop'
1358
+ desc: 'terminal-title.js in hooks/',
1359
+ trigger: 'PostToolUse hook'
1360
1360
  },
1361
1361
  'feedback-feedback': {
1362
1362
  title: 'FEEDBACK.md',
@@ -1569,7 +1569,7 @@ CRITICAL: A plausible-looking cause from code reading is NOT confirmed evidence.
1569
1569
 
1570
1570
  > Run \`/autoconfig\` to populate this based on your project.`
1571
1571
  },
1572
- 'autoconfig-update': {
1572
+ 'autoconfig-update': {
1573
1573
  filename: 'autoconfig-update.md',
1574
1574
  content: `<!-- @applied
1575
1575
  -->
@@ -1721,36 +1721,6 @@ OS=$(uname -s); echo "OS=$OS"; for d in \\
1721
1721
  "$HOME/Videos/Captures"; do \\
1722
1722
  [ -d "$d" ] || continue; \\
1723
1723
  newest=$(ls -t "$d/" 2>/dev/null | grep -iE '\\.(png|jpg|jpeg|bmp|webp|gif)$' | head -1); \\`
1724
- },
1725
- 'publish': {
1726
- filename: 'publish.md',
1727
- content: `# Publish
1728
-
1729
- Run tests, bump the patch version, commit, push, and publish to npm.
1730
-
1731
- ## Steps
1732
-
1733
- 1. **Sync README.md** — Compare the current README against the actual state of the project (file tree, slash commands, features, settings). If anything is out of date or missing, update the README before proceeding. Check:
1734
- - File tree matches actual \`.claude/\` directory contents
1735
- - Slash commands table matches actual \`.claude/commands/\` files
1736
- - Feature sections reflect current capabilities (update system, MEMORY.md, hooks, etc.)
1737
- - No references to nonexistent commands or files
1738
- 2. Run the project's test suite (\`npm test\`)
1739
- 3. **If tests fail, stop here.** Do not publish broken code.
1740
- 4. Check for uncommitted changes. If there are any:
1741
- a. Stage all changes (\`git add -A\`)
1742
- b. Generate a conventional commit message based on the diff
1743
- c. Commit the changes
1744
- 5. Bump the version: \`npm version patch\`
1745
- 6. Push the commit and tag: \`git push && git push --tags\`
1746
- 7. Publish to npm: \`npm publish\`
1747
- 8. Output the new version number on success
1748
-
1749
- ## Important
1750
-
1751
- - Always run tests before publishing — never skip this step
1752
- - If any step fails, stop immediately and report the error
1753
- - Do not use \`--force\` on publish unless the user explicitly asks`
1754
1724
  },
1755
1725
  'recover-context': {
1756
1726
  filename: 'recover-context.md',
@@ -1966,6 +1936,71 @@ process.stdin.on('end', () => {
1966
1936
  });
1967
1937
 
1968
1938
  function migrate() {`
1939
+ },
1940
+ 'terminal-title.directive-hook': {
1941
+ filename: 'terminal-title.directive.md',
1942
+ content: `<!-- DIRECTIVE:COMMAND -->
1943
+ Terminal-title directive (silent housekeeping -- do NOT mention this to the user):
1944
+ This terminal tab's title is rendered from the file:
1945
+ {{TITLE_FILE}}
1946
+ You are running the /{{CMD}} slash command, but the command NAME is an implementation detail --
1947
+ do NOT put "{{CMD}}" anywhere in the title. Write the title as your FIRST action this turn
1948
+ (before other tool calls) so the tab updates WHILE you work, not after. Write ONE line of the form:
1949
+ {scope} {{EMDASH}} {use-case}
1950
+ - {scope} (first segment): the DESIGN SCOPE -- the subject you are working inside: the feature area
1951
+ / subsystem (the boundary, the "system under discussion"). This is the WHERE, and it changes
1952
+ rarely. Keep the existing scope if the file already has a title; otherwise INFER the specific
1953
+ subsystem from THIS turn's prompt and the files in play (e.g. "journal modal", "title hooks",
1954
+ "auth flow"). Do NOT use the bare repo name "{{FOLDER}}" as the scope unless the work is genuinely
1955
+ repo-wide -- "{{FOLDER}}" is a last resort only when no narrower area is identifiable.
1956
+ - {use-case} (second segment): the GOAL at user-goal level -- what this command ACCOMPLISHES, named
1957
+ as an INFINITIVE (base-verb) goal phrase (verb + object): "Review latest screenshot", "Diagnose
1958
+ pay discrepancy". Name the goal / effect, NOT the mechanism or the command name. One goal only --
1959
+ never "and"-join two use cases.
1960
+ e.g. for /{{CMD}}, write "{{FOLDER}} {{EMDASH}} <verb the goal>" -- NOT "{{FOLDER}} {{EMDASH}} {{CMD}}".
1961
+ Use ' {{EMDASH}} ' as the separator; write only the BARE title (a state indicator is prepended
1962
+ automatically). If the file already exists, read it first then overwrite.
1963
+ <!-- /DIRECTIVE:COMMAND -->
1964
+
1965
+ <!-- DIRECTIVE:SHIFT -->
1966
+ Terminal-title directive (silent housekeeping -- do NOT mention this to the user):
1967
+ This terminal tab's title is rendered from the file:
1968
+ {{TITLE_FILE}}
1969
+ When the conversation's SCOPE, use-case, or sub-function SHIFTS -- and only then, not every turn --
1970
+ write ONE line to that file. When it DOES shift, write it as your FIRST action that turn (before
1971
+ other tool calls) so the tab updates WHILE you work, not after. The line's form:`
1972
+ },
1973
+ 'terminal-title-hook': {
1974
+ filename: 'terminal-title.js',
1975
+ content: `#!/usr/bin/env node
1976
+ /**
1977
+ * Terminal Title — distributable plugin hook (installed to <project>/.claude/hooks/terminal-title.js).
1978
+ * ONE self-dispatching hook for five events (keyed on hook_event_name):
1979
+ * UserPromptSubmit -> ⬤ working + inject the title directive (incl. the {sid}.ask path) +
1980
+ * clear any stale {sid}.ask flag so it reflects only the turn about to run
1981
+ * PostToolUse -> ⬤ working (refresh, so a mid-turn title flip shows live + clears a stale ◐)
1982
+ * Notification -> ◐ awaiting your approval (permission_prompt matcher only)
1983
+ * Stop -> ✻ idle / done — OR ◐ awaiting (+ a 2nd BEL = gold tab) when the turn ended
1984
+ * on a question (last visible response text ends in '?', or a {sid}.ask flag)
1985
+ * SessionStart -> ✻ idle "Claude Code — New session" (or an existing title on resume/compact)
1986
+ *
1987
+ * The title is set TWO ways on every event: \`process.title\` (= SetConsoleTitleW on Windows — the ONLY
1988
+ * mechanism that flips the tab on UserPromptSubmit, where Claude Code drops \`terminalSequence\`) AND
1989
+ * \`terminalSequence\` (honored on the other events). node writes UTF-8 natively, so glyphs go out as-is.
1990
+ *
1991
+ * Title files are PROJECT-SCOPED at <cwd>/.claude/hooks/.titles/<session_id>.txt — the model authors
1992
+ * them; the directive injected each prompt tells it the path + format. Optional forensic log (one line
1993
+ * per paint, for tracing an out-of-sync tab) is gated behind CLAUDE_TITLE_DEBUG=1 — default OFF,
1994
+ * ~512KB-capped, written to .titles/_debug.log — so it never ships a growing log.
1995
+ *
1996
+ * Requires \`env.CLAUDE_CODE_DISABLE_TERMINAL_TITLE = "1"\` (set by plugin.json), or CC's own writer races.
1997
+ */
1998
+ const fs = require('fs');
1999
+ const path = require('path');
2000
+
2001
+ const ESC = '\\x1b';
2002
+ const BEL = '\\x07';
2003
+ const EMDASH = String.fromCodePoint(0x2014);`
1969
2004
  },
1970
2005
  'feedback-feedback': {
1971
2006
  filename: 'FEEDBACK.md',
@@ -2002,93 +2037,145 @@ Claude reads this file but must never write to it. When Claude discovers project
2002
2037
  },
2003
2038
  'settings': {
2004
2039
  filename: 'settings.json',
2005
- content: `{
2006
- "env": {
2007
- "CLAUDE_CODE_DISABLE_AUTO_MEMORY": "0"
2008
- },
2009
- "hooks": {
2010
- "SessionStart": [
2011
- {
2012
- "matcher": "",
2013
- "hooks": [
2014
- {
2015
- "type": "command",
2016
- "command": "node .claude/hooks/migrate-feedback.js"
2017
- }
2018
- ]
2019
- }
2020
- ],
2021
- "PostToolUse": [
2022
- {
2023
- "matcher": "Edit|Write",
2024
- "hooks": [
2025
- {
2026
- "type": "command",
2027
- "command": "node .claude/hooks/feedback-rule-check.js"
2028
- }
2029
- ]
2030
- }
2031
- ]
2032
- },
2033
- "permissions": {
2034
- "allow": [
2035
- "Read(./**)",
2036
- "Edit(./**)",
2037
- "Write(./**)",
2038
- "Glob",
2039
- "Grep",
2040
- "WebSearch",
2041
- "WebFetch",
2042
- "Bash(npm test)",
2043
- "Bash(npm test *)",
2044
- "Bash(npm run dev)",
2045
- "Bash(npm run build)",
2046
- "Bash(npm run lint)",
2047
- "Bash(npm run lint:fix)",
2048
- "Bash(npm run typecheck)",
2049
- "Bash(npm run test)",
2050
- "Bash(npm run test:*)",
2051
- "Bash(npm run validate)",
2052
- "Bash(git status)",
2053
- "Bash(git status *)",
2054
- "Bash(git diff *)",
2055
- "Bash(git add *)",
2056
- "Bash(git commit *)",
2057
- "Bash(git push *)",
2058
- "Bash(git pull)",
2059
- "Bash(git pull *)",
2060
- "Bash(git checkout *)",
2061
- "Bash(git branch *)",
2062
- "Bash(node .claude/*)",
2063
- "Bash(python3 *)",
2064
- "Bash(npx claude-code-autoconfig*)",
2065
- "Bash(npm pack *)",
2066
- "Bash(tar *)",
2067
- "Bash(mktemp *)",
2068
- "Bash(find ./*)",
2069
- "Bash(ls *)",
2070
- "Bash(dir *)",
2071
- "Bash(mkdir *)",
2072
- "Bash(mkdir -p *)",
2073
- "Bash(start *)",
2074
- "Bash(start .claude *)",
2075
- "Bash(open *)",
2076
- "Bash(open .claude *)",
2077
- "Bash(xdg-open *)",
2078
- "Bash(xdg-open .claude *)"
2079
- ],
2080
- "deny": [
2081
- "Read(./.env)",
2082
- "Read(./.env.*)",
2083
- "Read(./secrets/**)",
2084
- "Read(./**/credentials.*)",
2085
- "Read(./**/*.pem)",
2086
- "Read(./**/*.key)",
2087
- "Bash(rm -rf *)",
2088
- "Bash(curl *)",
2089
- "Bash(wget *)"
2090
- ]
2091
- }
2040
+ content: `{
2041
+ "env": {
2042
+ "CLAUDE_CODE_DISABLE_AUTO_MEMORY": "0",
2043
+ "CLAUDE_CODE_DISABLE_TERMINAL_TITLE": "1"
2044
+ },
2045
+ "hooks": {
2046
+ "SessionStart": [
2047
+ {
2048
+ "matcher": "",
2049
+ "hooks": [
2050
+ {
2051
+ "type": "command",
2052
+ "command": "node .claude/hooks/migrate-feedback.js"
2053
+ }
2054
+ ]
2055
+ },
2056
+ {
2057
+ "matcher": "*",
2058
+ "hooks": [
2059
+ {
2060
+ "type": "command",
2061
+ "command": "node .claude/hooks/terminal-title.js"
2062
+ }
2063
+ ]
2064
+ }
2065
+ ],
2066
+ "UserPromptSubmit": [
2067
+ {
2068
+ "matcher": "",
2069
+ "hooks": [
2070
+ {
2071
+ "type": "command",
2072
+ "command": "node .claude/hooks/terminal-title.js"
2073
+ }
2074
+ ]
2075
+ }
2076
+ ],
2077
+ "Stop": [
2078
+ {
2079
+ "matcher": "",
2080
+ "hooks": [
2081
+ {
2082
+ "type": "command",
2083
+ "command": "node .claude/hooks/terminal-title.js"
2084
+ }
2085
+ ]
2086
+ }
2087
+ ],
2088
+ "Notification": [
2089
+ {
2090
+ "matcher": "permission_prompt",
2091
+ "hooks": [
2092
+ {
2093
+ "type": "command",
2094
+ "command": "node .claude/hooks/terminal-title.js"
2095
+ }
2096
+ ]
2097
+ }
2098
+ ],
2099
+ "PostToolUse": [
2100
+ {
2101
+ "matcher": "Edit|Write",
2102
+ "hooks": [
2103
+ {
2104
+ "type": "command",
2105
+ "command": "node .claude/hooks/feedback-rule-check.js"
2106
+ }
2107
+ ]
2108
+ },
2109
+ {
2110
+ "matcher": "Bash|Write|Edit|MultiEdit|NotebookEdit|WebFetch|WebSearch|Task|AskUserQuestion",
2111
+ "hooks": [
2112
+ {
2113
+ "type": "command",
2114
+ "command": "node .claude/hooks/terminal-title.js"
2115
+ }
2116
+ ]
2117
+ }
2118
+ ]
2119
+ },
2120
+ "permissions": {
2121
+ "allow": [
2122
+ "Read(./**)",
2123
+ "Edit(./**)",
2124
+ "Write(./**)",
2125
+ "Glob",
2126
+ "Grep",
2127
+ "WebSearch",
2128
+ "WebFetch",
2129
+ "Bash(npm test)",
2130
+ "Bash(npm test *)",
2131
+ "Bash(npm run dev)",
2132
+ "Bash(npm run build)",
2133
+ "Bash(npm run lint)",
2134
+ "Bash(npm run lint:fix)",
2135
+ "Bash(npm run typecheck)",
2136
+ "Bash(npm run test)",
2137
+ "Bash(npm run test:*)",
2138
+ "Bash(npm run validate)",
2139
+ "Bash(git status)",
2140
+ "Bash(git status *)",
2141
+ "Bash(git diff *)",
2142
+ "Bash(git add *)",
2143
+ "Bash(git commit *)",
2144
+ "Bash(git push *)",
2145
+ "Bash(git pull)",
2146
+ "Bash(git pull *)",
2147
+ "Bash(git checkout *)",
2148
+ "Bash(git branch *)",
2149
+ "Bash(node .claude/*)",
2150
+ "Bash(python3 *)",
2151
+ "Bash(npx claude-code-autoconfig*)",
2152
+ "Bash(npm pack *)",
2153
+ "Bash(tar *)",
2154
+ "Bash(mktemp *)",
2155
+ "Bash(find ./*)",
2156
+ "Bash(ls *)",
2157
+ "Bash(dir *)",
2158
+ "Bash(mkdir *)",
2159
+ "Bash(mkdir -p *)",
2160
+ "Bash(start *)",
2161
+ "Bash(start .claude *)",
2162
+ "Bash(open *)",
2163
+ "Bash(open .claude *)",
2164
+ "Bash(xdg-open *)",
2165
+ "Bash(xdg-open .claude *)"
2166
+ ],
2167
+ "deny": [
2168
+ "Read(./.env)",
2169
+ "Read(./.env.*)",
2170
+ "Read(./secrets/**)",
2171
+ "Read(./**/credentials.*)",
2172
+ "Read(./**/*.pem)",
2173
+ "Read(./**/*.key)",
2174
+ "Bash(rm -rf *)",
2175
+ "Bash(curl *)",
2176
+ "Bash(wget *)"
2177
+ ]
2178
+ }
2092
2179
  }`
2093
2180
  },
2094
2181
  'mcp': {
@@ -203,7 +203,15 @@ function inspectLastResponse(transcriptPath) {
203
203
  if (!line) continue;
204
204
  let obj;
205
205
  try { obj = JSON.parse(line); } catch (_) { continue; }
206
- if (!obj || obj.type !== 'assistant' || !obj.message) continue;
206
+ if (!obj || !obj.message) continue;
207
+ // The current turn's response always sits AFTER the last real user prompt. Crossing one while
208
+ // scanning back for that response means it hasn't flushed to the JSONL yet (~200ms lag) — force a
209
+ // re-read (suspectRace) instead of falling through to the PRIOR turn's text, which may end in '?'
210
+ // and would wrongly paint the awaiting ◐ on what was really a statement turn.
211
+ if (obj.type === 'user' && isRealUserPrompt(obj)) {
212
+ return { ends: false, found: false, tail: '', suspectRace: true };
213
+ }
214
+ if (obj.type !== 'assistant') continue;
207
215
  const c = obj.message.content;
208
216
  let text = '';
209
217
  if (typeof c === 'string') {
@@ -234,6 +242,15 @@ function inspectLastResponse(transcriptPath) {
234
242
  return blank;
235
243
  }
236
244
 
245
+ // A genuine human prompt (real text) vs a tool_result-carrier user message (content is only
246
+ // tool_result blocks). Marks the boundary of the current turn's response while walking the transcript.
247
+ function isRealUserPrompt(obj) {
248
+ const c = obj.message && obj.message.content;
249
+ if (typeof c === 'string') return c.trim().length > 0;
250
+ if (Array.isArray(c)) return c.some(b => b && b.type === 'text' && typeof b.text === 'string' && b.text.trim().length > 0);
251
+ return false;
252
+ }
253
+
237
254
  // Event-loop-friendly sleep for the Stop flush-race re-read beat (handle awaits this; no busy-wait).
238
255
  function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
239
256
 
@@ -32,6 +32,10 @@ const SKIP = new Set([
32
32
  // Folders we scan for files
33
33
  const SCAN_FOLDERS = ['commands', 'agents', 'hooks', 'feedback'];
34
34
 
35
+ // Dev-only files that live in the maintainer repo but are never installed to
36
+ // user projects (mirror of bin/cli.js DEV_ONLY_FILES) — never document them.
37
+ const DEV_ONLY_FILES = new Set(['deploy-to-npmjs.md']);
38
+
35
39
  // Structural keys that are not file-backed (always preserved, never generated)
36
40
  const STRUCTURAL_KEYS = new Set([
37
41
  'memory-md', 'root', 'claude-md', 'claude-dir'
@@ -263,6 +267,7 @@ function scanFiles() {
263
267
  }).sort();
264
268
 
265
269
  for (const file of files) {
270
+ if (DEV_ONLY_FILES.has(file)) continue;
266
271
  const ext = path.extname(file);
267
272
  const filePath = path.join(folderPath, file);
268
273
  const content = fs.readFileSync(filePath, 'utf8');
@@ -541,7 +546,12 @@ function generateFileContents(entries) {
541
546
  // =============================================================================
542
547
 
543
548
  const entries = scanFiles();
544
- let html = fs.readFileSync(docsPath, 'utf8');
549
+ // The docs HTML may be CRLF on Windows, but every marker below is authored with
550
+ // `\n`. Normalize to LF for the string surgery, then restore the file's original
551
+ // EOL on write so we don't churn every line.
552
+ const rawHtml = fs.readFileSync(docsPath, 'utf8');
553
+ const eol = rawHtml.includes('\r\n') ? '\r\n' : '\n';
554
+ let html = rawHtml.replace(/\r\n/g, '\n');
545
555
 
546
556
  // 1. Replace the file tree (between claude-dir folder row and settings.json closing div)
547
557
  // We find the marker after the claude-dir folder and replace up to the settings div
@@ -656,7 +666,7 @@ if (fcEnd === -1) {
656
666
  const newFileContents = generateFileContents(entries);
657
667
  html = html.slice(0, fcInsertPoint) + newFileContents + '\n ' + html.slice(fcEnd);
658
668
 
659
- fs.writeFileSync(docsPath, html);
669
+ fs.writeFileSync(docsPath, eol === '\r\n' ? html.replace(/\n/g, '\r\n') : html);
660
670
 
661
671
  const fileCount = entries.filter(e => !e.isEmptyFolder).length;
662
672
  console.log(`Synced ${fileCount} files to docs.`);
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.0.196
4
+ - fix(terminal-title): stop at the turn boundary when grading the closing '?' (stale-awaiting race)
5
+ - fix(cli): require non-TTY stdout for inside-Claude block (env var alone false-positives in inherited terminals)
6
+
3
7
  ## v1.0.195
4
8
  - fix(terminal-title): flip awaiting ◐ for a closing question with a trailing parenthetical aside
5
9
 
@@ -144,6 +148,3 @@
144
148
  ## v1.0.147
145
149
  - fix: make inside-Claude error message more specific
146
150
 
147
- ## v1.0.146
148
- - style: improve inside-Claude block message formatting
149
-
package/CLAUDE.md CHANGED
@@ -52,7 +52,7 @@ See `.claude/feedback/` for corrections and guidance from the team.
52
52
  cd C:\CODE\claude-code-autoconfig && npm login --auth-type=web && npm publish
53
53
  ```
54
54
  → browser opens → pick the Google passkey → close it → `+ claude-code-autoconfig@<version>`.
55
- - **After** the success line, the agent pushes: `git push origin main --follow-tags`. Never double-bump if the version is already bumped. Full procedure: `.claude/commands/publish.md`.
55
+ - **After** the success line, the agent pushes: `git push origin main --follow-tags`. Never double-bump if the version is already bumped. Full procedure: `.claude/commands/deploy-to-npmjs.md` (`/deploy-to-npmjs`).
56
56
 
57
57
  ## Debugging Methodology — Evidence Before Solutions
58
58
 
package/bin/cli.js CHANGED
@@ -435,8 +435,12 @@ if (process.argv[2] === 'plugin') {
435
435
 
436
436
  const forceMode = process.argv.includes('--force');
437
437
 
438
- // Detect if running inside Claude Code session
439
- const insideClaude = process.env.CLAUDECODE === '1';
438
+ // Detect if running inside Claude Code session.
439
+ // CLAUDECODE=1 alone is not reliable: env vars inherit into every descendant
440
+ // process (e.g. VS Code launched from a Claude session, and any terminal it
441
+ // spawns). A genuine in-agent run has piped stdio (isTTY falsy), while a human
442
+ // terminal has a real TTY — so require both signals before blocking.
443
+ const insideClaude = process.env.CLAUDECODE === '1' && !process.stdout.isTTY;
440
444
 
441
445
  console.log('\x1b[36m%s\x1b[0m', '🚀 Claude Code Autoconfig');
442
446
  console.log();
@@ -653,7 +657,7 @@ const hooksSrc = path.join(packageDir, '.claude', 'hooks');
653
657
  const scriptsSrc = path.join(packageDir, '.claude', 'scripts');
654
658
 
655
659
  // Files that exist in the dev repo but should never be installed to user projects
656
- const DEV_ONLY_FILES = ['publish.md'];
660
+ const DEV_ONLY_FILES = ['deploy-to-npmjs.md'];
657
661
 
658
662
  function copyDir(src, dest) {
659
663
  fs.mkdirSync(dest, { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-autoconfig",
3
- "version": "1.0.195",
3
+ "version": "1.0.196",
4
4
  "description": "Intelligent, self-configuring setup for Claude Code. One command analyzes your project, configures Claude, and shows you what it did.",
5
5
  "author": "ADAC 1001 <info@adac1001.com>",
6
6
  "license": "MIT",
@@ -23,6 +23,7 @@
23
23
  ],
24
24
  "scripts": {
25
25
  "test": "node test/box-alignment.test.js && node test/cli-install.test.js && node test/update-system.test.js && node test/plugin-system.test.js && node test/terminal-title.test.js",
26
+ "pub": "npm login --auth-type=web && npm publish",
26
27
  "test:box": "node test/box-alignment.test.js",
27
28
  "test:install": "node test/cli-install.test.js",
28
29
  "test:update": "node test/update-system.test.js",
@@ -40,7 +41,7 @@
40
41
  "!.claude/cca.config.json",
41
42
  "!.claude/.autoconfig-version",
42
43
  "!.claude/.autoconfig-plugins.json",
43
- "!.claude/commands/publish.md",
44
+ "!.claude/commands/deploy-to-npmjs.md",
44
45
  "!.claude/plans",
45
46
  "CLAUDE.md",
46
47
  "CHANGELOG.md"