~/.claude/CLAUDE.md
188 lines — Language Rule deleted (M591)


Git Init Rule (M387)


Every project directory tracked by the NS hub **must be git initialized** (`git init`).

When Claude works in an exec session (claude-exec-{proj}):

  • If the project dir is NOT git initialized → run `git init` first before any file changes.
  • After implementing a milestone, make an atomic commit: `git add -A && git commit -m "feat: "`.
  • Commits are how the work persists and can be reviewed/rolled back. No commit = work is untracked.

  • New project dirs added to `proj_dirs` in `server.py` must also have `git init` run.


    E2E Completion Screenshot Rule

    **Completion screenshots MUST be real UI screenshots** (browser showing the working feature), NOT code snippet captures or terminal output. For backend-only changes (edge functions, API fixes), show the UI where the feature is triggered successfully.


    "Prove with img" Rule (M295)

    When user says "prove with img", "share the shot", "completion shot", or similar: take a Playwright screenshot of the relevant working UI, upload to `gdrive:claude-shared/Moat/outbox/`, and share the GDrive link.


    Screenshot Path Rule (M357)

    **NEVER use relative filenames for Playwright screenshots** — always use absolute paths under the project root:

    `filename="/.playwright-mcp/screenshot-name.png"`

    Relative paths save to session CWD and clutter home dir.



    Service Binding Rule: dev servers may bind to `0.0.0.0` for local LAN/Tailscale access. Use `127.0.0.1` for strictly local-only services.


    Google Drive Share Protocol


    **Rule**: Always upload to `gdrive:claude-shared//outbox/`. Never use the top-level `claude-shared/outbox/`.


    **Upload command**:

    rclone copy <local-file> "gdrive:claude-shared/<project>/outbox/"
    rclone link "gdrive:claude-shared/<project>/outbox/<filename>"

    **If project folder missing**: `rclone mkdir "gdrive:claude-shared//inbox" && rclone mkdir "gdrive:claude-shared//outbox"`


    **[DEFAULT] Hub doc sharing — always docx table**: When sharing any document result from a hub stone (research, guide, comparison, analysis, screenshot summary, etc.), default format is **python-docx with styled tables** — even without explicit "docx" request. Styled table spec: header row dark bg (#1F2937) white text, alternating row shading (#F3F4F6 / white), `Table Grid` style. Upload via rclone to outbox, share link in stone comment.


    **Inbox usage** (read from user): `gdrive:claude-shared//inbox/` — user places files here for Claude to read.

    Read with: `rclone ls "gdrive:claude-shared//inbox/"` then `rclone copy /tmp/` to download.

    On "make into docx" / "표/테이블 docx로" / any tabular-output request: emit **HTML with styled tables** (borders, header bg, alternating row shading, priority highlights) — never markdown pipe-tables. Upload as `text/html` so Drive preview shows real tables.



    Private Keys / Token


    Full inventory and quick-reference scripts: `~/.claude/env/README.md`

    Usage: `source ~/.claude/env/shared.env && `


    Tailscale Host Registry


    IPs and hostnames are dynamic — always query at runtime:


    tailscale status --json | python3 -m json.tool | grep -E "HostName|TailscaleIPs|OS"


    Remote Notify Client Registry (Tailscale)


    Full reference: `~/.claude/tool-hints/tailscale-notify.md`

    Bootstrap: `irm http://:9955/bootstrap | iex` (admin PS + Tailscale). All clients port 6789. Use `wsl-expose ` / `wsl-unexpose ` for dev-server mirroring.


    G1/G2/CM Hook Display Rule


    When `additionalContext` contains G1/G2/CM headers: output the `> **XX**` header lines verbatim as the first lines of the response (before any other content), then skip if none present.


    Memory Persistence — Immediate Write Rule


    **MANDATORY**: When **[MEMORY TRIGGER]** appears in context, immediately Edit the MEMORY.md file shown in the trigger and add the decision in the SAME response turn — do NOT defer to session end.


    Also write immediately on: person/project status changes, kills/pauses, finalized decisions, or explicit "기억해"/"저장해".


    MEMORY.md path: `~/.claude/projects/{cwd-with-slashes-as-dashes}/memory/MEMORY.md`




    Skill & Agent Files


  • ✅ Write in **English** (name, description, prompts) — Korean frontmatter causes silent load failures
  • ✅ Structure: `~/.claude/skills//SKILL.md` (directory, not a flat `.md` file)
  • Frontmatter: `name` + `description` only (no `type: skill`)


  • Login Priority


    When an external site (Zoom, Notion, Figma, etc.) presents multiple SSO options, prefer **Google SSO with `be2jay67@gmail.com`** — this is the user's primary account and has the highest chance of being already authenticated.




    Prohibited Patterns


    Never do the following under any circumstances:


    1. ❌ **`npm run build` while dev server is running** — use `npx tsc --noEmit` for type-check only; deploy via `vercel --prod` directly

    2. ❌ **Killing Node.js processes without authorization** (`taskkill /IM node.exe`, `pkill node`, etc.)

    - Never kill `node.exe` processes without user approval

    - On port conflict: use different port or inform user instead of killing


    3. ❌ **Running git commit without authorization** — only run when user explicitly says "commit"


    4. ❌ **Running git checkout/restore without authorization** (reverting file changes)

    - Must confirm before `git checkout ` or `git restore ` — uncommitted changes will be lost

    - `git checkout -b` (branch creation) is exempt


    5. ❌ **Korean/multibyte filenames** — minimize Korean in filenames/branch names (prefer ASCII). Use `--name-only` for git output parsing.


    6. ❌ **Tool output truncation** — for Korean content, set generous `head_limit`; process line by line if needed.


    7. ❌ **Killing the hub server process directly** (`pkill uvicorn`, `kill -9 `, `lsof -ti:9000 | xargs kill`, etc.)

    - The hub at port 9000 is managed by systemd and is the exec session's own communication channel.

    - To restart hub after code changes: `POST http://:9000/api/hub/restart`

    - Direct kill disconnects the exec session from the hub — losing task context.



    Document Location Rules


  • ❌ No `.md` files in root (except `README.md`, `CONTRIBUTING.md`)
  • ❌ No docs in `src/`, `scripts/`, `tests/` code folders
  • ✅ Always save under `docs//`
  • ✅ After moving files: run `index_directory(project_path, incremental=True)`
  • ✅ **[Required] Update `docs/DOC_INDEX.md` on every doc create/move/delete**
  • (PostToolUse hook enforces this)




    External Services Safety


    **Never mix up projects in a multi-project environment.** Always verify `.env.local` matches the target project before any connection.


    **Past incident**: "table not found" → was connected to wrong Supabase project.

    Full checklists (Supabase / Vercel / Railway): `~/.claude/tool-hints/external-services.md`


    **Supabase Edge Functions errors**: Always check logs directly at [Supabase Dashboard → Edge Functions → Logs](https://supabase.com/dashboard/project/_/functions) before guessing the cause.



    Browser RPA & Playwright Rules


    When browser work gets stuck or needs verification — use Playwright instead of guessing.


    **Tool priority:** `mcp__playwright-session-*` → `playwright` CLI (`~/.local/bin/playwright`, always available)


    **Session vs Remote:** Use `mcp__playwright-session-*` for non-interactive checks (snapshots, scraping, URL verification). Use `mcp__playwright-mcp-remote__*` only when user interaction is needed (login, file upload, clicking visible UI) — remote shows in noVNC so user can watch/intervene.


    **Session rules:** Check `browser_tabs` first (session-1→2→3→4), use `about:blank` = idle session. **If session-N fails or is busy (non-blank tabs, tool error), immediately try session-(N+1) — exhaust all 4 before giving up.** ❌ Never create new sessions without authorization. ❌ Never auto-proceed on login required — stop and ask.


    **Selector strategy (MANDATORY):** `getByRole` / `getByLabel` / `getByText` / `getByPlaceholder` — ❌ no CSS/ID selectors.


    **Smoke test:** `node ~/.claude/snippets/pw-smoke.js` (template: `~/.claude/snippets/pw-smoke.js`)




    Tool Substitution for Non-Anthropic Models

  • When using non-Anthropic models (MiniMax, Gemini, Qwen, GLM, etc.), replace websearch tools with `mcp__websearch__search_web` and `mcp__websearch__fetch_url`.

  • Dev Server Restart

    On port conflict: kill process (`lsof -ti: | xargs kill`) → delete `.next` → restart

    **Note**: If the process is Node.js-based (Next.js, etc.), confirm with user first (Prohibited Patterns #7). For non-Node servers (Python, Go, etc.): kill without confirmation.





    UI Design Rules


    No AI Model Names in UI

  • ❌ **Never expose AI model names in UI code** (Gemini, Claude, GPT, Flash, Sonnet, etc.)
  • Use generic terms like "AI", "AI Analysis" instead
  • Scope: all user-visible text in `.tsx`, `.jsx`, `.html` files
  • Exception: admin-only internal pages, dev tools, server logs

  • No Emojis in UI Code

  • ❌ **Never use emojis in TSX/HTML UI code** (text labels, buttons, headers, icons, etc.)
  • Use text, SVG icons, or Unicode symbols (←, →, ↑, ↓, ✓) instead
  • Scope: strings inside JSX/HTML elements in `.tsx`, `.jsx`, `.html` files
  • Exception: only when explicitly requested by user

  • NS Hub Protocol (auto-injected by hub install-global)

    Stone lifecycle: queued → pending_confirmation → done.

    COMPLETION PROTOCOL: PATCH status=pending_confirmation + append_message.role=claude + star_relation + exec_start + exec_end + model_used (all in one PATCH).

    COMMENT RULE: append_message ≤3 lines. Longer detail → docs/ns-replies/-.md then reference link in comment.

    PARALLEL DISPATCH: 2+ independent queued stones → emit multiple Agent calls in ONE message.

    NO-OP PROTOCOL: if skipping a stone, post 1-line reason via append_message. Silent skip forbidden.

    TOKEN DISCIPLINE: after completion post ONLY the 1-line summary. No follow-up questions.