feat: implement agent-os standards system and feature planning tools
- Split CODING_GUIDELINES.md into 19 indexed standards files under .claude/standards/ - 9 from CODING_GUIDELINES (conventions, powershell, security, api, git, gururmm) - 10 from session log tribal knowledge (syncro, ssh, gitea, python, client, gururmm) - Add .claude/standards/index.yml for cheap relevance-based lookup - Add /inject-standards command: load targeted standards per task instead of full guidelines - Add /shape-spec command: pre-implementation spec for GuruRMM features (plan.md, shape.md, references.md, standards.md) with mandatory out-of-scope gate - Add docs/tech-stack.md and docs/mission.md for ClaudeTools API - Add projects/msp-tools/guru-rmm/docs/tech-stack.md and mission.md for GuruRMM - Update CLAUDE.md commands table with /inject-standards and /shape-spec Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
58
.claude/standards/powershell/execution-pattern.md
Normal file
58
.claude/standards/powershell/execution-pattern.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
name: execution-pattern
|
||||
description: Always write PowerShell to .ps1 files and run with -NoProfile -File, never -Command inline
|
||||
applies-to: powershell, all
|
||||
---
|
||||
|
||||
# PowerShell Execution Pattern (Windows)
|
||||
|
||||
## Rule: Always use -NoProfile -File
|
||||
|
||||
Never use inline PowerShell commands (`-Command` or `-c`). Always write scripts to `.ps1` files and execute with `-NoProfile -File`.
|
||||
|
||||
## Rationale
|
||||
|
||||
- **Prevents font/codepage changes**: PowerShell profile scripts often set `chcp 65001` or modify `[Console]::OutputEncoding`, which changes the Claude Code CLI font and breaks rendering. `-NoProfile` skips all profile scripts.
|
||||
- **Avoids Git Bash quoting issues**: Inline commands have unpredictable quote escaping and variable expansion (`$_`, `$foo`) before PowerShell sees them. What you write is not what PowerShell receives.
|
||||
- **Enforced by hooks**: `.claude/hooks/pre-bash-pwsh-script.sh` blocks inline execution and rejects the command before it runs.
|
||||
|
||||
## Correct pattern
|
||||
|
||||
```bash
|
||||
# Write script to file using the Write tool
|
||||
# (Write tool creates the file; Bash tool executes it)
|
||||
|
||||
# Execute with -NoProfile -File
|
||||
pwsh -NoProfile -File /tmp/script.ps1
|
||||
```
|
||||
|
||||
Or using a temp file in the claudetools tmp directory (safe from /tmp path mismatch):
|
||||
|
||||
```bash
|
||||
# Write to .claude/tmp/ which both Write tool and Bash agree on
|
||||
pwsh -NoProfile -File D:/claudetools/.claude/tmp/script.ps1
|
||||
```
|
||||
|
||||
## Incorrect (BLOCKED BY HOOKS)
|
||||
|
||||
```bash
|
||||
# These will be rejected by the pre-bash-pwsh-script.sh hook
|
||||
powershell -Command "Get-Process"
|
||||
pwsh -c "Get-Date"
|
||||
powershell.exe -Command '$x = 5; Write-Host $x'
|
||||
powershell.exe -Command "Get-Service GuruRMMAgent"
|
||||
```
|
||||
|
||||
## Hook enforcement
|
||||
|
||||
The hook at `.claude/hooks/pre-bash-pwsh-script.sh` intercepts any `Bash` tool call and checks for the patterns `powershell.*-Command`, `powershell.*-c`, `pwsh.*-c`, `pwsh.*-Command`. If matched, the hook returns a non-zero exit code and the command is rejected.
|
||||
|
||||
The hook extracts only the `tool_input.command` field via `jq` before grepping — this prevents false positives from grep matching echo arguments or heredoc content.
|
||||
|
||||
## Note on /tmp path ambiguity on Windows
|
||||
|
||||
On Windows, `/tmp` resolves differently in Git Bash vs. the Write tool. Git Bash maps `/tmp` to `%LOCALAPPDATA%\Temp\`, while the Write tool may create files in `C:\tmp\`. This mismatch has caused wrong-content file reads in past sessions. Use `D:/claudetools/.claude/tmp/` as the temp directory for any file that needs to be read back by a Bash command.
|
||||
|
||||
## Reference
|
||||
|
||||
See `.claude/hooks/pre-bash-pwsh-script.sh` for enforcement details.
|
||||
68
.claude/standards/powershell/tmp-path-windows.md
Normal file
68
.claude/standards/powershell/tmp-path-windows.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
name: tmp-path-windows
|
||||
description: /tmp resolves to different directories in Git Bash vs Write tool on Windows; use .claude/tmp/ instead
|
||||
applies-to: all
|
||||
---
|
||||
|
||||
# /tmp Path Mismatch on Windows
|
||||
|
||||
## The problem
|
||||
|
||||
On Windows, `/tmp` resolves to two different real directories depending on which tool accesses it:
|
||||
|
||||
| Tool | /tmp resolves to |
|
||||
|------|-----------------|
|
||||
| Git Bash / curl | `%LOCALAPPDATA%\Temp\` (e.g., `C:\Users\Howard\AppData\Local\Temp\`) |
|
||||
| Claude Code Write tool | `C:\tmp\` |
|
||||
|
||||
These are different directories. If you write a file with the Write tool to `/tmp/payload.json` and then read it back with curl in a Bash command, curl reads a stale file from a previous session — or a completely different file.
|
||||
|
||||
## Incident that established this rule
|
||||
|
||||
2026-05-01: The Write tool created `/tmp/comment_payload.json` in `C:\tmp\`. curl read `/tmp/comment_payload.json` from `%LOCALAPPDATA%\Temp\` — a stale payload from the previous day's Cascades session. The wrong comment (containing Karen Rossini / ALDOCS content) was posted to a Sombra ticket. The comment could not be deleted via the Syncro API.
|
||||
|
||||
## The fix: use .claude/tmp/ or heredocs
|
||||
|
||||
**Option 1 — Heredoc (preferred for JSON payloads):**
|
||||
|
||||
```bash
|
||||
curl -s -X POST "${URL}" -H "Content-Type: application/json" --data-binary @- <<'JSON'
|
||||
{"key": "value", "other": "data"}
|
||||
JSON
|
||||
```
|
||||
|
||||
No file involved — no path ambiguity. Use `<<'JSON'` for static content and `<<JSON` when you need shell variable interpolation.
|
||||
|
||||
**Option 2 — .claude/tmp/ directory:**
|
||||
|
||||
Both the Write tool and Git Bash agree on the absolute Windows path when you use the repo-relative temp directory:
|
||||
|
||||
```
|
||||
D:/claudetools/.claude/tmp/
|
||||
```
|
||||
|
||||
Write files there using the Write tool, then read them in Bash with `D:/claudetools/.claude/tmp/filename`. Forward slashes work in Git Bash.
|
||||
|
||||
```bash
|
||||
# After writing with Write tool to D:/claudetools/.claude/tmp/payload.json
|
||||
curl -s -X POST "${URL}" -H "Content-Type: application/json" \
|
||||
-d @D:/claudetools/.claude/tmp/payload.json
|
||||
```
|
||||
|
||||
**Option 3 — Python urllib (no file at all):**
|
||||
|
||||
```bash
|
||||
py -c "
|
||||
import urllib.request, json
|
||||
data = json.dumps({'key': 'value'}).encode()
|
||||
req = urllib.request.Request('$URL', data=data, headers={'Content-Type': 'application/json'})
|
||||
print(urllib.request.urlopen(req).status)
|
||||
"
|
||||
```
|
||||
|
||||
## Applies to
|
||||
|
||||
Any workflow where the Write tool creates a file that is subsequently read by a Bash command on Windows. This includes:
|
||||
- Syncro API payloads
|
||||
- PowerShell script files (use .claude/tmp/ or the Write tool with an absolute path)
|
||||
- Any temp file exchange between Write tool and Bash tool
|
||||
Reference in New Issue
Block a user