{"owner":"mayocream","repo":"koharu","hasSkills":true,"totalSkillsCount":20,"totalTokensCount":7541,"categories":["anthropic-skill","root-instruction","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["packages/ui/package.json","packages/koharu/.oxlintrc.json","packages/ui/components.json","AGENTS.md","packages/ui/tsconfig.json","packages/koharu/components.json","packages/koharu/package.json","packages/koharu/tsconfig.json","packages/bridge/package.json","packages/bridge/README.md","packages/bridge/tsconfig.json","packages/koharu/public/locales/zh-TW/translation.json","packages/koharu/public/locales/zh-CN/translation.json","packages/koharu/public/locales/tr-TR/translation.json","packages/koharu/public/locales/ru-RU/translation.json","packages/koharu/public/locales/pt-BR/translation.json","packages/koharu/public/locales/ko-KR/translation.json","packages/koharu/public/locales/ja-JP/translation.json","packages/koharu/public/locales/es-ES/translation.json","packages/koharu/public/locales/en-US/translation.json"],"skills":{"packages/ui/package.json":"{\n  \"name\": \"@koharu/ui\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./globals.css\": \"./src/styles/globals.css\",\n    \"./components/*\": \"./src/components/*.tsx\",\n    \"./lib/*\": \"./src/lib/*.ts\",\n    \"./hooks/*\": \"./src/hooks/*.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"shadcn\": \"shadcn add --all --overwrite --yes\"\n  },\n  \"dependencies\": {\n    \"@base-ui/react\": \"^1.9.0\",\n    \"@shadcn/react\": \"^0.3.1\",\n    \"class-variance-authority\": \"^0.7.1\",\n    \"clsx\": \"^2.1.1\",\n    \"cmdk\": \"^1.1.1\",\n    \"date-fns\": \"^4.4.0\",\n    \"embla-carousel-react\": \"^8.6.0\",\n    \"input-otp\": \"^1.5.0\",\n    \"lucide-react\": \"^1.59.0\",\n    \"react\": \"^19.3.1\",\n    \"react-day-picker\": \"^10.0.2\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-resizable-panels\": \"^4.14.5\",\n    \"recharts\": \"3.10.1\",\n    \"tailwind-merge\": \"^3.7.0\",\n    \"tw-animate-css\": \"^1.4.0\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"oxlint\": \"^1.89.0\",\n    \"shadcn\": \"^4.22.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n","packages/koharu/.oxlintrc.json":"{\n  \"$schema\": \"../node_modules/oxlint/configuration_schema.json\",\n  \"plugins\": [\"eslint\", \"typescript\", \"unicorn\", \"oxc\", \"react\"],\n  \"categories\": {\n    \"correctness\": \"error\"\n  },\n  \"rules\": {\n    \"react/exhaustive-deps\": \"warn\",\n    \"react/incompatible-library\": \"off\",\n    \"react/refs\": \"off\",\n    \"react/set-state-in-effect\": \"off\",\n    \"react/static-components\": \"off\",\n    \"no-useless-catch\": \"warn\",\n    \"typescript/no-useless-empty-export\": \"warn\",\n    \"unicorn/no-empty-file\": \"warn\",\n    \"unicorn/no-unnecessary-await\": \"warn\",\n    \"unicorn/no-useless-spread\": \"warn\",\n    \"no-unused-vars\": \"warn\",\n    \"unicorn/no-document-cookie\": \"warn\",\n    \"no-useless-rename\": \"warn\",\n    \"unicorn/no-useless-length-check\": \"warn\",\n    \"no-useless-escape\": \"warn\",\n    \"typescript/prefer-as-const\": \"warn\",\n    \"unicorn/no-useless-fallback-in-spread\": \"warn\",\n    \"no-extra-boolean-cast\": \"warn\",\n    \"unicorn/no-new-array\": \"warn\",\n    \"unicorn/prefer-set-size\": \"warn\",\n    \"typescript/no-this-alias\": \"warn\",\n    \"unicorn/prefer-string-starts-ends-with\": \"warn\"\n  },\n  \"ignorePatterns\": [\".next/\", \"out/\", \"dist/\", \"build/\", \"coverage/\", \"lib/api/**/*.msw.ts\"]\n}\n","packages/ui/components.json":"{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"menuAccent\": \"subtle\",\n  \"menuColor\": \"default-translucent\",\n  \"aliases\": {\n    \"components\": \"@koharu/ui/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@koharu/ui/lib\",\n    \"hooks\": \"@koharu/ui/hooks\"\n  },\n  \"registries\": {}\n}\n","AGENTS.md":"# Koharu Project Rules\n\nDocument only durable, repository-specific constraints here. Do not record current file layouts, temporary paths, model inventories, helper names, or other implementation details that may change during a refactor. Normal Rust, TypeScript, testing, formatting, and Git practices are assumed.\n\n## Change Policy\n\n- Never add backward compatibility. When an API, schema, configuration, or ownership boundary changes, update every in-repository consumer and remove the replaced form.\n- Prefer a coherent ownership redesign over aliases, forwarding layers, compatibility parsers, or cosmetic renaming.\n- Keep responsibilities self-contained. Defaults and provider-specific behavior belong to the component that owns them rather than a central list of special cases.\n- Remove dead abstractions and one-use helpers when direct code is clearer.\n- Make the smallest change that solves the problem. Do not edit unrelated configuration, documentation, generated files, or workflows in the same change. A feature does not land beside drive-by cleanup.\n- If the current owner has moved, rebase onto that owner. Do not port a patch onto a deleted tree.\n- When two changes implement the same workflow, keep one and extend the existing command or configuration. Do not land both.\n- For editor behavior that is not already specified, match Photoshop or Clip Studio Paint. Prefer an in-app edit over an export/import round trip when the task is ordinary editing.\n- Desktop API keys go through the OS credential store. Do not add a project environment-file fallback for the desktop app.\n- Once a subsystem is removed, delete its calls and dependency together. Do not leave a stub, alias, or disabled flag behind.\n\n## Ownership\n\n- The UI invokes typed commands. Native code owns durable project state and processing. Do not add an HTTP client or a generic event envelope.\n- Scene owns what a project means. Storage owns opaque payloads and immutable blobs. Analysis, content, and presentation stay separate: detection geometry is not a visible layer, translation does not drop OCR provenance, and typography does not rewrite semantic text.\n- A patch binds to a project and a base revision, records preconditions, and carries inverses. Reject a stale patch. Derived work rebases explicitly and fails if anything it observed has changed.\n- Publish missing blobs first, write the inactive state slot, then publish atomically. Opening uses the newest valid slot and can fall back. Renderer, pipeline, and Agent consume snapshots and submit patches. They do not write storage files.\n- A pipeline stage runs on one page: detection, then OCR and translation, or detection, then inpainting. Pages enter in project order. Completed detection makes that page's later stages eligible immediately. At most one job per stage runs at a time. Each committed result is its own undo step. Do not add a second translation prompt path.\n- Accelerator inference uses one admission lane, including remote translation. On out-of-memory, release the lane, unload the other models, wait for a fresh resource sample, and retry once. Any other failure unloads the failing stage. Stopping is cooperative and discards an uncommitted result.\n- One prepared frame feeds presentation, PNG, layer crops, and PSD. Translation is the only visible text. Incremental reuse must match a full render. The previous page stays visible until the staged generation is ready. An obsolete preparation cannot replace a newer generation. Transient camera, transform, stroke, and sampling stay in the browser. Completed edits cross commands.\n\n## Interface\n\n- User-visible strings go through the translation function and the locale files. Hardcoded English in a translated surface is incomplete.\n- An interface language's display name is that language's own name in every locale. Do not translate it into the surrounding locale.\n- The translation-target language list stays in the active UI language. Drop a country name unless the entry is a real variant.\n- Do not duplicate status the current selection already implies. Do not add a second job kind, cancel path, or counter for an operation the existing command already covers.\n- Use the existing control library for standard interaction. Commit on selection or an uncanceled drop, not on focus or hover. Ignore a canceled drag. Do not let a shortcut steal keys from a focused control.\n- Reuse the existing numeric color and typography representation. Do not introduce a parallel string format.\n- A page switch uses the existing selection and optimistic cache update. Do not add a second navigation path that leaves the rail, layer selection, or query data behind.\n\n## Source Boundaries\n\n- Keep safe public APIs separate from unsafe FFI, dynamic loading, and build integration.\n- Do not hand-edit generated or derived source. Change its authoritative input and run the generator.\n- Do not commit credentials, model weights, datasets, generated outputs, or machine-specific artifacts.\n- Native llama.cpp and diffusion runtimes come from prebuilt packages. Do not compile those CUDA trees inside the app build. Release and publish jobs do a fresh build.\n- Hardware discovery stays separate from managed runtime package activation. Do not load a cached accelerator runtime during the probe.\n- Error sampling is off in debug builds and on in release builds.\n\n## ML Architecture\n\n- Keep a consistent public lifecycle across models while allowing model-specific inputs and outputs.\n- Separate network ownership and weight loading from preprocessing, postprocessing, slicing, and public result types.\n- Avoid pass-through types and layers that do not own a real responsibility.\n- Accept a device abstraction at the model boundary, convert it once, and avoid unnecessary transfers or synchronization.\n- Use the established runtime and variable-store loading paths unless they are proven insufficient.\n- Disable gradient tracking during inference.\n- Create generated token IDs and index tensors on the model device. A CPU tensor used against accelerator embeddings is a defect, not a later optimization.\n- Invalid model JSON fails closed. Do not add a silent repair layer that can change meaning.\n- Enforce a translation output schema through each provider's native structured-output API. A bounded retry belongs only to a provider that already has one. Hosted machine-translation providers fail immediately.\n\n## Upstream Alignment\n\n- Keep ports structurally traceable to a commit-pinned authoritative implementation.\n- Preserve checkpoint-affecting names, construction order, parameter paths, tensor layouts, execution order, and postprocessing semantics.\n- Treat missing or unexpected weights as an architecture or parameter-name mismatch before changing the loader.\n- Explain intentional divergences next to the affected code.\n- Compare ports on identical inputs using structured outputs such as shapes, ranges, boxes, scores, masks, and ordering.\n\n## Performance\n\n- Optimize and benchmark the actual target device with representative inputs.\n- Remove redundant transfers, synchronization, allocations, and per-pixel host loops before adding concurrency or caching.\n- Account for asynchronous accelerator execution when timing work.\n- Load assets and warm models outside measured regions.\n- Report the device, input size, baseline, result, and correctness difference.\n\n## Verification\n\n- Optimize for fast development and iteration. By default, run the smallest relevant check or focused test once using the debug profile.\n- Do not run full test suites, repeatedly rerun unchanged tests or builds, or build and test profiles other than debug unless the user explicitly requests it.\n- Run end-to-end tests only when the user explicitly asks for them.\n- Add a test when it protects a real regression boundary. Do not lock a translated phrase, a language display name, a registration string, or a one-line behavior the owner can read directly. Do not add a second harness for behavior the crate's existing tests already cover. Do not assert a compatibility shim.\n- A UI change needs a screenshot of the affected state. If the bug is truncation, include a long-label case.\n- A model port needs a structured comparison on identical inputs. A green build is not that comparison.\n- A green check is not acceptance. Small bug fixes, documentation, translations, and tests can be opened directly. A new product feature, significant UI change, model or provider integration, platform integration, dependency, public API, schema change, or architectural refactor needs an issue discussion first.\n- Keep the pull-request text short: problem, change, and verification. A human reviews the whole diff and can explain every change. Do not submit an unreviewed autonomous patch.\n\n## Desktop UI Debugging\n\n- Debug builds must expose the CEF remote debugging endpoint at `http://127.0.0.1:4000` through CEF's command-line arguments.\n- Connect `chrome-devtools-mcp` with `--browser-url=http://127.0.0.1:4000` and prefer its tools for WebView inspection and automation. Use semantic targets and observable conditions instead of coordinate-only actions or fixed delays.\n- Use a lower-level CDP client only when `chrome-devtools-mcp` does not expose a required protocol operation. Use native window capture when CDP cannot observe the final WebGPU output.\n\n## Desktop Rendering\n\n- Koharu presents canvas pixels through the `koharu-canvas` WASM module and WebGPU inside the standard Tauri webview. Keep durable scene preparation and export native, keep transient canvas interaction in the browser, and validate WebGPU presentation through the final desktop window.\n\n## Documentation\n\n- Comments should explain ownership, invariants, upstream mapping, or deliberate divergence; do not narrate straightforward code.\n- Keep this file focused on long-lived decision rules rather than the current implementation.\n","packages/ui/tsconfig.json":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"paths\": {\n      \"@koharu/ui/*\": [\"./src/*\"]\n    }\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"]\n}\n","packages/koharu/components.json":"{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"../ui/src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"aliases\": {\n    \"components\": \"@/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@/lib\",\n    \"hooks\": \"@/hooks\"\n  },\n  \"registries\": {}\n}\n","packages/koharu/package.json":"{\n  \"name\": \"@koharu/app\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next dev --port 3000\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"lint\": \"oxlint -c .oxlintrc.json\",\n    \"test\": \"vitest run\"\n  },\n  \"dependencies\": {\n    \"@koharu/bridge\": \"workspace:*\",\n    \"@koharu/ui\": \"workspace:*\",\n    \"@sentry/nextjs\": \"^11.8.0\",\n    \"@tanstack/react-query\": \"^5.104.4\",\n    \"@tanstack/react-virtual\": \"^3.14.21\",\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-opener\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-process\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-updater\": \"3.0.0-alpha.3\",\n    \"i18next\": \"^26.5.3\",\n    \"i18next-browser-languagedetector\": \"^8.2.1\",\n    \"i18next-localstorage-backend\": \"^4.3.2\",\n    \"lucide-react\": \"^1.59.0\",\n    \"next\": \"^16.4.2\",\n    \"next-themes\": \"^0.4.6\",\n    \"react\": \"^19.3.1\",\n    \"react-colorful\": \"^5.8.1\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-i18next\": \"^17.1.0\",\n    \"react-markdown\": \"^10.1.0\",\n    \"remark-gfm\": \"^4.0.1\",\n    \"zustand\": \"^5.0.15\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@testing-library/jest-dom\": \"^7.0.1\",\n    \"@testing-library/react\": \"^16.3.3\",\n    \"@testing-library/user-event\": \"^14.6.8\",\n    \"@types/node\": \"^26.6.5\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"@vitejs/plugin-react\": \"^6.1.2\",\n    \"@vitest/ui\": \"^5.0.5\",\n    \"jsdom\": \"^30.1.3\",\n    \"oxlint\": \"^1.89.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\",\n    \"vitest\": \"^5.0.5\"\n  }\n}\n","packages/koharu/tsconfig.json":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"noImplicitAny\": false,\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"],\n      \"@koharu/ui/*\": [\"../ui/src/*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".next/dev/types/**/*.ts\",\n    \"**/*.mts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n","packages/bridge/package.json":"{\n  \"name\": \"@koharu/bridge\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./canvas\": \"./src/canvas.ts\",\n    \"./protocol\": \"./src/protocol.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src --ignore-pattern src/protocol.ts --ignore-pattern src/wasm\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"dev\": \"nodemon --watch $(npm prefix)/crates/koharu-canvas --watch $(npm prefix)/crates/koharu-rasterizer --ext rs,toml --delay 250ms --on-change-only --exec bun -- run --filter @koharu/bridge build\",\n    \"build\": \"bun x wasm-pack@0.15.0 build $(npm prefix)/crates/koharu-canvas --release --target web --out-dir $(npm prefix)/packages/bridge/src/wasm --out-name koharu_canvas --no-pack\"\n  },\n  \"dependencies\": {\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\"\n  },\n  \"devDependencies\": {\n    \"nodemon\": \"^3.1.14\",\n    \"oxlint\": \"^1.89.0\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n","packages/bridge/README.md":"# @koharu/bridge\n\nThis package owns Koharu's browser/native boundary:\n\n- `src/protocol.ts` is generated from the Rust Tauri command surface;\n- `src/canvas.ts` adapts that protocol and `koharu-canvas` to the browser;\n- `src/wasm` is ignored derived output produced by `wasm-pack`.\n\nThe bridge package builds only its WASM output. The root frontend tasks sequence that build before starting or building the consuming Next.js app. During development, `nodemon` rebuilds the bridge when `koharu-canvas` or `koharu-rasterizer` changes. `npm prefix` supplies the absolute workspace root directly to the package commands, so they do not depend on parent traversal or shell environment variables. Because the generated glue is imported from this package, Next.js includes it in the Turbopack module graph and refreshes the client after a successful rebuild.\n\nRegenerate the protocol with `cargo run -p koharu-app --bin generate`. Do not edit generated protocol or WASM output by hand.\n","packages/bridge/tsconfig.json":"# Bridge Skill\n\nPath: `packages/bridge/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/bridge/tsconfig.json)","packages/koharu/public/locales/zh-TW/translation.json":"# Zh-TW Skill\n\nPath: `packages/koharu/public/locales/zh-TW/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-TW/translation.json)","packages/koharu/public/locales/zh-CN/translation.json":"# Zh-CN Skill\n\nPath: `packages/koharu/public/locales/zh-CN/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-CN/translation.json)","packages/koharu/public/locales/tr-TR/translation.json":"# Tr-TR Skill\n\nPath: `packages/koharu/public/locales/tr-TR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/tr-TR/translation.json)","packages/koharu/public/locales/ru-RU/translation.json":"# Ru-RU Skill\n\nPath: `packages/koharu/public/locales/ru-RU/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ru-RU/translation.json)","packages/koharu/public/locales/pt-BR/translation.json":"# Pt-BR Skill\n\nPath: `packages/koharu/public/locales/pt-BR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/pt-BR/translation.json)","packages/koharu/public/locales/ko-KR/translation.json":"# Ko-KR Skill\n\nPath: `packages/koharu/public/locales/ko-KR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ko-KR/translation.json)","packages/koharu/public/locales/ja-JP/translation.json":"# Ja-JP Skill\n\nPath: `packages/koharu/public/locales/ja-JP/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ja-JP/translation.json)","packages/koharu/public/locales/es-ES/translation.json":"# Es-ES Skill\n\nPath: `packages/koharu/public/locales/es-ES/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/es-ES/translation.json)","packages/koharu/public/locales/en-US/translation.json":"# En-US Skill\n\nPath: `packages/koharu/public/locales/en-US/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/en-US/translation.json)"},"files":{"packages/ui/package.json":"{\n  \"name\": \"@koharu/ui\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./globals.css\": \"./src/styles/globals.css\",\n    \"./components/*\": \"./src/components/*.tsx\",\n    \"./lib/*\": \"./src/lib/*.ts\",\n    \"./hooks/*\": \"./src/hooks/*.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"shadcn\": \"shadcn add --all --overwrite --yes\"\n  },\n  \"dependencies\": {\n    \"@base-ui/react\": \"^1.9.0\",\n    \"@shadcn/react\": \"^0.3.1\",\n    \"class-variance-authority\": \"^0.7.1\",\n    \"clsx\": \"^2.1.1\",\n    \"cmdk\": \"^1.1.1\",\n    \"date-fns\": \"^4.4.0\",\n    \"embla-carousel-react\": \"^8.6.0\",\n    \"input-otp\": \"^1.5.0\",\n    \"lucide-react\": \"^1.59.0\",\n    \"react\": \"^19.3.1\",\n    \"react-day-picker\": \"^10.0.2\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-resizable-panels\": \"^4.14.5\",\n    \"recharts\": \"3.10.1\",\n    \"tailwind-merge\": \"^3.7.0\",\n    \"tw-animate-css\": \"^1.4.0\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"oxlint\": \"^1.89.0\",\n    \"shadcn\": \"^4.22.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n","packages/koharu/.oxlintrc.json":"{\n  \"$schema\": \"../node_modules/oxlint/configuration_schema.json\",\n  \"plugins\": [\"eslint\", \"typescript\", \"unicorn\", \"oxc\", \"react\"],\n  \"categories\": {\n    \"correctness\": \"error\"\n  },\n  \"rules\": {\n    \"react/exhaustive-deps\": \"warn\",\n    \"react/incompatible-library\": \"off\",\n    \"react/refs\": \"off\",\n    \"react/set-state-in-effect\": \"off\",\n    \"react/static-components\": \"off\",\n    \"no-useless-catch\": \"warn\",\n    \"typescript/no-useless-empty-export\": \"warn\",\n    \"unicorn/no-empty-file\": \"warn\",\n    \"unicorn/no-unnecessary-await\": \"warn\",\n    \"unicorn/no-useless-spread\": \"warn\",\n    \"no-unused-vars\": \"warn\",\n    \"unicorn/no-document-cookie\": \"warn\",\n    \"no-useless-rename\": \"warn\",\n    \"unicorn/no-useless-length-check\": \"warn\",\n    \"no-useless-escape\": \"warn\",\n    \"typescript/prefer-as-const\": \"warn\",\n    \"unicorn/no-useless-fallback-in-spread\": \"warn\",\n    \"no-extra-boolean-cast\": \"warn\",\n    \"unicorn/no-new-array\": \"warn\",\n    \"unicorn/prefer-set-size\": \"warn\",\n    \"typescript/no-this-alias\": \"warn\",\n    \"unicorn/prefer-string-starts-ends-with\": \"warn\"\n  },\n  \"ignorePatterns\": [\".next/\", \"out/\", \"dist/\", \"build/\", \"coverage/\", \"lib/api/**/*.msw.ts\"]\n}\n","packages/ui/components.json":"{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"menuAccent\": \"subtle\",\n  \"menuColor\": \"default-translucent\",\n  \"aliases\": {\n    \"components\": \"@koharu/ui/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@koharu/ui/lib\",\n    \"hooks\": \"@koharu/ui/hooks\"\n  },\n  \"registries\": {}\n}\n","AGENTS.md":"# Koharu Project Rules\n\nDocument only durable, repository-specific constraints here. Do not record current file layouts, temporary paths, model inventories, helper names, or other implementation details that may change during a refactor. Normal Rust, TypeScript, testing, formatting, and Git practices are assumed.\n\n## Change Policy\n\n- Never add backward compatibility. When an API, schema, configuration, or ownership boundary changes, update every in-repository consumer and remove the replaced form.\n- Prefer a coherent ownership redesign over aliases, forwarding layers, compatibility parsers, or cosmetic renaming.\n- Keep responsibilities self-contained. Defaults and provider-specific behavior belong to the component that owns them rather than a central list of special cases.\n- Remove dead abstractions and one-use helpers when direct code is clearer.\n- Make the smallest change that solves the problem. Do not edit unrelated configuration, documentation, generated files, or workflows in the same change. A feature does not land beside drive-by cleanup.\n- If the current owner has moved, rebase onto that owner. Do not port a patch onto a deleted tree.\n- When two changes implement the same workflow, keep one and extend the existing command or configuration. Do not land both.\n- For editor behavior that is not already specified, match Photoshop or Clip Studio Paint. Prefer an in-app edit over an export/import round trip when the task is ordinary editing.\n- Desktop API keys go through the OS credential store. Do not add a project environment-file fallback for the desktop app.\n- Once a subsystem is removed, delete its calls and dependency together. Do not leave a stub, alias, or disabled flag behind.\n\n## Ownership\n\n- The UI invokes typed commands. Native code owns durable project state and processing. Do not add an HTTP client or a generic event envelope.\n- Scene owns what a project means. Storage owns opaque payloads and immutable blobs. Analysis, content, and presentation stay separate: detection geometry is not a visible layer, translation does not drop OCR provenance, and typography does not rewrite semantic text.\n- A patch binds to a project and a base revision, records preconditions, and carries inverses. Reject a stale patch. Derived work rebases explicitly and fails if anything it observed has changed.\n- Publish missing blobs first, write the inactive state slot, then publish atomically. Opening uses the newest valid slot and can fall back. Renderer, pipeline, and Agent consume snapshots and submit patches. They do not write storage files.\n- A pipeline stage runs on one page: detection, then OCR and translation, or detection, then inpainting. Pages enter in project order. Completed detection makes that page's later stages eligible immediately. At most one job per stage runs at a time. Each committed result is its own undo step. Do not add a second translation prompt path.\n- Accelerator inference uses one admission lane, including remote translation. On out-of-memory, release the lane, unload the other models, wait for a fresh resource sample, and retry once. Any other failure unloads the failing stage. Stopping is cooperative and discards an uncommitted result.\n- One prepared frame feeds presentation, PNG, layer crops, and PSD. Translation is the only visible text. Incremental reuse must match a full render. The previous page stays visible until the staged generation is ready. An obsolete preparation cannot replace a newer generation. Transient camera, transform, stroke, and sampling stay in the browser. Completed edits cross commands.\n\n## Interface\n\n- User-visible strings go through the translation function and the locale files. Hardcoded English in a translated surface is incomplete.\n- An interface language's display name is that language's own name in every locale. Do not translate it into the surrounding locale.\n- The translation-target language list stays in the active UI language. Drop a country name unless the entry is a real variant.\n- Do not duplicate status the current selection already implies. Do not add a second job kind, cancel path, or counter for an operation the existing command already covers.\n- Use the existing control library for standard interaction. Commit on selection or an uncanceled drop, not on focus or hover. Ignore a canceled drag. Do not let a shortcut steal keys from a focused control.\n- Reuse the existing numeric color and typography representation. Do not introduce a parallel string format.\n- A page switch uses the existing selection and optimistic cache update. Do not add a second navigation path that leaves the rail, layer selection, or query data behind.\n\n## Source Boundaries\n\n- Keep safe public APIs separate from unsafe FFI, dynamic loading, and build integration.\n- Do not hand-edit generated or derived source. Change its authoritative input and run the generator.\n- Do not commit credentials, model weights, datasets, generated outputs, or machine-specific artifacts.\n- Native llama.cpp and diffusion runtimes come from prebuilt packages. Do not compile those CUDA trees inside the app build. Release and publish jobs do a fresh build.\n- Hardware discovery stays separate from managed runtime package activation. Do not load a cached accelerator runtime during the probe.\n- Error sampling is off in debug builds and on in release builds.\n\n## ML Architecture\n\n- Keep a consistent public lifecycle across models while allowing model-specific inputs and outputs.\n- Separate network ownership and weight loading from preprocessing, postprocessing, slicing, and public result types.\n- Avoid pass-through types and layers that do not own a real responsibility.\n- Accept a device abstraction at the model boundary, convert it once, and avoid unnecessary transfers or synchronization.\n- Use the established runtime and variable-store loading paths unless they are proven insufficient.\n- Disable gradient tracking during inference.\n- Create generated token IDs and index tensors on the model device. A CPU tensor used against accelerator embeddings is a defect, not a later optimization.\n- Invalid model JSON fails closed. Do not add a silent repair layer that can change meaning.\n- Enforce a translation output schema through each provider's native structured-output API. A bounded retry belongs only to a provider that already has one. Hosted machine-translation providers fail immediately.\n\n## Upstream Alignment\n\n- Keep ports structurally traceable to a commit-pinned authoritative implementation.\n- Preserve checkpoint-affecting names, construction order, parameter paths, tensor layouts, execution order, and postprocessing semantics.\n- Treat missing or unexpected weights as an architecture or parameter-name mismatch before changing the loader.\n- Explain intentional divergences next to the affected code.\n- Compare ports on identical inputs using structured outputs such as shapes, ranges, boxes, scores, masks, and ordering.\n\n## Performance\n\n- Optimize and benchmark the actual target device with representative inputs.\n- Remove redundant transfers, synchronization, allocations, and per-pixel host loops before adding concurrency or caching.\n- Account for asynchronous accelerator execution when timing work.\n- Load assets and warm models outside measured regions.\n- Report the device, input size, baseline, result, and correctness difference.\n\n## Verification\n\n- Optimize for fast development and iteration. By default, run the smallest relevant check or focused test once using the debug profile.\n- Do not run full test suites, repeatedly rerun unchanged tests or builds, or build and test profiles other than debug unless the user explicitly requests it.\n- Run end-to-end tests only when the user explicitly asks for them.\n- Add a test when it protects a real regression boundary. Do not lock a translated phrase, a language display name, a registration string, or a one-line behavior the owner can read directly. Do not add a second harness for behavior the crate's existing tests already cover. Do not assert a compatibility shim.\n- A UI change needs a screenshot of the affected state. If the bug is truncation, include a long-label case.\n- A model port needs a structured comparison on identical inputs. A green build is not that comparison.\n- A green check is not acceptance. Small bug fixes, documentation, translations, and tests can be opened directly. A new product feature, significant UI change, model or provider integration, platform integration, dependency, public API, schema change, or architectural refactor needs an issue discussion first.\n- Keep the pull-request text short: problem, change, and verification. A human reviews the whole diff and can explain every change. Do not submit an unreviewed autonomous patch.\n\n## Desktop UI Debugging\n\n- Debug builds must expose the CEF remote debugging endpoint at `http://127.0.0.1:4000` through CEF's command-line arguments.\n- Connect `chrome-devtools-mcp` with `--browser-url=http://127.0.0.1:4000` and prefer its tools for WebView inspection and automation. Use semantic targets and observable conditions instead of coordinate-only actions or fixed delays.\n- Use a lower-level CDP client only when `chrome-devtools-mcp` does not expose a required protocol operation. Use native window capture when CDP cannot observe the final WebGPU output.\n\n## Desktop Rendering\n\n- Koharu presents canvas pixels through the `koharu-canvas` WASM module and WebGPU inside the standard Tauri webview. Keep durable scene preparation and export native, keep transient canvas interaction in the browser, and validate WebGPU presentation through the final desktop window.\n\n## Documentation\n\n- Comments should explain ownership, invariants, upstream mapping, or deliberate divergence; do not narrate straightforward code.\n- Keep this file focused on long-lived decision rules rather than the current implementation.\n","packages/ui/tsconfig.json":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"paths\": {\n      \"@koharu/ui/*\": [\"./src/*\"]\n    }\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"]\n}\n","packages/koharu/components.json":"{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"../ui/src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"aliases\": {\n    \"components\": \"@/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@/lib\",\n    \"hooks\": \"@/hooks\"\n  },\n  \"registries\": {}\n}\n","packages/koharu/package.json":"{\n  \"name\": \"@koharu/app\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next dev --port 3000\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"lint\": \"oxlint -c .oxlintrc.json\",\n    \"test\": \"vitest run\"\n  },\n  \"dependencies\": {\n    \"@koharu/bridge\": \"workspace:*\",\n    \"@koharu/ui\": \"workspace:*\",\n    \"@sentry/nextjs\": \"^11.8.0\",\n    \"@tanstack/react-query\": \"^5.104.4\",\n    \"@tanstack/react-virtual\": \"^3.14.21\",\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-opener\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-process\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-updater\": \"3.0.0-alpha.3\",\n    \"i18next\": \"^26.5.3\",\n    \"i18next-browser-languagedetector\": \"^8.2.1\",\n    \"i18next-localstorage-backend\": \"^4.3.2\",\n    \"lucide-react\": \"^1.59.0\",\n    \"next\": \"^16.4.2\",\n    \"next-themes\": \"^0.4.6\",\n    \"react\": \"^19.3.1\",\n    \"react-colorful\": \"^5.8.1\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-i18next\": \"^17.1.0\",\n    \"react-markdown\": \"^10.1.0\",\n    \"remark-gfm\": \"^4.0.1\",\n    \"zustand\": \"^5.0.15\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@testing-library/jest-dom\": \"^7.0.1\",\n    \"@testing-library/react\": \"^16.3.3\",\n    \"@testing-library/user-event\": \"^14.6.8\",\n    \"@types/node\": \"^26.6.5\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"@vitejs/plugin-react\": \"^6.1.2\",\n    \"@vitest/ui\": \"^5.0.5\",\n    \"jsdom\": \"^30.1.3\",\n    \"oxlint\": \"^1.89.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\",\n    \"vitest\": \"^5.0.5\"\n  }\n}\n","packages/koharu/tsconfig.json":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"noImplicitAny\": false,\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"],\n      \"@koharu/ui/*\": [\"../ui/src/*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".next/dev/types/**/*.ts\",\n    \"**/*.mts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n","packages/bridge/package.json":"{\n  \"name\": \"@koharu/bridge\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./canvas\": \"./src/canvas.ts\",\n    \"./protocol\": \"./src/protocol.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src --ignore-pattern src/protocol.ts --ignore-pattern src/wasm\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"dev\": \"nodemon --watch $(npm prefix)/crates/koharu-canvas --watch $(npm prefix)/crates/koharu-rasterizer --ext rs,toml --delay 250ms --on-change-only --exec bun -- run --filter @koharu/bridge build\",\n    \"build\": \"bun x wasm-pack@0.15.0 build $(npm prefix)/crates/koharu-canvas --release --target web --out-dir $(npm prefix)/packages/bridge/src/wasm --out-name koharu_canvas --no-pack\"\n  },\n  \"dependencies\": {\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\"\n  },\n  \"devDependencies\": {\n    \"nodemon\": \"^3.1.14\",\n    \"oxlint\": \"^1.89.0\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n","packages/bridge/README.md":"# @koharu/bridge\n\nThis package owns Koharu's browser/native boundary:\n\n- `src/protocol.ts` is generated from the Rust Tauri command surface;\n- `src/canvas.ts` adapts that protocol and `koharu-canvas` to the browser;\n- `src/wasm` is ignored derived output produced by `wasm-pack`.\n\nThe bridge package builds only its WASM output. The root frontend tasks sequence that build before starting or building the consuming Next.js app. During development, `nodemon` rebuilds the bridge when `koharu-canvas` or `koharu-rasterizer` changes. `npm prefix` supplies the absolute workspace root directly to the package commands, so they do not depend on parent traversal or shell environment variables. Because the generated glue is imported from this package, Next.js includes it in the Turbopack module graph and refreshes the client after a successful rebuild.\n\nRegenerate the protocol with `cargo run -p koharu-app --bin generate`. Do not edit generated protocol or WASM output by hand.\n","packages/bridge/tsconfig.json":"# Bridge Skill\n\nPath: `packages/bridge/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/bridge/tsconfig.json)","packages/koharu/public/locales/zh-TW/translation.json":"# Zh-TW Skill\n\nPath: `packages/koharu/public/locales/zh-TW/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-TW/translation.json)","packages/koharu/public/locales/zh-CN/translation.json":"# Zh-CN Skill\n\nPath: `packages/koharu/public/locales/zh-CN/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-CN/translation.json)","packages/koharu/public/locales/tr-TR/translation.json":"# Tr-TR Skill\n\nPath: `packages/koharu/public/locales/tr-TR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/tr-TR/translation.json)","packages/koharu/public/locales/ru-RU/translation.json":"# Ru-RU Skill\n\nPath: `packages/koharu/public/locales/ru-RU/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ru-RU/translation.json)","packages/koharu/public/locales/pt-BR/translation.json":"# Pt-BR Skill\n\nPath: `packages/koharu/public/locales/pt-BR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/pt-BR/translation.json)","packages/koharu/public/locales/ko-KR/translation.json":"# Ko-KR Skill\n\nPath: `packages/koharu/public/locales/ko-KR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ko-KR/translation.json)","packages/koharu/public/locales/ja-JP/translation.json":"# Ja-JP Skill\n\nPath: `packages/koharu/public/locales/ja-JP/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ja-JP/translation.json)","packages/koharu/public/locales/es-ES/translation.json":"# Es-ES Skill\n\nPath: `packages/koharu/public/locales/es-ES/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/es-ES/translation.json)","packages/koharu/public/locales/en-US/translation.json":"# En-US Skill\n\nPath: `packages/koharu/public/locales/en-US/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/en-US/translation.json)"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Koharu Project Rules\n\nDocument only durable, repository-specific constraints here. Do not record current file layouts, temporary paths, model inventories, helper names, or other implementation details that may change during a refactor. Normal Rust, TypeScript, testing, formatting, and Git practices are assumed.\n\n## Change Policy\n\n- Never add backward compatibility. When an API, schema, configuration, or ownership boundary changes, update every in-repository consumer and remove the replaced form.\n- Prefer a coherent ownership redesign over aliases, forwarding layers, compatibility parsers, or cosmetic renaming.\n- Keep responsibilities self-contained. Defaults and provider-specific behavior belong to the component that owns them rather than a central list of special cases.\n- Remove dead abstractions and one-use helpers when direct code is clearer.\n- Make the smallest change that solves the problem. Do not edit unrelated configuration, documentation, generated files, or workflows in the same change. A feature does not land beside drive-by cleanup.\n- If the current owner has moved, rebase onto that owner. Do not port a patch onto a deleted tree.\n- When two changes implement the same workflow, keep one and extend the existing command or configuration. Do not land both.\n- For editor behavior that is not already specified, match Photoshop or Clip Studio Paint. Prefer an in-app edit over an export/import round trip when the task is ordinary editing.\n- Desktop API keys go through the OS credential store. Do not add a project environment-file fallback for the desktop app.\n- Once a subsystem is removed, delete its calls and dependency together. Do not leave a stub, alias, or disabled flag behind.\n\n## Ownership\n\n- The UI invokes typed commands. Native code owns durable project state and processing. Do not add an HTTP client or a generic event envelope.\n- Scene owns what a project means. Storage owns opaque payloads and immutable blobs. Analysis, content, and presentation stay separate: detection geometry is not a visible layer, translation does not drop OCR provenance, and typography does not rewrite semantic text.\n- A patch binds to a project and a base revision, records preconditions, and carries inverses. Reject a stale patch. Derived work rebases explicitly and fails if anything it observed has changed.\n- Publish missing blobs first, write the inactive state slot, then publish atomically. Opening uses the newest valid slot and can fall back. Renderer, pipeline, and Agent consume snapshots and submit patches. They do not write storage files.\n- A pipeline stage runs on one page: detection, then OCR and translation, or detection, then inpainting. Pages enter in project order. Completed detection makes that page's later stages eligible immediately. At most one job per stage runs at a time. Each committed result is its own undo step. Do not add a second translation prompt path.\n- Accelerator inference uses one admission lane, including remote translation. On out-of-memory, release the lane, unload the other models, wait for a fresh resource sample, and retry once. Any other failure unloads the failing stage. Stopping is cooperative and discards an uncommitted result.\n- One prepared frame feeds presentation, PNG, layer crops, and PSD. Translation is the only visible text. Incremental reuse must match a full render. The previous page stays visible until the staged generation is ready. An obsolete preparation cannot replace a newer generation. Transient camera, transform, stroke, and sampling stay in the browser. Completed edits cross commands.\n\n## Interface\n\n- User-visible strings go through the translation function and the locale files. Hardcoded English in a translated surface is incomplete.\n- An interface language's display name is that language's own name in every locale. Do not translate it into the surrounding locale.\n- The translation-target language list stays in the active UI language. Drop a country name unless the entry is a real variant.\n- Do not duplicate status the current selection already implies. Do not add a second job kind, cancel path, or counter for an operation the existing command already covers.\n- Use the existing control library for standard interaction. Commit on selection or an uncanceled drop, not on focus or hover. Ignore a canceled drag. Do not let a shortcut steal keys from a focused control.\n- Reuse the existing numeric color and typography representation. Do not introduce a parallel string format.\n- A page switch uses the existing selection and optimistic cache update. Do not add a second navigation path that leaves the rail, layer selection, or query data behind.\n\n## Source Boundaries\n\n- Keep safe public APIs separate from unsafe FFI, dynamic loading, and build integration.\n- Do not hand-edit generated or derived source. Change its authoritative input and run the generator.\n- Do not commit credentials, model weights, datasets, generated outputs, or machine-specific artifacts.\n- Native llama.cpp and diffusion runtimes come from prebuilt packages. Do not compile those CUDA trees inside the app build. Release and publish jobs do a fresh build.\n- Hardware discovery stays separate from managed runtime package activation. Do not load a cached accelerator runtime during the probe.\n- Error sampling is off in debug builds and on in release builds.\n\n## ML Architecture\n\n- Keep a consistent public lifecycle across models while allowing model-specific inputs and outputs.\n- Separate network ownership and weight loading from preprocessing, postprocessing, slicing, and public result types.\n- Avoid pass-through types and layers that do not own a real responsibility.\n- Accept a device abstraction at the model boundary, convert it once, and avoid unnecessary transfers or synchronization.\n- Use the established runtime and variable-store loading paths unless they are proven insufficient.\n- Disable gradient tracking during inference.\n- Create generated token IDs and index tensors on the model device. A CPU tensor used against accelerator embeddings is a defect, not a later optimization.\n- Invalid model JSON fails closed. Do not add a silent repair layer that can change meaning.\n- Enforce a translation output schema through each provider's native structured-output API. A bounded retry belongs only to a provider that already has one. Hosted machine-translation providers fail immediately.\n\n## Upstream Alignment\n\n- Keep ports structurally traceable to a commit-pinned authoritative implementation.\n- Preserve checkpoint-affecting names, construction order, parameter paths, tensor layouts, execution order, and postprocessing semantics.\n- Treat missing or unexpected weights as an architecture or parameter-name mismatch before changing the loader.\n- Explain intentional divergences next to the affected code.\n- Compare ports on identical inputs using structured outputs such as shapes, ranges, boxes, scores, masks, and ordering.\n\n## Performance\n\n- Optimize and benchmark the actual target device with representative inputs.\n- Remove redundant transfers, synchronization, allocations, and per-pixel host loops before adding concurrency or caching.\n- Account for asynchronous accelerator execution when timing work.\n- Load assets and warm models outside measured regions.\n- Report the device, input size, baseline, result, and correctness difference.\n\n## Verification\n\n- Optimize for fast development and iteration. By default, run the smallest relevant check or focused test once using the debug profile.\n- Do not run full test suites, repeatedly rerun unchanged tests or builds, or build and test profiles other than debug unless the user explicitly requests it.\n- Run end-to-end tests only when the user explicitly asks for them.\n- Add a test when it protects a real regression boundary. Do not lock a translated phrase, a language display name, a registration string, or a one-line behavior the owner can read directly. Do not add a second harness for behavior the crate's existing tests already cover. Do not assert a compatibility shim.\n- A UI change needs a screenshot of the affected state. If the bug is truncation, include a long-label case.\n- A model port needs a structured comparison on identical inputs. A green build is not that comparison.\n- A green check is not acceptance. Small bug fixes, documentation, translations, and tests can be opened directly. A new product feature, significant UI change, model or provider integration, platform integration, dependency, public API, schema change, or architectural refactor needs an issue discussion first.\n- Keep the pull-request text short: problem, change, and verification. A human reviews the whole diff and can explain every change. Do not submit an unreviewed autonomous patch.\n\n## Desktop UI Debugging\n\n- Debug builds must expose the CEF remote debugging endpoint at `http://127.0.0.1:4000` through CEF's command-line arguments.\n- Connect `chrome-devtools-mcp` with `--browser-url=http://127.0.0.1:4000` and prefer its tools for WebView inspection and automation. Use semantic targets and observable conditions instead of coordinate-only actions or fixed delays.\n- Use a lower-level CDP client only when `chrome-devtools-mcp` does not expose a required protocol operation. Use native window capture when CDP cannot observe the final WebGPU output.\n\n## Desktop Rendering\n\n- Koharu presents canvas pixels through the `koharu-canvas` WASM module and WebGPU inside the standard Tauri webview. Keep durable scene preparation and export native, keep transient canvas interaction in the browser, and validate WebGPU presentation through the final desktop window.\n\n## Documentation\n\n- Comments should explain ownership, invariants, upstream mapping, or deliberate divergence; do not narrate straightforward code.\n- Keep this file focused on long-lived decision rules rather than the current implementation.\n","isInternal":false,"tokens":1897,"sizeBytes":9885},{"name":"package.json","path":"packages/bridge/package.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/bridge/package.json","title":"@koharu/bridge","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@koharu/bridge\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./canvas\": \"./src/canvas.ts\",\n    \"./protocol\": \"./src/protocol.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src --ignore-pattern src/protocol.ts --ignore-pattern src/wasm\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"dev\": \"nodemon --watch $(npm prefix)/crates/koharu-canvas --watch $(npm prefix)/crates/koharu-rasterizer --ext rs,toml --delay 250ms --on-change-only --exec bun -- run --filter @koharu/bridge build\",\n    \"build\": \"bun x wasm-pack@0.15.0 build $(npm prefix)/crates/koharu-canvas --release --target web --out-dir $(npm prefix)/packages/bridge/src/wasm --out-name koharu_canvas --no-pack\"\n  },\n  \"dependencies\": {\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\"\n  },\n  \"devDependencies\": {\n    \"nodemon\": \"^3.1.14\",\n    \"oxlint\": \"^1.89.0\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n","frontmatter":{"name":"@koharu/bridge","version":"0.1.0","private":true,"license":"MIT OR Apache-2.0","type":"module","exports":{"./canvas":"./src/canvas.ts","./protocol":"./src/protocol.ts"},"scripts":{"lint":"oxlint src --ignore-pattern src/protocol.ts --ignore-pattern src/wasm","typecheck":"tsc --noEmit","dev":"nodemon --watch $(npm prefix)/crates/koharu-canvas --watch $(npm prefix)/crates/koharu-rasterizer --ext rs,toml --delay 250ms --on-change-only --exec bun -- run --filter @koharu/bridge build","build":"bun x wasm-pack@0.15.0 build $(npm prefix)/crates/koharu-canvas --release --target web --out-dir $(npm prefix)/packages/bridge/src/wasm --out-name koharu_canvas --no-pack"},"dependencies":{"@tauri-apps/api":"3.0.0-alpha.3"},"devDependencies":{"nodemon":"^3.1.14","oxlint":"^1.89.0","typescript":"^7.0.2"}},"isInternal":false,"tokens":308,"sizeBytes":918},{"name":"tsconfig.json","path":"packages/bridge/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/bridge/tsconfig.json","title":"Bridge Skill","category":"anthropic-skill","format":"json","content":"# Bridge Skill\n\nPath: `packages/bridge/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/bridge/tsconfig.json)","tokens":300,"sizeBytes":170},{"name":".oxlintrc.json","path":"packages/koharu/.oxlintrc.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/.oxlintrc.json","title":"Koharu Skill","category":"anthropic-skill","format":"json","content":"{\n  \"$schema\": \"../node_modules/oxlint/configuration_schema.json\",\n  \"plugins\": [\"eslint\", \"typescript\", \"unicorn\", \"oxc\", \"react\"],\n  \"categories\": {\n    \"correctness\": \"error\"\n  },\n  \"rules\": {\n    \"react/exhaustive-deps\": \"warn\",\n    \"react/incompatible-library\": \"off\",\n    \"react/refs\": \"off\",\n    \"react/set-state-in-effect\": \"off\",\n    \"react/static-components\": \"off\",\n    \"no-useless-catch\": \"warn\",\n    \"typescript/no-useless-empty-export\": \"warn\",\n    \"unicorn/no-empty-file\": \"warn\",\n    \"unicorn/no-unnecessary-await\": \"warn\",\n    \"unicorn/no-useless-spread\": \"warn\",\n    \"no-unused-vars\": \"warn\",\n    \"unicorn/no-document-cookie\": \"warn\",\n    \"no-useless-rename\": \"warn\",\n    \"unicorn/no-useless-length-check\": \"warn\",\n    \"no-useless-escape\": \"warn\",\n    \"typescript/prefer-as-const\": \"warn\",\n    \"unicorn/no-useless-fallback-in-spread\": \"warn\",\n    \"no-extra-boolean-cast\": \"warn\",\n    \"unicorn/no-new-array\": \"warn\",\n    \"unicorn/prefer-set-size\": \"warn\",\n    \"typescript/no-this-alias\": \"warn\",\n    \"unicorn/prefer-string-starts-ends-with\": \"warn\"\n  },\n  \"ignorePatterns\": [\".next/\", \"out/\", \"dist/\", \"build/\", \"coverage/\", \"lib/api/**/*.msw.ts\"]\n}\n","frontmatter":{"$schema":"../node_modules/oxlint/configuration_schema.json","plugins":["eslint","typescript","unicorn","oxc","react"],"categories":{"correctness":"error"},"rules":{"react/exhaustive-deps":"warn","react/incompatible-library":"off","react/refs":"off","react/set-state-in-effect":"off","react/static-components":"off","no-useless-catch":"warn","typescript/no-useless-empty-export":"warn","unicorn/no-empty-file":"warn","unicorn/no-unnecessary-await":"warn","unicorn/no-useless-spread":"warn","no-unused-vars":"warn","unicorn/no-document-cookie":"warn","no-useless-rename":"warn","unicorn/no-useless-length-check":"warn","no-useless-escape":"warn","typescript/prefer-as-const":"warn","unicorn/no-useless-fallback-in-spread":"warn","no-extra-boolean-cast":"warn","unicorn/no-new-array":"warn","unicorn/prefer-set-size":"warn","typescript/no-this-alias":"warn","unicorn/prefer-string-starts-ends-with":"warn"},"ignorePatterns":[".next/","out/","dist/","build/","coverage/","lib/api/**/*.msw.ts"]},"isInternal":false,"tokens":334,"sizeBytes":1167},{"name":"components.json","path":"packages/koharu/components.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/components.json","title":"Koharu Skill","category":"anthropic-skill","format":"json","content":"{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"../ui/src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"aliases\": {\n    \"components\": \"@/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@/lib\",\n    \"hooks\": \"@/hooks\"\n  },\n  \"registries\": {}\n}\n","frontmatter":{"$schema":"https://ui.shadcn.com/schema.json","style":"base-nova","rsc":true,"tsx":true,"tailwind":{"config":"","css":"../ui/src/styles/globals.css","baseColor":"neutral","cssVariables":true,"prefix":""},"iconLibrary":"lucide","aliases":{"components":"@/components","utils":"@koharu/ui/lib/utils","ui":"@koharu/ui/components","lib":"@/lib","hooks":"@/hooks"},"registries":{}},"isInternal":false,"tokens":151,"sizeBytes":476},{"name":"package.json","path":"packages/koharu/package.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/package.json","title":"@koharu/app","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@koharu/app\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next dev --port 3000\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"lint\": \"oxlint -c .oxlintrc.json\",\n    \"test\": \"vitest run\"\n  },\n  \"dependencies\": {\n    \"@koharu/bridge\": \"workspace:*\",\n    \"@koharu/ui\": \"workspace:*\",\n    \"@sentry/nextjs\": \"^11.8.0\",\n    \"@tanstack/react-query\": \"^5.104.4\",\n    \"@tanstack/react-virtual\": \"^3.14.21\",\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-opener\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-process\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-updater\": \"3.0.0-alpha.3\",\n    \"i18next\": \"^26.5.3\",\n    \"i18next-browser-languagedetector\": \"^8.2.1\",\n    \"i18next-localstorage-backend\": \"^4.3.2\",\n    \"lucide-react\": \"^1.59.0\",\n    \"next\": \"^16.4.2\",\n    \"next-themes\": \"^0.4.6\",\n    \"react\": \"^19.3.1\",\n    \"react-colorful\": \"^5.8.1\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-i18next\": \"^17.1.0\",\n    \"react-markdown\": \"^10.1.0\",\n    \"remark-gfm\": \"^4.0.1\",\n    \"zustand\": \"^5.0.15\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@testing-library/jest-dom\": \"^7.0.1\",\n    \"@testing-library/react\": \"^16.3.3\",\n    \"@testing-library/user-event\": \"^14.6.8\",\n    \"@types/node\": \"^26.6.5\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"@vitejs/plugin-react\": \"^6.1.2\",\n    \"@vitest/ui\": \"^5.0.5\",\n    \"jsdom\": \"^30.1.3\",\n    \"oxlint\": \"^1.89.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\",\n    \"vitest\": \"^5.0.5\"\n  }\n}\n","frontmatter":{"name":"@koharu/app","version":"0.1.0","private":true,"license":"MIT OR Apache-2.0","type":"module","scripts":{"dev":"next dev --port 3000","build":"next build","start":"next start","lint":"oxlint -c .oxlintrc.json","test":"vitest run"},"dependencies":{"@koharu/bridge":"workspace:*","@koharu/ui":"workspace:*","@sentry/nextjs":"^11.8.0","@tanstack/react-query":"^5.104.4","@tanstack/react-virtual":"^3.14.21","@tauri-apps/api":"3.0.0-alpha.3","@tauri-apps/plugin-opener":"3.0.0-alpha.3","@tauri-apps/plugin-process":"3.0.0-alpha.3","@tauri-apps/plugin-updater":"3.0.0-alpha.3","i18next":"^26.5.3","i18next-browser-languagedetector":"^8.2.1","i18next-localstorage-backend":"^4.3.2","lucide-react":"^1.59.0","next":"^16.4.2","next-themes":"^0.4.6","react":"^19.3.1","react-colorful":"^5.8.1","react-dom":"^19.3.0","react-i18next":"^17.1.0","react-markdown":"^10.1.0","remark-gfm":"^4.0.1","zustand":"^5.0.15"},"devDependencies":{"@tailwindcss/postcss":"^4.3.3","@testing-library/jest-dom":"^7.0.1","@testing-library/react":"^16.3.3","@testing-library/user-event":"^14.6.8","@types/node":"^26.6.5","@types/react":"^19.3.0","@types/react-dom":"^19.3.0","@vitejs/plugin-react":"^6.1.2","@vitest/ui":"^5.0.5","jsdom":"^30.1.3","oxlint":"^1.89.0","tailwindcss":"^4.3.3","typescript":"^7.0.2","vitest":"^5.0.5"}},"isInternal":false,"tokens":626,"sizeBytes":1595},{"name":"translation.json","path":"packages/koharu/public/locales/en-US/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/en-US/translation.json","title":"En-US Skill","category":"anthropic-skill","format":"json","content":"# En-US Skill\n\nPath: `packages/koharu/public/locales/en-US/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/en-US/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/es-ES/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/es-ES/translation.json","title":"Es-ES Skill","category":"anthropic-skill","format":"json","content":"# Es-ES Skill\n\nPath: `packages/koharu/public/locales/es-ES/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/es-ES/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/ja-JP/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ja-JP/translation.json","title":"Ja-JP Skill","category":"anthropic-skill","format":"json","content":"# Ja-JP Skill\n\nPath: `packages/koharu/public/locales/ja-JP/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ja-JP/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/ko-KR/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ko-KR/translation.json","title":"Ko-KR Skill","category":"anthropic-skill","format":"json","content":"# Ko-KR Skill\n\nPath: `packages/koharu/public/locales/ko-KR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ko-KR/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/pt-BR/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/pt-BR/translation.json","title":"Pt-BR Skill","category":"anthropic-skill","format":"json","content":"# Pt-BR Skill\n\nPath: `packages/koharu/public/locales/pt-BR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/pt-BR/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/ru-RU/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ru-RU/translation.json","title":"Ru-RU Skill","category":"anthropic-skill","format":"json","content":"# Ru-RU Skill\n\nPath: `packages/koharu/public/locales/ru-RU/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ru-RU/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/tr-TR/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/tr-TR/translation.json","title":"Tr-TR Skill","category":"anthropic-skill","format":"json","content":"# Tr-TR Skill\n\nPath: `packages/koharu/public/locales/tr-TR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/tr-TR/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/zh-CN/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-CN/translation.json","title":"Zh-CN Skill","category":"anthropic-skill","format":"json","content":"# Zh-CN Skill\n\nPath: `packages/koharu/public/locales/zh-CN/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-CN/translation.json)","tokens":300,"sizeBytes":217},{"name":"translation.json","path":"packages/koharu/public/locales/zh-TW/translation.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-TW/translation.json","title":"Zh-TW Skill","category":"anthropic-skill","format":"json","content":"# Zh-TW Skill\n\nPath: `packages/koharu/public/locales/zh-TW/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-TW/translation.json)","tokens":300,"sizeBytes":217},{"name":"tsconfig.json","path":"packages/koharu/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/tsconfig.json","title":"Koharu Skill","category":"anthropic-skill","format":"json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"noImplicitAny\": false,\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"],\n      \"@koharu/ui/*\": [\"../ui/src/*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".next/dev/types/**/*.ts\",\n    \"**/*.mts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n","frontmatter":{"compilerOptions":{"target":"ES2017","lib":["dom","dom.iterable","esnext"],"noImplicitAny":false,"allowJs":true,"skipLibCheck":true,"strict":true,"noEmit":true,"esModuleInterop":true,"module":"esnext","moduleResolution":"bundler","resolveJsonModule":true,"isolatedModules":true,"jsx":"react-jsx","incremental":true,"plugins":[{"name":"next"}],"paths":{"@/*":["./*"],"@koharu/ui/*":["../ui/src/*"]}},"include":["next-env.d.ts","**/*.ts","**/*.tsx",".next/types/**/*.ts",".next/dev/types/**/*.ts","**/*.mts"],"exclude":["node_modules"]},"isInternal":false,"tokens":227,"sizeBytes":733},{"name":"components.json","path":"packages/ui/components.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/ui/components.json","title":"Ui Skill","category":"anthropic-skill","format":"json","content":"{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"menuAccent\": \"subtle\",\n  \"menuColor\": \"default-translucent\",\n  \"aliases\": {\n    \"components\": \"@koharu/ui/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@koharu/ui/lib\",\n    \"hooks\": \"@koharu/ui/hooks\"\n  },\n  \"registries\": {}\n}\n","frontmatter":{"$schema":"https://ui.shadcn.com/schema.json","style":"base-nova","rsc":true,"tsx":true,"tailwind":{"config":"","css":"src/styles/globals.css","baseColor":"neutral","cssVariables":true,"prefix":""},"iconLibrary":"lucide","menuAccent":"subtle","menuColor":"default-translucent","aliases":{"components":"@koharu/ui/components","utils":"@koharu/ui/lib/utils","ui":"@koharu/ui/components","lib":"@koharu/ui/lib","hooks":"@koharu/ui/hooks"},"registries":{}},"isInternal":false,"tokens":181,"sizeBytes":561},{"name":"package.json","path":"packages/ui/package.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/ui/package.json","title":"@koharu/ui","category":"anthropic-skill","format":"json","content":"{\n  \"name\": \"@koharu/ui\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./globals.css\": \"./src/styles/globals.css\",\n    \"./components/*\": \"./src/components/*.tsx\",\n    \"./lib/*\": \"./src/lib/*.ts\",\n    \"./hooks/*\": \"./src/hooks/*.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"shadcn\": \"shadcn add --all --overwrite --yes\"\n  },\n  \"dependencies\": {\n    \"@base-ui/react\": \"^1.9.0\",\n    \"@shadcn/react\": \"^0.3.1\",\n    \"class-variance-authority\": \"^0.7.1\",\n    \"clsx\": \"^2.1.1\",\n    \"cmdk\": \"^1.1.1\",\n    \"date-fns\": \"^4.4.0\",\n    \"embla-carousel-react\": \"^8.6.0\",\n    \"input-otp\": \"^1.5.0\",\n    \"lucide-react\": \"^1.59.0\",\n    \"react\": \"^19.3.1\",\n    \"react-day-picker\": \"^10.0.2\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-resizable-panels\": \"^4.14.5\",\n    \"recharts\": \"3.10.1\",\n    \"tailwind-merge\": \"^3.7.0\",\n    \"tw-animate-css\": \"^1.4.0\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"oxlint\": \"^1.89.0\",\n    \"shadcn\": \"^4.22.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n","frontmatter":{"name":"@koharu/ui","version":"0.0.0","private":true,"license":"MIT OR Apache-2.0","type":"module","exports":{"./globals.css":"./src/styles/globals.css","./components/*":"./src/components/*.tsx","./lib/*":"./src/lib/*.ts","./hooks/*":"./src/hooks/*.ts"},"scripts":{"lint":"oxlint src","typecheck":"tsc --noEmit","shadcn":"shadcn add --all --overwrite --yes"},"dependencies":{"@base-ui/react":"^1.9.0","@shadcn/react":"^0.3.1","class-variance-authority":"^0.7.1","clsx":"^2.1.1","cmdk":"^1.1.1","date-fns":"^4.4.0","embla-carousel-react":"^8.6.0","input-otp":"^1.5.0","lucide-react":"^1.59.0","react":"^19.3.1","react-day-picker":"^10.0.2","react-dom":"^19.3.0","react-resizable-panels":"^4.14.5","recharts":"3.10.1","tailwind-merge":"^3.7.0","tw-animate-css":"^1.4.0"},"devDependencies":{"@tailwindcss/postcss":"^4.3.3","@types/react":"^19.3.0","@types/react-dom":"^19.3.0","oxlint":"^1.89.0","shadcn":"^4.22.0","tailwindcss":"^4.3.3","typescript":"^7.0.2"}},"isInternal":false,"tokens":462,"sizeBytes":1189},{"name":"tsconfig.json","path":"packages/ui/tsconfig.json","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/ui/tsconfig.json","title":"Ui Skill","category":"anthropic-skill","format":"json","content":"{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"paths\": {\n      \"@koharu/ui/*\": [\"./src/*\"]\n    }\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"]\n}\n","frontmatter":{"compilerOptions":{"target":"ES2017","lib":["dom","dom.iterable","esnext"],"skipLibCheck":true,"strict":true,"noEmit":true,"esModuleInterop":true,"module":"esnext","moduleResolution":"bundler","isolatedModules":true,"jsx":"react-jsx","paths":{"@koharu/ui/*":["./src/*"]}},"include":["src/**/*.ts","src/**/*.tsx"]},"isInternal":false,"tokens":132,"sizeBytes":409},{"name":"README.md","path":"packages/bridge/README.md","rawUrl":"https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/bridge/README.md","title":"bridge Documentation","category":"plugin-manifest","format":"markdown","content":"# @koharu/bridge\n\nThis package owns Koharu's browser/native boundary:\n\n- `src/protocol.ts` is generated from the Rust Tauri command surface;\n- `src/canvas.ts` adapts that protocol and `koharu-canvas` to the browser;\n- `src/wasm` is ignored derived output produced by `wasm-pack`.\n\nThe bridge package builds only its WASM output. The root frontend tasks sequence that build before starting or building the consuming Next.js app. During development, `nodemon` rebuilds the bridge when `koharu-canvas` or `koharu-rasterizer` changes. `npm prefix` supplies the absolute workspace root directly to the package commands, so they do not depend on parent traversal or shell environment variables. Because the generated glue is imported from this package, Next.js includes it in the Turbopack module graph and refreshes the client after a successful rebuild.\n\nRegenerate the protocol with `cargo run -p koharu-app --bin generate`. Do not edit generated protocol or WASM output by hand.\n","isInternal":false,"tokens":223,"sizeBytes":977}],"systemPromptSnippet":"<yakaai_skills repo=\"mayocream/koharu\">\n<!-- File: AGENTS.md (Tokens: ~1897 | Category: root-instruction) -->\n# Koharu Project Rules\n\nDocument only durable, repository-specific constraints here. Do not record current file layouts, temporary paths, model inventories, helper names, or other implementation details that may change during a refactor. Normal Rust, TypeScript, testing, formatting, and Git practices are assumed.\n\n## Change Policy\n\n- Never add backward compatibility. When an API, schema, configuration, or ownership boundary changes, update every in-repository consumer and remove the replaced form.\n- Prefer a coherent ownership redesign over aliases, forwarding layers, compatibility parsers, or cosmetic renaming.\n- Keep responsibilities self-contained. Defaults and provider-specific behavior belong to the component that owns them rather than a central list of special cases.\n- Remove dead abstractions and one-use helpers when direct code is clearer.\n- Make the smallest change that solves the problem. Do not edit unrelated configuration, documentation, generated files, or workflows in the same change. A feature does not land beside drive-by cleanup.\n- If the current owner has moved, rebase onto that owner. Do not port a patch onto a deleted tree.\n- When two changes implement the same workflow, keep one and extend the existing command or configuration. Do not land both.\n- For editor behavior that is not already specified, match Photoshop or Clip Studio Paint. Prefer an in-app edit over an export/import round trip when the task is ordinary editing.\n- Desktop API keys go through the OS credential store. Do not add a project environment-file fallback for the desktop app.\n- Once a subsystem is removed, delete its calls and dependency together. Do not leave a stub, alias, or disabled flag behind.\n\n## Ownership\n\n- The UI invokes typed commands. Native code owns durable project state and processing. Do not add an HTTP client or a generic event envelope.\n- Scene owns what a project means. Storage owns opaque payloads and immutable blobs. Analysis, content, and presentation stay separate: detection geometry is not a visible layer, translation does not drop OCR provenance, and typography does not rewrite semantic text.\n- A patch binds to a project and a base revision, records preconditions, and carries inverses. Reject a stale patch. Derived work rebases explicitly and fails if anything it observed has changed.\n- Publish missing blobs first, write the inactive state slot, then publish atomically. Opening uses the newest valid slot and can fall back. Renderer, pipeline, and Agent consume snapshots and submit patches. They do not write storage files.\n- A pipeline stage runs on one page: detection, then OCR and translation, or detection, then inpainting. Pages enter in project order. Completed detection makes that page's later stages eligible immediately. At most one job per stage runs at a time. Each committed result is its own undo step. Do not add a second translation prompt path.\n- Accelerator inference uses one admission lane, including remote translation. On out-of-memory, release the lane, unload the other models, wait for a fresh resource sample, and retry once. Any other failure unloads the failing stage. Stopping is cooperative and discards an uncommitted result.\n- One prepared frame feeds presentation, PNG, layer crops, and PSD. Translation is the only visible text. Incremental reuse must match a full render. The previous page stays visible until the staged generation is ready. An obsolete preparation cannot replace a newer generation. Transient camera, transform, stroke, and sampling stay in the browser. Completed edits cross commands.\n\n## Interface\n\n- User-visible strings go through the translation function and the locale files. Hardcoded English in a translated surface is incomplete.\n- An interface language's display name is that language's own name in every locale. Do not translate it into the surrounding locale.\n- The translation-target language list stays in the active UI language. Drop a country name unless the entry is a real variant.\n- Do not duplicate status the current selection already implies. Do not add a second job kind, cancel path, or counter for an operation the existing command already covers.\n- Use the existing control library for standard interaction. Commit on selection or an uncanceled drop, not on focus or hover. Ignore a canceled drag. Do not let a shortcut steal keys from a focused control.\n- Reuse the existing numeric color and typography representation. Do not introduce a parallel string format.\n- A page switch uses the existing selection and optimistic cache update. Do not add a second navigation path that leaves the rail, layer selection, or query data behind.\n\n## Source Boundaries\n\n- Keep safe public APIs separate from unsafe FFI, dynamic loading, and build integration.\n- Do not hand-edit generated or derived source. Change its authoritative input and run the generator.\n- Do not commit credentials, model weights, datasets, generated outputs, or machine-specific artifacts.\n- Native llama.cpp and diffusion runtimes come from prebuilt packages. Do not compile those CUDA trees inside the app build. Release and publish jobs do a fresh build.\n- Hardware discovery stays separate from managed runtime package activation. Do not load a cached accelerator runtime during the probe.\n- Error sampling is off in debug builds and on in release builds.\n\n## ML Architecture\n\n- Keep a consistent public lifecycle across models while allowing model-specific inputs and outputs.\n- Separate network ownership and weight loading from preprocessing, postprocessing, slicing, and public result types.\n- Avoid pass-through types and layers that do not own a real responsibility.\n- Accept a device abstraction at the model boundary, convert it once, and avoid unnecessary transfers or synchronization.\n- Use the established runtime and variable-store loading paths unless they are proven insufficient.\n- Disable gradient tracking during inference.\n- Create generated token IDs and index tensors on the model device. A CPU tensor used against accelerator embeddings is a defect, not a later optimization.\n- Invalid model JSON fails closed. Do not add a silent repair layer that can change meaning.\n- Enforce a translation output schema through each provider's native structured-output API. A bounded retry belongs only to a provider that already has one. Hosted machine-translation providers fail immediately.\n\n## Upstream Alignment\n\n- Keep ports structurally traceable to a commit-pinned authoritative implementation.\n- Preserve checkpoint-affecting names, construction order, parameter paths, tensor layouts, execution order, and postprocessing semantics.\n- Treat missing or unexpected weights as an architecture or parameter-name mismatch before changing the loader.\n- Explain intentional divergences next to the affected code.\n- Compare ports on identical inputs using structured outputs such as shapes, ranges, boxes, scores, masks, and ordering.\n\n## Performance\n\n- Optimize and benchmark the actual target device with representative inputs.\n- Remove redundant transfers, synchronization, allocations, and per-pixel host loops before adding concurrency or caching.\n- Account for asynchronous accelerator execution when timing work.\n- Load assets and warm models outside measured regions.\n- Report the device, input size, baseline, result, and correctness difference.\n\n## Verification\n\n- Optimize for fast development and iteration. By default, run the smallest relevant check or focused test once using the debug profile.\n- Do not run full test suites, repeatedly rerun unchanged tests or builds, or build and test profiles other than debug unless the user explicitly requests it.\n- Run end-to-end tests only when the user explicitly asks for them.\n- Add a test when it protects a real regression boundary. Do not lock a translated phrase, a language display name, a registration string, or a one-line behavior the owner can read directly. Do not add a second harness for behavior the crate's existing tests already cover. Do not assert a compatibility shim.\n- A UI change needs a screenshot of the affected state. If the bug is truncation, include a long-label case.\n- A model port needs a structured comparison on identical inputs. A green build is not that comparison.\n- A green check is not acceptance. Small bug fixes, documentation, translations, and tests can be opened directly. A new product feature, significant UI change, model or provider integration, platform integration, dependency, public API, schema change, or architectural refactor needs an issue discussion first.\n- Keep the pull-request text short: problem, change, and verification. A human reviews the whole diff and can explain every change. Do not submit an unreviewed autonomous patch.\n\n## Desktop UI Debugging\n\n- Debug builds must expose the CEF remote debugging endpoint at `http://127.0.0.1:4000` through CEF's command-line arguments.\n- Connect `chrome-devtools-mcp` with `--browser-url=http://127.0.0.1:4000` and prefer its tools for WebView inspection and automation. Use semantic targets and observable conditions instead of coordinate-only actions or fixed delays.\n- Use a lower-level CDP client only when `chrome-devtools-mcp` does not expose a required protocol operation. Use native window capture when CDP cannot observe the final WebGPU output.\n\n## Desktop Rendering\n\n- Koharu presents canvas pixels through the `koharu-canvas` WASM module and WebGPU inside the standard Tauri webview. Keep durable scene preparation and export native, keep transient canvas interaction in the browser, and validate WebGPU presentation through the final desktop window.\n\n## Documentation\n\n- Comments should explain ownership, invariants, upstream mapping, or deliberate divergence; do not narrate straightforward code.\n- Keep this file focused on long-lived decision rules rather than the current implementation.\n\n<!-- File: packages/bridge/package.json (Tokens: ~308 | Category: anthropic-skill) -->\n{\n  \"name\": \"@koharu/bridge\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./canvas\": \"./src/canvas.ts\",\n    \"./protocol\": \"./src/protocol.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src --ignore-pattern src/protocol.ts --ignore-pattern src/wasm\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"dev\": \"nodemon --watch $(npm prefix)/crates/koharu-canvas --watch $(npm prefix)/crates/koharu-rasterizer --ext rs,toml --delay 250ms --on-change-only --exec bun -- run --filter @koharu/bridge build\",\n    \"build\": \"bun x wasm-pack@0.15.0 build $(npm prefix)/crates/koharu-canvas --release --target web --out-dir $(npm prefix)/packages/bridge/src/wasm --out-name koharu_canvas --no-pack\"\n  },\n  \"dependencies\": {\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\"\n  },\n  \"devDependencies\": {\n    \"nodemon\": \"^3.1.14\",\n    \"oxlint\": \"^1.89.0\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n\n<!-- File: packages/bridge/tsconfig.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Bridge Skill\n\nPath: `packages/bridge/tsconfig.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/bridge/tsconfig.json)\n\n<!-- File: packages/koharu/.oxlintrc.json (Tokens: ~334 | Category: anthropic-skill) -->\n{\n  \"$schema\": \"../node_modules/oxlint/configuration_schema.json\",\n  \"plugins\": [\"eslint\", \"typescript\", \"unicorn\", \"oxc\", \"react\"],\n  \"categories\": {\n    \"correctness\": \"error\"\n  },\n  \"rules\": {\n    \"react/exhaustive-deps\": \"warn\",\n    \"react/incompatible-library\": \"off\",\n    \"react/refs\": \"off\",\n    \"react/set-state-in-effect\": \"off\",\n    \"react/static-components\": \"off\",\n    \"no-useless-catch\": \"warn\",\n    \"typescript/no-useless-empty-export\": \"warn\",\n    \"unicorn/no-empty-file\": \"warn\",\n    \"unicorn/no-unnecessary-await\": \"warn\",\n    \"unicorn/no-useless-spread\": \"warn\",\n    \"no-unused-vars\": \"warn\",\n    \"unicorn/no-document-cookie\": \"warn\",\n    \"no-useless-rename\": \"warn\",\n    \"unicorn/no-useless-length-check\": \"warn\",\n    \"no-useless-escape\": \"warn\",\n    \"typescript/prefer-as-const\": \"warn\",\n    \"unicorn/no-useless-fallback-in-spread\": \"warn\",\n    \"no-extra-boolean-cast\": \"warn\",\n    \"unicorn/no-new-array\": \"warn\",\n    \"unicorn/prefer-set-size\": \"warn\",\n    \"typescript/no-this-alias\": \"warn\",\n    \"unicorn/prefer-string-starts-ends-with\": \"warn\"\n  },\n  \"ignorePatterns\": [\".next/\", \"out/\", \"dist/\", \"build/\", \"coverage/\", \"lib/api/**/*.msw.ts\"]\n}\n\n<!-- File: packages/koharu/components.json (Tokens: ~151 | Category: anthropic-skill) -->\n{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"../ui/src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"aliases\": {\n    \"components\": \"@/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@/lib\",\n    \"hooks\": \"@/hooks\"\n  },\n  \"registries\": {}\n}\n\n<!-- File: packages/koharu/package.json (Tokens: ~626 | Category: anthropic-skill) -->\n{\n  \"name\": \"@koharu/app\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"next dev --port 3000\",\n    \"build\": \"next build\",\n    \"start\": \"next start\",\n    \"lint\": \"oxlint -c .oxlintrc.json\",\n    \"test\": \"vitest run\"\n  },\n  \"dependencies\": {\n    \"@koharu/bridge\": \"workspace:*\",\n    \"@koharu/ui\": \"workspace:*\",\n    \"@sentry/nextjs\": \"^11.8.0\",\n    \"@tanstack/react-query\": \"^5.104.4\",\n    \"@tanstack/react-virtual\": \"^3.14.21\",\n    \"@tauri-apps/api\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-opener\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-process\": \"3.0.0-alpha.3\",\n    \"@tauri-apps/plugin-updater\": \"3.0.0-alpha.3\",\n    \"i18next\": \"^26.5.3\",\n    \"i18next-browser-languagedetector\": \"^8.2.1\",\n    \"i18next-localstorage-backend\": \"^4.3.2\",\n    \"lucide-react\": \"^1.59.0\",\n    \"next\": \"^16.4.2\",\n    \"next-themes\": \"^0.4.6\",\n    \"react\": \"^19.3.1\",\n    \"react-colorful\": \"^5.8.1\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-i18next\": \"^17.1.0\",\n    \"react-markdown\": \"^10.1.0\",\n    \"remark-gfm\": \"^4.0.1\",\n    \"zustand\": \"^5.0.15\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@testing-library/jest-dom\": \"^7.0.1\",\n    \"@testing-library/react\": \"^16.3.3\",\n    \"@testing-library/user-event\": \"^14.6.8\",\n    \"@types/node\": \"^26.6.5\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"@vitejs/plugin-react\": \"^6.1.2\",\n    \"@vitest/ui\": \"^5.0.5\",\n    \"jsdom\": \"^30.1.3\",\n    \"oxlint\": \"^1.89.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\",\n    \"vitest\": \"^5.0.5\"\n  }\n}\n\n<!-- File: packages/koharu/public/locales/en-US/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# En-US Skill\n\nPath: `packages/koharu/public/locales/en-US/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/en-US/translation.json)\n\n<!-- File: packages/koharu/public/locales/es-ES/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Es-ES Skill\n\nPath: `packages/koharu/public/locales/es-ES/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/es-ES/translation.json)\n\n<!-- File: packages/koharu/public/locales/ja-JP/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Ja-JP Skill\n\nPath: `packages/koharu/public/locales/ja-JP/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ja-JP/translation.json)\n\n<!-- File: packages/koharu/public/locales/ko-KR/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Ko-KR Skill\n\nPath: `packages/koharu/public/locales/ko-KR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ko-KR/translation.json)\n\n<!-- File: packages/koharu/public/locales/pt-BR/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Pt-BR Skill\n\nPath: `packages/koharu/public/locales/pt-BR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/pt-BR/translation.json)\n\n<!-- File: packages/koharu/public/locales/ru-RU/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Ru-RU Skill\n\nPath: `packages/koharu/public/locales/ru-RU/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/ru-RU/translation.json)\n\n<!-- File: packages/koharu/public/locales/tr-TR/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Tr-TR Skill\n\nPath: `packages/koharu/public/locales/tr-TR/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/tr-TR/translation.json)\n\n<!-- File: packages/koharu/public/locales/zh-CN/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Zh-CN Skill\n\nPath: `packages/koharu/public/locales/zh-CN/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-CN/translation.json)\n\n<!-- File: packages/koharu/public/locales/zh-TW/translation.json (Tokens: ~300 | Category: anthropic-skill) -->\n# Zh-TW Skill\n\nPath: `packages/koharu/public/locales/zh-TW/translation.json`\n\n[View Raw Content on GitHub](https://raw.githubusercontent.com/mayocream/koharu/HEAD/packages/koharu/public/locales/zh-TW/translation.json)\n\n<!-- File: packages/koharu/tsconfig.json (Tokens: ~227 | Category: anthropic-skill) -->\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"noImplicitAny\": false,\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"incremental\": true,\n    \"plugins\": [\n      {\n        \"name\": \"next\"\n      }\n    ],\n    \"paths\": {\n      \"@/*\": [\"./*\"],\n      \"@koharu/ui/*\": [\"../ui/src/*\"]\n    }\n  },\n  \"include\": [\n    \"next-env.d.ts\",\n    \"**/*.ts\",\n    \"**/*.tsx\",\n    \".next/types/**/*.ts\",\n    \".next/dev/types/**/*.ts\",\n    \"**/*.mts\"\n  ],\n  \"exclude\": [\"node_modules\"]\n}\n\n<!-- File: packages/ui/components.json (Tokens: ~181 | Category: anthropic-skill) -->\n{\n  \"$schema\": \"https://ui.shadcn.com/schema.json\",\n  \"style\": \"base-nova\",\n  \"rsc\": true,\n  \"tsx\": true,\n  \"tailwind\": {\n    \"config\": \"\",\n    \"css\": \"src/styles/globals.css\",\n    \"baseColor\": \"neutral\",\n    \"cssVariables\": true,\n    \"prefix\": \"\"\n  },\n  \"iconLibrary\": \"lucide\",\n  \"menuAccent\": \"subtle\",\n  \"menuColor\": \"default-translucent\",\n  \"aliases\": {\n    \"components\": \"@koharu/ui/components\",\n    \"utils\": \"@koharu/ui/lib/utils\",\n    \"ui\": \"@koharu/ui/components\",\n    \"lib\": \"@koharu/ui/lib\",\n    \"hooks\": \"@koharu/ui/hooks\"\n  },\n  \"registries\": {}\n}\n\n<!-- File: packages/ui/package.json (Tokens: ~462 | Category: anthropic-skill) -->\n{\n  \"name\": \"@koharu/ui\",\n  \"version\": \"0.0.0\",\n  \"private\": true,\n  \"license\": \"MIT OR Apache-2.0\",\n  \"type\": \"module\",\n  \"exports\": {\n    \"./globals.css\": \"./src/styles/globals.css\",\n    \"./components/*\": \"./src/components/*.tsx\",\n    \"./lib/*\": \"./src/lib/*.ts\",\n    \"./hooks/*\": \"./src/hooks/*.ts\"\n  },\n  \"scripts\": {\n    \"lint\": \"oxlint src\",\n    \"typecheck\": \"tsc --noEmit\",\n    \"shadcn\": \"shadcn add --all --overwrite --yes\"\n  },\n  \"dependencies\": {\n    \"@base-ui/react\": \"^1.9.0\",\n    \"@shadcn/react\": \"^0.3.1\",\n    \"class-variance-authority\": \"^0.7.1\",\n    \"clsx\": \"^2.1.1\",\n    \"cmdk\": \"^1.1.1\",\n    \"date-fns\": \"^4.4.0\",\n    \"embla-carousel-react\": \"^8.6.0\",\n    \"input-otp\": \"^1.5.0\",\n    \"lucide-react\": \"^1.59.0\",\n    \"react\": \"^19.3.1\",\n    \"react-day-picker\": \"^10.0.2\",\n    \"react-dom\": \"^19.3.0\",\n    \"react-resizable-panels\": \"^4.14.5\",\n    \"recharts\": \"3.10.1\",\n    \"tailwind-merge\": \"^3.7.0\",\n    \"tw-animate-css\": \"^1.4.0\"\n  },\n  \"devDependencies\": {\n    \"@tailwindcss/postcss\": \"^4.3.3\",\n    \"@types/react\": \"^19.3.0\",\n    \"@types/react-dom\": \"^19.3.0\",\n    \"oxlint\": \"^1.89.0\",\n    \"shadcn\": \"^4.22.0\",\n    \"tailwindcss\": \"^4.3.3\",\n    \"typescript\": \"^7.0.2\"\n  }\n}\n\n<!-- File: packages/ui/tsconfig.json (Tokens: ~132 | Category: anthropic-skill) -->\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2017\",\n    \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n    \"skipLibCheck\": true,\n    \"strict\": true,\n    \"noEmit\": true,\n    \"esModuleInterop\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"isolatedModules\": true,\n    \"jsx\": \"react-jsx\",\n    \"paths\": {\n      \"@koharu/ui/*\": [\"./src/*\"]\n    }\n  },\n  \"include\": [\"src/**/*.ts\", \"src/**/*.tsx\"]\n}\n\n<!-- File: packages/bridge/README.md (Tokens: ~223 | Category: plugin-manifest) -->\n# @koharu/bridge\n\nThis package owns Koharu's browser/native boundary:\n\n- `src/protocol.ts` is generated from the Rust Tauri command surface;\n- `src/canvas.ts` adapts that protocol and `koharu-canvas` to the browser;\n- `src/wasm` is ignored derived output produced by `wasm-pack`.\n\nThe bridge package builds only its WASM output. The root frontend tasks sequence that build before starting or building the consuming Next.js app. During development, `nodemon` rebuilds the bridge when `koharu-canvas` or `koharu-rasterizer` changes. `npm prefix` supplies the absolute workspace root directly to the package commands, so they do not depend on parent traversal or shell environment variables. Because the generated glue is imported from this package, Next.js includes it in the Turbopack module graph and refreshes the client after a successful rebuild.\n\nRegenerate the protocol with `cargo run -p koharu-app --bin generate`. Do not edit generated protocol or WASM output by hand.\n</yakaai_skills>"}