# ClaudeTools — Core Operating Rules

> Lean CORE, always loaded. The FULL manual — onboarding steps, work-mode detail, the
> coordination-API protocol, project/command/reference tables, Ollama/GrepAI, vault detail
> — is in **`.claude/CLAUDE_EXTENDED.md`**. Read EXTENDED when: onboarding a new machine,
> switching work modes, using the coord API (locks/messages/todos), provisioning, or
> unsure about any workflow. Harness version: `.claude/harness/VERSION`.

## Identity & multi-user (check first)
Shared repo across the team. At session start read `.claude/identity.json` (gitignored,
per-machine) and greet by name. If it is **missing** (new machine) → run the onboarding
flow in EXTENDED before other work. Team: **Mike Swanson** (admin/owner), **Howard Enos**
(tech, full trust — same access). Commits use local git config (per-person authorship);
the Gitea push account is shared. Every session log needs a `## User` block (use
`.claude/scripts/whoami-block.sh`).

## How you work — act directly, delegate deliberately
You are the main operator. **ACT DIRECTLY by default.** Delegate to a sub-agent ONLY when:
(a) the task produces high-volume tool output, (b) blast radius >3 files across layers,
(c) a genuine domain shift needs a specialized agent, or (d) independent work can run in
parallel. Do NOT delegate one-shot work (a single API call, a ticket comment, a 1–2 file
edit, an immediate answer) — each agent boundary is a cache miss + handoff + repo reload
that hurts accuracy and context. For a coupled explore→implement→review on one context,
use ONE agent across all phases. Agent defs: `.claude/agents/`.

## Model routing
Tier 0 Ollama (low-stakes prose/classify, output reviewed) · Tier 1 `haiku` · Tier 2
inherit (most code/db/test/git) · Tier 3 `opus` (architecture, security, ambiguous
failures, production risk). Bump one tier for: security, auth, credential, migration,
production, data-loss. Detail: EXTENDED + `.claude/OLLAMA.md`.

## Key rules (always)
- **Simplest solution FIRST.** Start with the least complex thing that could answer the
  problem, confirm it works, and only THEN graduate to more advanced/complicated approaches
  as the simple one proves insufficient. Don't reach for SSH/plink/multi-hop tooling when a
  one-shot query (a single DNS lookup, one API call, one command) would answer it. E.g. "what
  IP does the UDM think X is?" = `nslookup X <udm-ip>`, not shelling into the device. Escalate
  deliberately, not by default.
- **NO EMOJIS.** Use ASCII markers: `[OK]` `[ERROR]` `[WARNING]` `[INFO]` `[CRITICAL]`.
- **Skill-first — if a skill/command covers the task, USE IT; never hand-roll the API.**
  When a request maps to an installed skill or slash-command, INVOKE THAT SKILL instead of
  improvising raw `curl`/API calls from memory. The skill encodes the correct payload shape,
  validation, attribution, and preview gates; free-handing the API is exactly how malformed
  records (e.g. Syncro tickets/invoices) reach a human for cleanup. **Syncro billing/invoicing
  ALWAYS runs through `/syncro` (or `/syncro-emergency-billing`) — no exceptions.** Same for
  other covered domains: credentials → `vault`, RMM actions → `/rmm` (+ `rmm-search` to find a
  host), M365 → `remediation-tool`, asking a human a question/decision in Discord (get their
  reply back in-session) → `ask-forum` (never hand-roll the Discord API — that footgun cost us
  a broken background wait), bugs/features/projects → `bug-tracker`, etc. Knowing the API is NOT a reason to bypass the skill —
  the memory rules (e.g. [[feedback_syncro_billing]]) describe what the SKILL does, not a license
  to free-hand it. Reach for raw API ONLY when no skill fits or the skill genuinely cannot do it
  — and say so explicitly when you do. Mistakes here go to `errorlog.md` (`--correction`).
- **Definition of Done — route the REQUEST to a doing-skill, then GATE the result with the
  matching check-skill(s) before calling work done — automatically, without being asked.**
  You map the request to skills from the conversation + expected end result; the user should not
  have to name skill A/B/C. Standing gates (run the check-skill BEFORE declaring done): code edits
  → `/code-review` + `/simplify` (+ `/security-review` if it touches auth/creds/security); anything
  outbound/client-facing → `impeccable` / `stop-slop`; Syncro/vendor work → its skill's own
  preview+verify gate; bug reports → confirm title/priority with user before filing via `bug-tracker`;
  wiki/memory writes → their lint (`wiki-lint`/`memory-dream`). **Calibrate to
  stakes** (a typo fix doesn't need a full review) and **use Ollama Tier-0** for the cheap
  classify/prose passes so this stays low-token. The full request→doing-skill→check-skill map is
  `.claude/SKILL_ROUTING.md` — read it on demand when a request maps to a skill or work nears done.
- **Credentials — capture, vault, document (ALWAYS).** ANY credential that surfaces in a
  session — one the user pastes, one you create/rotate, one you discover in a log/config — you
  MUST immediately store it in the SOPS vault **via the `vault` skill** (the canonical path —
  this is why the vault exists; do not improvise raw `sops`/`vault.sh`) AND document it
  thoroughly in the entry: what it is, what it's for, and exactly how it's used (auth method,
  endpoint, gotchas). Read with the skill too; `vault.sh get-field <path> <field>` is the
  underlying read (1Password fallback). Never commit plaintext secrets (pre-commit
  `harness-guard.sh` warns). Losing/forgetting infra credentials wastes real time — capturing
  them is not optional.
- **SSH:** system OpenSSH (`C:\Windows\System32\OpenSSH\ssh.exe`), never Git-for-Windows SSH.
- **Data integrity:** never placeholder/fake data — check vault, wiki, or ask.
- **Hard-to-reverse or outward-facing actions:** confirm first (per-action, per-session).
- **Error logging (mandatory, all skills):** when a task or skill hits a GENUINE functional error during execution (failed command, API/auth failure, unexpected API response, tool call), record it to `errorlog.md` (repo root) via the canonical helper — never hand-format: `bash .claude/scripts/log-skill-error.sh "<skill/command>" "<brief error>" [--context "k=v ..."]`. It stamps UTC date + machine (from `identity.json`) and inserts in the standard `YYYY-MM-DD | MACHINE | skill | error` format (newest on top) for later skill **linting**, and soft-fails so it never breaks the caller. **Every skill MUST call it at its failure branches**; you (main loop) call it after any skill/command genuinely fails. Do NOT log expected/handled conditions (no search matches, no unread messages, a user declining a prompt) — only real failures worth spotting a pattern. Python skills shell out to the same helper.
- **Log user corrections too (`--correction`):** when the user CORRECTS an improper assumption or wrong approach you took (e.g. "don't use INKY unless onboarded", "EXO already has Mail.Send", "I don't need an exact match"), log it: `bash .claude/scripts/log-skill-error.sh "<skill/context>" "assumed X; correct is Y" --correction`. These are the highest-value entries — they surface recurring bad assumptions so we can train them out of the system. If the correction is a durable preference, ALSO save it as a `feedback` memory (the two are complementary: memory fixes future behavior, errorlog tracks the pattern for linting).
- **Bug tracker (errorlog → tracker bridge):** when logging a GENUINE functional bug to
  errorlog.md (not `--correction`/`--friction`), also evaluate whether it needs follow-up
  tracking. If the bug is reproducible, affects a skill/tool/harness component, and won't be
  fixed in this session → file it as a Gitea issue via the `bug-tracker` skill (confirm
  title/priority with the user). The errorlog captures patterns for linting; the tracker
  tracks resolution. **When starting work on a bug/feature/skill task, check the tracker
  for a matching issue first** — this is the step that connects the fix to the close.
  When fixing a tracked bug, update/close the issue with a commit ref comment — never
  close silently. See `SKILL_ROUTING.md` "Bug tracking" block.
- **Log preventable friction too (`--friction`):** any time you waste tokens on a preventable, repeatable self-inflicted error — harness/env/tool misuse (Git-Bash `/tmp` path mismatch, shell env not persisting between Bash calls, passing huge args on the command line, PowerShell var case-collisions, etc.) — log it: `bash .claude/scripts/log-skill-error.sh "<context e.g. bash/env>" "what wasted tokens + the fix" --friction [--context "ref=<memory-or-rule>"]`. **If it repeats something already in memory or CLAUDE.md, that's the highest-value entry** — it means a rule/memory isn't working; cite the ref. This log is the corpus we lint to build better CLAUDE.md rules and to clean stale/misleading memory. Goal: stop paying twice for the same mistake.
- **Windows:** ensure `bash` resolves to Git-for-Windows MSYS bash, not the WSL stub; write
  `.claude/current-mode` with a relative/forward-slash path only (never a backslash Windows
  path). **Never write API/scratch JSON to `/tmp`** — Git-Bash `/tmp` and the Write/Python tools
  resolve it to different places (read-back fails); use a repo-relative path (`./.x.json`). **Never
  embed `"` in `curl.exe`/`plink` args from PowerShell** — `CommandLineToArgvW` strips them and
  silently mangles the payload; single-quote bodies, build `$` from `[char]36`, or use SSH key auth.
  These two recur fleet-wide (errorlog) — treat as hard rules. Detail + fixes: EXTENDED,
  memories `feedback_tmp_path_windows` + `feedback_windows_quote_stripping`.

## Coordination (live source of truth)
The coord API (`http://172.16.3.30:8001/api/coord`, no auth) holds live locks, messages,
todos, component state. **If a `system-reminder` contains "UNREAD COORD MESSAGES", you MUST
reproduce the full message block verbatim at the top of your response before anything else**
— the user cannot see system-reminders. Session-start checks, locks, inter-session
messaging, todos, softfail queue: EXTENDED (and the `coord` skill).

## Context loading (don't ask for what's recorded)
Before responding, load context when a trigger fires — a client/project/system/server is
named, or the user says continue/resume/back-to/finish: read **`wiki/`** FIRST (synthesized
knowledge; index `wiki/index.md`), then the relevant `CONTEXT.md` / session logs, then the
coord API. Never ask for infra or recent-work facts that live in the wiki or `CONTEXT.md`.
Full trigger table + recovery: EXTENDED; the `/context` command.

## Work modes
Auto-detect mode (remediation / client / infra / dev / general) from each message. On
change: announce `[MODE -> x]`, tell the user to run `/color <c>`, and write the mode to
`.claude/current-mode`. Mode postures + triggers: EXTENDED.

## Memory & knowledge layers
Shared memory in `.claude/memory/` (index `MEMORY.md`, loaded each session) — write here
(repo-relative), NEVER `~/.claude/projects/*/memory/`. Wiki = synthesized truth (on-demand);
session-logs = archive; memory = small ephemeral facts + harness quirks. Save user
facts/feedback/project/reference per the memory format; one fact per file + an index line.

## RMM Thoughts
GuruRMM ideas from Mike/Howard go to `projects/msp-tools/guru-rmm/docs/RMM_THOUGHTS.md`
(Status: Raw) → discuss → `/shape-spec` → roadmap → build. Don't build until an explicit go.
`/feature-request` captures Howard's requests there.

---
Projects, commands table, file-placement guide, full coord protocol, onboarding, Ollama,
GrepAI, and every detailed workflow: **`.claude/CLAUDE_EXTENDED.md`**.
