14 KiB
Project AIRI Agent Guide
This file gives the core rules for all work in the moeru-ai/airi monorepo. Skills and nested AGENTS.md files give the rules for specific tasks. Before you start a task, find it in Task Routing and read the listed file.
Project Map
All apps use Vue 3, Vite, TypeScript, Pinia, VueUse, UnoCSS, Vitest, and ESLint.
| Path | Content |
|---|---|
apps/stage-web |
The web app. It uses Vue Router. |
apps/stage-tamagotchi |
The Electron desktop app. |
apps/stage-pocket |
The mobile app. It uses Vue Router, Capacitor, Kotlin, and Swift. |
packages/stage-ui |
Business components, composables, and stores that stage-web and stage-tamagotchi share. |
packages/stage-ui-three |
Three.js bindings and Vue components. |
packages/stage-shared |
Logic that the stage packages and the stage apps share. |
packages/stage-pages |
Shared page bases. |
packages/stage-layouts |
Shared layouts, including the stage-web settings layout. |
packages/ui |
Primitives built on reka-ui, such as inputs, buttons, and layout. They have minimal business logic. |
packages/i18n |
All translations. |
packages/server-runtime, packages/server-sdk, packages/server-shared |
The server channel that services/ and plugins/ use. |
server/apps/api |
The hosted Hono resource API and its business domains. |
server/apps/auth |
The standalone Better Auth and OIDC service. |
server/packages |
Backend-only schema and Node infrastructure packages. |
server/dev/caddy |
Local Auth and API edge routing. |
server/docker-compose.yaml |
The complete local backend stack. |
Key files and directories:
- Pages are in
apps/stage-web/src/pagesandapps/stage-tamagotchi/src/renderer/pages. Devtools pages are in thedevtoolsfolder of each. - The router configuration is in
apps/stage-web/vite.config.tsandapps/stage-tamagotchi/electron.vite.config.ts. - The settings layouts are
packages/stage-layouts/src/layouts/settings.vue(stage-web) andapps/stage-tamagotchi/src/renderer/layouts/settings.vue. - A settings or devtools page needs
<route lang="yaml"> meta: layout: settings </route>. Register its route and icon in the settings layout. - In
packages/stage-ui/src, provider definitions are instores/providers/and orchestration modules are instores/modules/. - Business composables are in
packages/stage-ui/src/composables/. Business components are inpackages/stage-ui/src/components/. - Put a component for one page or one use case in
packages/stage-ui/src/components/scenarios/. - Stories are in
packages/stage-ui/stories, withpackages/stage-ui/histoire.config.ts. An example ispackages/stage-ui/src/components/misc/Button.story.vue. - Eventa contracts are in
apps/stage-tamagotchi/src/shared. Main and renderer usage examples are inapps/stage-tamagotchi/src/main/services/electron. - The dependency injection example is
apps/stage-tamagotchi/src/main/index.ts. - Style configuration is in
uno.config.ts. Existing animations are inapps/stage-web/src/styles. - CI pipelines are in
.github/workflows. Lint rules are ineslint.config.ts.
Commands
Use pnpm workspace filters to limit a command to one workspace. Replace <package name> with the name field in package.json, for example @proj-airi/stage-tamagotchi.
-
Typecheck one workspace:
pnpm -F <package name> typecheck. For stage-tamagotchi, this command runstscandvue-tsc. -
Test one file:
pnpm -F <package name> exec vitest run <path>. Give<path>relative to the workspace. -
Test one workspace:
pnpm -F <package name> exec vitest run. -
Test all workspaces:
pnpm test:run. Turbo runs thetest:runscript of each workspace, with its browser projects. -
Test the root scripts in
.github/scripts:pnpm test:root. The rootvitest.config.tshas only these tests. -
Test the changes of a branch: run the
test:runscript of each changed workspace and of each workspace that depends on it. Use the merge base withorigin/mainas the base.base=$(git merge-base origin/main HEAD) TURBO_SCM_BASE="$base" pnpm exec turbo run test:run --affectedIf the branch changes
.github/scripts, also runpnpm test:root. -
Lint:
pnpm lint. ESLint also does the formatting. To fix lint and format errors, runpnpm lint:fix. -
Build one workspace:
pnpm -F <package name> build. For stage-tamagotchi, this command runs the typecheck andelectron-vite build.
Scope and Checks
- Keep each change inside the scope of the task.
- In each function, component, or test that you change, correct the code that does not obey a current rule. Do not change other code only to improve it.
- Do not add one-off patterns. Before you write a new utility or function, search for an existing internal implementation.
- If new logic can become a shared utility, propose the shared approach to the user.
- If a refactor is small, do it step by step.
- After a task, run the typecheck and the related tests for each workspace that you changed.
- Before you create a PR or push to one, run the tests of the branch changes. CI runs every project, including the browser projects.
- If a change alters UI structure, layout, or interaction, review the related browser and end-to-end tests.
- If intended behavior changes, update the affected assertions. Keep valid regression checks. Do not delete an assertion only to make a test pass.
- After the final UI change, run the related tests on the final commit.
- Before you report a CI success, make sure that CI tested the current PR head.
- If you change a shared package or an exported type, also run the root
pnpm typecheck. - Run
pnpm lintbefore you finish. - Report only the checks that you ran. Give each command and its result.
- At the end, summarize the changes, the commands that you ran, and the follow-up work.
Code Rules
-
Put shared logic in
packages/. Keep module boundaries clear. -
Use kebab-case for all file names.
-
Do not use
any. Prefer type generics. Useas unknown as <Type>only when you cannot fix the type safely. -
Omit TypeScript and JavaScript source extensions in relative imports, dynamic imports, and re-exports. Write
./module, not./module.tsor./module.js. Keep an extension only when the runtime or asset format requires it. -
Do not edit
tsconfig.jsonto hide an import or type error. Find and fix the cause. -
Treat a circular import as a design problem. First reconsider ownership and module boundaries. If you cannot resolve the cycle confidently, ask the user.
-
Use
@moeru/eventafor all IPC, RPC, and cross-process events. Define the contracts in one central place, such asapps/stage-tamagotchi/src/shared. -
Use dependency injection only at external boundaries: databases, model runtimes, queues, caches, filesystems, networks, clocks, environments, and feature gates. Use
injecafor it. -
Do not add dependency objects for internal functions that only call sibling helpers or forward parameters.
-
Prefer classes for runtime or browser APIs. Also prefer classes for substantial business modules that own state, lifecycle, or a stable domain boundary.
-
Prefer functions for pure transformations and local helpers.
-
Use Valibot for schema validation. Keep each schema near its consumers.
-
Use
errorMessageFrom(error)from@moeru/stdto get an error message. Add?? 'fallback'when you need a default. For other error handling, prefer the@moeru/stdpatterns. -
Mark every workaround with a
// NOTICE:comment in this format:// NOTICE: // Why this workaround is needed. // Root cause summary. // Source/context (file, issue, URL, or node_modules reference). // Removal condition (when it can be safely deleted).
Backward Compatibility
- Do not add backward-compatibility guards.
- If old callers or old data need extended support, write a refactor document with the target shape. Then start another Codex or Claude Code session from the shell to do the refactor.
- If a compatibility fallback must stay for a limited time, mark it with
// NOTICE:and give its removal condition. - If a compatibility fallback is permanent, document it as supported policy. Do not call it legacy.
- A nested
AGENTS.mdcan override this rule for a public contract. It must name the root rule that it overrides.
Dependencies
- Prefer
es-toolkitfor general utilities. Ask the user before you add another general utility library, such as a package fromunjsortinylib. - Some features use
node:*built-in modules, DOM operations, Vue composables, React hooks, Vite plugins, or GitHub Actions workflows. For these features, research existing libraries first. - Before you choose a library, ask the user to choose. Help the user compare the options.
- If the user works spec-driven, list the candidate libraries in a Markdown comparison table.
- If the user asks you to use a specific tool or dependency, read its documentation in Context7 first. Then examine how this repository uses it.
- If Context7 returns several names without a clear difference, ask the user to choose one.
- If the documentation conflicts with the typecheck result, examine the dependency source in
node_modulesto find the cause.
Documentation
- Put project-wide and client ADRs in
docs/ai/adr/. Put hosted backend ADRs inserver/docs/ai/adr/, and obey the ADR rules inserver/AGENTS.md. - Put a documentation change in the same commit or PR as the code that it describes. This rule applies to ADRs,
README.mdfiles, and component references. - Put agent configuration changes in their own commit. Agent configuration includes
AGENTS.md,CLAUDE.md, skills, and.github/copilot-instructions.md. - If the agent configuration describes the code of a PR, put its commit in that PR. Do not open a second PR for it.
- Keep a structured
README.mdin eachpackages/andapps/entry. It tells what the entry does, how to use it, when to use it, and when not to use it. - Put all translations in
packages/i18n. By default, edit only the English source locale and your own locale. - Do not edit other locales unless the user asks. Crowdin manages them, and the next Crowdin sync can replace local edits.
- Do not use English text as a placeholder in other locales. Add only the locales you implement.
- When you add a nested
AGENTS.md, add aCLAUDE.mdnext to it that contains only@AGENTS.md. The rootCLAUDE.mdstops Claude Code from reading a nestedAGENTS.mdwithout this file.
Writing
- For text, obey the
simple-englishskill. Text includes documentation, code comments, commit messages, and PR and issue text. - Do not apply the skill to code, identifiers, commands, or quoted errors.
- This repository breaks these rules most often:
- Do not write "should", "may", "might", "could", or "would". Write "must" or "can", or state the fact.
- Do not use semicolons. Write two sentences.
- Write "for example" and "that is". Do not write "e.g.", "i.e.", or "etc.".
- Write an instruction in 20 words or fewer. Write a description in 25 words or fewer.
- Put a condition before its command.
Git and Pull Requests
- Use Conventional Commits, for example
feat(<package name>): add runner reconnect backoff. Do not use gitmoji. - Name branches
username/feat/short-name. - Rebase when you pull.
- To create, open, publish, or prepare a pull request, use the
create-prskill. It also covers visual evidence and review follow-up.
Task Routing
Skills are in .agents/skills/<name>/SKILL.md. Read the listed file before you start the task.
| Task | Read |
|---|---|
| Design, change, or review UI appearance and interaction | AIRI Design Guide |
| Write, refactor, or review TypeScript or Vue code | enforce-rules-for-typescript |
| Write or debug tests, reproduce a bug, add mocks, or fix test import boundaries | enforce-rules-for-vitest |
| Change UnoCSS, Vue styles, UI components, animations, icons, or color mode | enforce-rules-for-unocss |
Add synced to a Pinia store, or change a synced store |
enforce-rules-for-pinia-synced |
| Write or change a string that users see, or a glossary term | packages/i18n/AGENTS.md |
| Review pending Crowdin translations, or find why approved translations did not reach the repository | enforce-rules-for-i18n |
Work under server/ |
server/AGENTS.md. For server/apps/api, also read server/apps/api/AGENTS.md. |
| Write documentation, code comments, commit messages, or PR and issue text | simple-english |
| Analyze why a chat, speech, or audio turn was slow or failed, using saved IO traces | analyze-io-traces |
| Create or prepare a pull request | create-pr |
| Upload a local file through a file input or a file chooser in a web or Electron app | use-agent-browser-with-input-file and agent-browser. For Electron, also read agent-browser-electron. |
| Test Live2D, VRM, or MMD import and rendering in stage-web, stage-tamagotchi, or stage-pocket | use-agent-browser-for-airi |
These directories also have their own AGENTS.md. Read it before you work in the directory:
packages/model-driver-mediapipe/services/computer-use-mcp/