{"owner":"jason5ng32","repo":"MyIP","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md","AGENTS.md"],"skills":{"CLAUDE.md":"# CLAUDE.md\n\nAuthoritative project instructions: @AGENTS.md\n\nClaude-specific additions below; on conflict, AGENTS.md wins.\n\n## Claude-specific\n\nNone at the moment. This file exists so Claude Code auto-loads AGENTS.md at\nsession start; additional Claude-only guidance goes here if it ever diverges\nfrom what all contributors should follow.\n","AGENTS.md":"# AGENTS.md\n\nSingle source of truth for anyone — human or AI — contributing to MyIP.\nArea-specific details: @frontend/AGENTS.md (Vue SPA) · @api/AGENTS.md (Express API).\n\n## Overview\n\n**MyIP** (IPCheck.ing) is an open-source IP toolbox: IP lookup, connectivity\ntests, WebRTC / DNS-leak detection, speed test, MTR, Whois, security\nchecklist, browser fingerprint, anonymity checks, and more. Single repo, two\nhalves: a Vue 3 SPA front-end and an Express 5 back-end API.\n\n## Stack\n\n| Layer | Technology |\n|---|---|\n| Frontend | Vue 3 (`<script setup>`) · Pinia · vue-router (HTML5 history) · vue-i18n (`en`/`zh`/`fr`/`ru`) |\n| Build | Vite + `@vitejs/plugin-vue`; Tailwind CSS v4 + `tw-animate-css` |\n| UI | shadcn-vue copy-in primitives (reka-ui) · lucide icons · circle-flags via `@iconify/vue` · vaul-vue drawer · vue-sonner toast |\n| Backend | Express 5 |\n| Logger | `pino` singleton at `common/logger.js` (+ `pino-http`, opt-in) |\n| Auth | Firebase Auth (optional, env-gated) |\n| Error monitoring | Sentry — optional & env-gated on both halves: `@sentry/vue` (no `VITE_SENTRY_DSN_FRONTEND`, no Sentry in the build — see frontend/AGENTS.md) + `@sentry/node` (no `SENTRY_DSN_BACKEND`, never loaded — see api/AGENTS.md) |\n| PWA | `manifest.webmanifest` only — installable but online-only, no service worker |\n| Tests | Node built-in test runner (`node --test`) |\n| Runtime libs | chart.js · chartjs-chart-geo · @cloudflare/speedtest · maxmind · whoiser · thumbmarkjs · ua-parser-js · detect-gpu · @vueuse/core |\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `pnpm dev` | Vite + backend (nodemon) together |\n| `pnpm build` | Front-end production build |\n| `pnpm preview` | Vite preview of the build output |\n| `pnpm start` | Built front-end + backend |\n| `pnpm test` | Run all `tests/*.test.js` specs |\n| `pnpm check` | `test` + `build` — the pre-commit self-check |\n\n**pnpm only** (pinned via `packageManager`); `pnpm-lock.yaml` is committed and\n`pnpm-workspace.yaml` holds the `allowBuilds` install-script approvals. Never\nuse npm / yarn — they'd produce a competing lockfile.\n\n## Project layout\n\n```\n.\n├── AGENTS.md / CLAUDE.md        ← this file + Claude pointer to it\n├── frontend/                    ← Vue 3 SPA (see frontend/AGENTS.md)\n├── api/                         ← Express handlers (see api/AGENTS.md)\n├── common/                      ← code shared by both halves (valid-ip /\n│                                  fetch-with-timeout / guards / logger / …)\n├── tests/                       ← Node test runner specs\n├── backend-server.js            ← Express app (default port 11966)\n├── sentry-instrument.js         ← backend Sentry bootstrap via `node --import`;\n│                                  no-op without SENTRY_DSN_BACKEND\n├── frontend-server.js           ← static server for `pnpm start` (+ SPA fallback)\n├── ecosystem.config.cjs         ← pm2 definitions (carries the `--import` flag)\n├── index.html                   ← Vite entry\n├── vite.config.js / jsconfig.json (alias @ → frontend/) / package.json\n```\n\n## Conventions\n\n### Language\n\n- **JavaScript only.** New files are `.js` / `.vue`; no `lang=\"ts\"`, no\n  TypeScript migration.\n- **English by default** for code comments, commit messages, and AGENTS.md.\n  Locale packs obviously carry their own language; planning docs are free.\n\n### Functions\n\n- **New functions use `const` arrow syntax** (`const fn = async () => {}`),\n  not `function` declarations. Object methods keep shorthand. Arrow consts\n  aren't hoisted — declare before use. Applies to new / rewritten code only;\n  don't mass-convert existing declarations.\n\n### Comments\n\n- **Every new file opens with a header comment** stating its purpose.\n- **Large templates / functions carry block comments** per meaningful region.\n- **Comments describe the code as it is now** — no changelog narration\n  (`previously…`, `…fixes that`); git history covers the past. A comment\n  stays shorter than the code it explains.\n\n### i18n coverage\n\n- Copy-surfacing features land in **all four locales** in the same change —\n  including `frontend/data/changelog.json` entries\n  (`tests/changelog.test.js` enforces it).\n\n### Logging (backend)\n\n- **Always the shared logger** (`common/logger.js`) in backend files; bare\n  `console.*` is banned there (frontend keeps using `console.*`).\n- Pino first-arg-is-context: `logger.error({ err, ip }, 'short message')`.\n- Env knobs: `LOG_LEVEL` (default info), `LOG_FORMAT=json` for shippers,\n  `LOG_HTTP=true` to mount `pino-http` on `/api` (off by default; handlers\n  never log \"received request\" lines themselves). No `NODE_ENV` anywhere.\n- Startup-only lines lead with an emoji (🚀 listening · 📦 ready ·\n  📥 downloading · 🛡️ security · 🐢 throttling · 🗓️ schedule · ⚠️ recoverable\n  · ❌ failure); per-request logs stay plain.\n\n## Testing\n\n- Any non-visual logic exercisable without a network call — pure functions,\n  composables with mockable inputs, transforms, validators — ships with a\n  spec in `tests/`, in the same change (don't defer; update affected tests\n  when behavior shifts).\n- UI rendering, real network behavior, and browser APIs are out of scope.\n- **`pnpm check` must be green before handing off.**\n\n## Security & Boundaries\n\nAccess control and timeouts live in shared middleware, not handlers\n(details in @api/AGENTS.md):\n\n- `requireReferer` is global on `/api/*`; `requirePublicIP()` per-route —\n  handlers never repeat these checks.\n- Every upstream HTTP call goes through `fetchUpstream`\n  (`common/fetch-with-timeout.js`, 8s timeout). Never a bare `fetch()` in `api/`.\n\n## Workflow\n\n- **Branch discipline — `dev` in, `dev` out.** `main` only moves via\n  dev → main PRs. From a worktree, fast-forward dev with `git push . HEAD:dev`\n  (repo has `receive.denyCurrentBranch=updateInstead`), not `git update-ref`.\n- **No commits without explicit user approval** — AI edits → user reviews →\n  user tests → user says \"commit\". Even with tests green, visual changes need\n  user eyes before landing.\n- **One concern per commit**, message style per `git log`\n  (`Feat(xxx):` / `Fix(ui):` / `Refactor(xxx):` / `Style:` / `Chore:`),\n  AI adds itself as co-author.\n- **Self-test before handing off** (`pnpm check`); if a change is visual and\n  headless-unverifiable, say so explicitly.\n- **On every commit, scan AGENTS.md (root + relevant sub-file) for\n  staleness** — conventions, renames, flipped rules, dead examples get fixed\n  in the same commit. Doc drift is this file's main failure mode.\n\n---\n\nIf [local-context.md](./local-context.md) exists in the workspace root, read\nit too — it lists machine-local Knowledge Hub paths (not in git).\n"},"files":{"CLAUDE.md":"# CLAUDE.md\n\nAuthoritative project instructions: @AGENTS.md\n\nClaude-specific additions below; on conflict, AGENTS.md wins.\n\n## Claude-specific\n\nNone at the moment. This file exists so Claude Code auto-loads AGENTS.md at\nsession start; additional Claude-only guidance goes here if it ever diverges\nfrom what all contributors should follow.\n","AGENTS.md":"# AGENTS.md\n\nSingle source of truth for anyone — human or AI — contributing to MyIP.\nArea-specific details: @frontend/AGENTS.md (Vue SPA) · @api/AGENTS.md (Express API).\n\n## Overview\n\n**MyIP** (IPCheck.ing) is an open-source IP toolbox: IP lookup, connectivity\ntests, WebRTC / DNS-leak detection, speed test, MTR, Whois, security\nchecklist, browser fingerprint, anonymity checks, and more. Single repo, two\nhalves: a Vue 3 SPA front-end and an Express 5 back-end API.\n\n## Stack\n\n| Layer | Technology |\n|---|---|\n| Frontend | Vue 3 (`<script setup>`) · Pinia · vue-router (HTML5 history) · vue-i18n (`en`/`zh`/`fr`/`ru`) |\n| Build | Vite + `@vitejs/plugin-vue`; Tailwind CSS v4 + `tw-animate-css` |\n| UI | shadcn-vue copy-in primitives (reka-ui) · lucide icons · circle-flags via `@iconify/vue` · vaul-vue drawer · vue-sonner toast |\n| Backend | Express 5 |\n| Logger | `pino` singleton at `common/logger.js` (+ `pino-http`, opt-in) |\n| Auth | Firebase Auth (optional, env-gated) |\n| Error monitoring | Sentry — optional & env-gated on both halves: `@sentry/vue` (no `VITE_SENTRY_DSN_FRONTEND`, no Sentry in the build — see frontend/AGENTS.md) + `@sentry/node` (no `SENTRY_DSN_BACKEND`, never loaded — see api/AGENTS.md) |\n| PWA | `manifest.webmanifest` only — installable but online-only, no service worker |\n| Tests | Node built-in test runner (`node --test`) |\n| Runtime libs | chart.js · chartjs-chart-geo · @cloudflare/speedtest · maxmind · whoiser · thumbmarkjs · ua-parser-js · detect-gpu · @vueuse/core |\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `pnpm dev` | Vite + backend (nodemon) together |\n| `pnpm build` | Front-end production build |\n| `pnpm preview` | Vite preview of the build output |\n| `pnpm start` | Built front-end + backend |\n| `pnpm test` | Run all `tests/*.test.js` specs |\n| `pnpm check` | `test` + `build` — the pre-commit self-check |\n\n**pnpm only** (pinned via `packageManager`); `pnpm-lock.yaml` is committed and\n`pnpm-workspace.yaml` holds the `allowBuilds` install-script approvals. Never\nuse npm / yarn — they'd produce a competing lockfile.\n\n## Project layout\n\n```\n.\n├── AGENTS.md / CLAUDE.md        ← this file + Claude pointer to it\n├── frontend/                    ← Vue 3 SPA (see frontend/AGENTS.md)\n├── api/                         ← Express handlers (see api/AGENTS.md)\n├── common/                      ← code shared by both halves (valid-ip /\n│                                  fetch-with-timeout / guards / logger / …)\n├── tests/                       ← Node test runner specs\n├── backend-server.js            ← Express app (default port 11966)\n├── sentry-instrument.js         ← backend Sentry bootstrap via `node --import`;\n│                                  no-op without SENTRY_DSN_BACKEND\n├── frontend-server.js           ← static server for `pnpm start` (+ SPA fallback)\n├── ecosystem.config.cjs         ← pm2 definitions (carries the `--import` flag)\n├── index.html                   ← Vite entry\n├── vite.config.js / jsconfig.json (alias @ → frontend/) / package.json\n```\n\n## Conventions\n\n### Language\n\n- **JavaScript only.** New files are `.js` / `.vue`; no `lang=\"ts\"`, no\n  TypeScript migration.\n- **English by default** for code comments, commit messages, and AGENTS.md.\n  Locale packs obviously carry their own language; planning docs are free.\n\n### Functions\n\n- **New functions use `const` arrow syntax** (`const fn = async () => {}`),\n  not `function` declarations. Object methods keep shorthand. Arrow consts\n  aren't hoisted — declare before use. Applies to new / rewritten code only;\n  don't mass-convert existing declarations.\n\n### Comments\n\n- **Every new file opens with a header comment** stating its purpose.\n- **Large templates / functions carry block comments** per meaningful region.\n- **Comments describe the code as it is now** — no changelog narration\n  (`previously…`, `…fixes that`); git history covers the past. A comment\n  stays shorter than the code it explains.\n\n### i18n coverage\n\n- Copy-surfacing features land in **all four locales** in the same change —\n  including `frontend/data/changelog.json` entries\n  (`tests/changelog.test.js` enforces it).\n\n### Logging (backend)\n\n- **Always the shared logger** (`common/logger.js`) in backend files; bare\n  `console.*` is banned there (frontend keeps using `console.*`).\n- Pino first-arg-is-context: `logger.error({ err, ip }, 'short message')`.\n- Env knobs: `LOG_LEVEL` (default info), `LOG_FORMAT=json` for shippers,\n  `LOG_HTTP=true` to mount `pino-http` on `/api` (off by default; handlers\n  never log \"received request\" lines themselves). No `NODE_ENV` anywhere.\n- Startup-only lines lead with an emoji (🚀 listening · 📦 ready ·\n  📥 downloading · 🛡️ security · 🐢 throttling · 🗓️ schedule · ⚠️ recoverable\n  · ❌ failure); per-request logs stay plain.\n\n## Testing\n\n- Any non-visual logic exercisable without a network call — pure functions,\n  composables with mockable inputs, transforms, validators — ships with a\n  spec in `tests/`, in the same change (don't defer; update affected tests\n  when behavior shifts).\n- UI rendering, real network behavior, and browser APIs are out of scope.\n- **`pnpm check` must be green before handing off.**\n\n## Security & Boundaries\n\nAccess control and timeouts live in shared middleware, not handlers\n(details in @api/AGENTS.md):\n\n- `requireReferer` is global on `/api/*`; `requirePublicIP()` per-route —\n  handlers never repeat these checks.\n- Every upstream HTTP call goes through `fetchUpstream`\n  (`common/fetch-with-timeout.js`, 8s timeout). Never a bare `fetch()` in `api/`.\n\n## Workflow\n\n- **Branch discipline — `dev` in, `dev` out.** `main` only moves via\n  dev → main PRs. From a worktree, fast-forward dev with `git push . HEAD:dev`\n  (repo has `receive.denyCurrentBranch=updateInstead`), not `git update-ref`.\n- **No commits without explicit user approval** — AI edits → user reviews →\n  user tests → user says \"commit\". Even with tests green, visual changes need\n  user eyes before landing.\n- **One concern per commit**, message style per `git log`\n  (`Feat(xxx):` / `Fix(ui):` / `Refactor(xxx):` / `Style:` / `Chore:`),\n  AI adds itself as co-author.\n- **Self-test before handing off** (`pnpm check`); if a change is visual and\n  headless-unverifiable, say so explicitly.\n- **On every commit, scan AGENTS.md (root + relevant sub-file) for\n  staleness** — conventions, renames, flipped rules, dead examples get fixed\n  in the same commit. Doc drift is this file's main failure mode.\n\n---\n\nIf [local-context.md](./local-context.md) exists in the workspace root, read\nit too — it lists machine-local Knowledge Hub paths (not in git).\n"},"items":[{"name":"CLAUDE.md","path":"CLAUDE.md","title":"CLAUDE.md","content":"# CLAUDE.md\n\nAuthoritative project instructions: @AGENTS.md\n\nClaude-specific additions below; on conflict, AGENTS.md wins.\n\n## Claude-specific\n\nNone at the moment. This file exists so Claude Code auto-loads AGENTS.md at\nsession start; additional Claude-only guidance goes here if it ever diverges\nfrom what all contributors should follow.\n","category":"root","tokens":85},{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\nSingle source of truth for anyone — human or AI — contributing to MyIP.\nArea-specific details: @frontend/AGENTS.md (Vue SPA) · @api/AGENTS.md (Express API).\n\n## Overview\n\n**MyIP** (IPCheck.ing) is an open-source IP toolbox: IP lookup, connectivity\ntests, WebRTC / DNS-leak detection, speed test, MTR, Whois, security\nchecklist, browser fingerprint, anonymity checks, and more. Single repo, two\nhalves: a Vue 3 SPA front-end and an Express 5 back-end API.\n\n## Stack\n\n| Layer | Technology |\n|---|---|\n| Frontend | Vue 3 (`<script setup>`) · Pinia · vue-router (HTML5 history) · vue-i18n (`en`/`zh`/`fr`/`ru`) |\n| Build | Vite + `@vitejs/plugin-vue`; Tailwind CSS v4 + `tw-animate-css` |\n| UI | shadcn-vue copy-in primitives (reka-ui) · lucide icons · circle-flags via `@iconify/vue` · vaul-vue drawer · vue-sonner toast |\n| Backend | Express 5 |\n| Logger | `pino` singleton at `common/logger.js` (+ `pino-http`, opt-in) |\n| Auth | Firebase Auth (optional, env-gated) |\n| Error monitoring | Sentry — optional & env-gated on both halves: `@sentry/vue` (no `VITE_SENTRY_DSN_FRONTEND`, no Sentry in the build — see frontend/AGENTS.md) + `@sentry/node` (no `SENTRY_DSN_BACKEND`, never loaded — see api/AGENTS.md) |\n| PWA | `manifest.webmanifest` only — installable but online-only, no service worker |\n| Tests | Node built-in test runner (`node --test`) |\n| Runtime libs | chart.js · chartjs-chart-geo · @cloudflare/speedtest · maxmind · whoiser · thumbmarkjs · ua-parser-js · detect-gpu · @vueuse/core |\n\n## Commands\n\n| Command | What it does |\n|---|---|\n| `pnpm dev` | Vite + backend (nodemon) together |\n| `pnpm build` | Front-end production build |\n| `pnpm preview` | Vite preview of the build output |\n| `pnpm start` | Built front-end + backend |\n| `pnpm test` | Run all `tests/*.test.js` specs |\n| `pnpm check` | `test` + `build` — the pre-commit self-check |\n\n**pnpm only** (pinned via `packageManager`); `pnpm-lock.yaml` is committed and\n`pnpm-workspace.yaml` holds the `allowBuilds` install-script approvals. Never\nuse npm / yarn — they'd produce a competing lockfile.\n\n## Project layout\n\n```\n.\n├── AGENTS.md / CLAUDE.md        ← this file + Claude pointer to it\n├── frontend/                    ← Vue 3 SPA (see frontend/AGENTS.md)\n├── api/                         ← Express handlers (see api/AGENTS.md)\n├── common/                      ← code shared by both halves (valid-ip /\n│                                  fetch-with-timeout / guards / logger / …)\n├── tests/                       ← Node test runner specs\n├── backend-server.js            ← Express app (default port 11966)\n├── sentry-instrument.js         ← backend Sentry bootstrap via `node --import`;\n│                                  no-op without SENTRY_DSN_BACKEND\n├── frontend-server.js           ← static server for `pnpm start` (+ SPA fallback)\n├── ecosystem.config.cjs         ← pm2 definitions (carries the `--import` flag)\n├── index.html                   ← Vite entry\n├── vite.config.js / jsconfig.json (alias @ → frontend/) / package.json\n```\n\n## Conventions\n\n### Language\n\n- **JavaScript only.** New files are `.js` / `.vue`; no `lang=\"ts\"`, no\n  TypeScript migration.\n- **English by default** for code comments, commit messages, and AGENTS.md.\n  Locale packs obviously carry their own language; planning docs are free.\n\n### Functions\n\n- **New functions use `const` arrow syntax** (`const fn = async () => {}`),\n  not `function` declarations. Object methods keep shorthand. Arrow consts\n  aren't hoisted — declare before use. Applies to new / rewritten code only;\n  don't mass-convert existing declarations.\n\n### Comments\n\n- **Every new file opens with a header comment** stating its purpose.\n- **Large templates / functions carry block comments** per meaningful region.\n- **Comments describe the code as it is now** — no changelog narration\n  (`previously…`, `…fixes that`); git history covers the past. A comment\n  stays shorter than the code it explains.\n\n### i18n coverage\n\n- Copy-surfacing features land in **all four locales** in the same change —\n  including `frontend/data/changelog.json` entries\n  (`tests/changelog.test.js` enforces it).\n\n### Logging (backend)\n\n- **Always the shared logger** (`common/logger.js`) in backend files; bare\n  `console.*` is banned there (frontend keeps using `console.*`).\n- Pino first-arg-is-context: `logger.error({ err, ip }, 'short message')`.\n- Env knobs: `LOG_LEVEL` (default info), `LOG_FORMAT=json` for shippers,\n  `LOG_HTTP=true` to mount `pino-http` on `/api` (off by default; handlers\n  never log \"received request\" lines themselves). No `NODE_ENV` anywhere.\n- Startup-only lines lead with an emoji (🚀 listening · 📦 ready ·\n  📥 downloading · 🛡️ security · 🐢 throttling · 🗓️ schedule · ⚠️ recoverable\n  · ❌ failure); per-request logs stay plain.\n\n## Testing\n\n- Any non-visual logic exercisable without a network call — pure functions,\n  composables with mockable inputs, transforms, validators — ships with a\n  spec in `tests/`, in the same change (don't defer; update affected tests\n  when behavior shifts).\n- UI rendering, real network behavior, and browser APIs are out of scope.\n- **`pnpm check` must be green before handing off.**\n\n## Security & Boundaries\n\nAccess control and timeouts live in shared middleware, not handlers\n(details in @api/AGENTS.md):\n\n- `requireReferer` is global on `/api/*`; `requirePublicIP()` per-route —\n  handlers never repeat these checks.\n- Every upstream HTTP call goes through `fetchUpstream`\n  (`common/fetch-with-timeout.js`, 8s timeout). Never a bare `fetch()` in `api/`.\n\n## Workflow\n\n- **Branch discipline — `dev` in, `dev` out.** `main` only moves via\n  dev → main PRs. From a worktree, fast-forward dev with `git push . HEAD:dev`\n  (repo has `receive.denyCurrentBranch=updateInstead`), not `git update-ref`.\n- **No commits without explicit user approval** — AI edits → user reviews →\n  user tests → user says \"commit\". Even with tests green, visual changes need\n  user eyes before landing.\n- **One concern per commit**, message style per `git log`\n  (`Feat(xxx):` / `Fix(ui):` / `Refactor(xxx):` / `Style:` / `Chore:`),\n  AI adds itself as co-author.\n- **Self-test before handing off** (`pnpm check`); if a change is visual and\n  headless-unverifiable, say so explicitly.\n- **On every commit, scan AGENTS.md (root + relevant sub-file) for\n  staleness** — conventions, renames, flipped rules, dead examples get fixed\n  in the same commit. Doc drift is this file's main failure mode.\n\n---\n\nIf [local-context.md](./local-context.md) exists in the workspace root, read\nit too — it lists machine-local Knowledge Hub paths (not in git).\n","category":"root","tokens":1655}]}