Project AIRI is an open attempt at a Neuro-sama of your own: an animated AI character that talks with you by voice, chats in Discord and Telegram, and can play Minecraft and, in early form, Factorio and Kerbal Space Program. The character is a Live2D or VRM model that blinks, follows your cursor and moves while it speaks, and you choose the brain (OpenAI, Anthropic, Ollama and many other providers through the team's xsai library) and the voice (ElevenLabs, Azure, OpenAI-compatible TTS or local Kokoro). Speech recognition and talk detection run on your device.
Built by the moeru-ai group, it is unusual for being web-first: it runs in a browser and as a PWA on phones, and the desktop apps for Windows, macOS and Linux add native CUDA or Metal acceleration. It is MIT-licensed, has about 50,000 stars, and spread through TikTok clips of the avatar in action. It is still in development (the latest release is a 0.12 beta), and the README warns that the project has no official cryptocurrency or token.
- Repository: github.com/moeru-ai/airi
- Licence: MIT (MIT License)
- Language: TypeScript. Stars: 50K. Forks: 4,981. Last push: Oct 3, 2026.
- Scan: safe, Oct 3, 2026, commit a2ce9f4
Who it is for
VTuber and anime-avatar fans, streamers who want an AI co-host, and developers interested in voice, avatar and game-playing agents running mostly in the browser.
Getting started
1. Try it in the browser, nothing to install
open https://airi.moeru.ai2. macOS, with Homebrew
brew install --cask airi3. Windows, with winget (installers for all platforms are on the Releases page)
winget install MoeruAI.AIRI4. Or run the web version from source
git clone https://github.com/moeru-ai/airi.git && cd airi && pnpm i && pnpm devYou need an LLM provider (an API key, or a local model through Ollama) and, for speech, a TTS provider or the local Kokoro voice. Builds are betas, so expect rough edges.
Safety scan
We cloned moeru-ai/airi at commit a2ce9f4 on Oct 3, 2026 and ran the checks described on the GitHub Tools page: credential patterns, decode-and-execute code, install-time scripts, committed binaries, risky CI workflows, every host the code talks to, known vulnerabilities in pinned dependencies, and project hygiene. A person read every hit. This is what we found.
- No secrets and no pattern hits across 6,015 files and about 800,000 lines of TypeScript and Vue. The 7 bare-IP URLs are all tests, and the one committed binary is the Android Gradle wrapper jar.
- Six npm lifecycle scripts, all monorepo setup: git hooks and package builds at the root, electron-builder's native rebuild for the desktop app, MediaPipe model files for the model driver, and the browser-extension and VS Code integration prep. Three shell scripts test the desktop updater.
- pnpm-lock.yaml pins 3,110 packages with 95 known advisories (3 critical, 37 high). The Better Auth critical and its highs belong to server/apps/auth, the backend for AIRI's own hosted accounts, not the app you run; gh-pages is deploy tooling. Of what remains, Electron is the dependency that ships inside the desktop app.
- 31 workflows. Two are flagged around pull requests: the preview deploy runs from workflow_run, validates the fork's metadata and waits for an approval comment, and neither checks out pull-request code with secrets. Only 6 of 70 third-party actions are pinned to a commit. Security policy, licence, contributing guide and code of conduct present; no Dependabot or CodeQL.
What the scanner counted
| Check | Result |
|---|---|
| Secrets | None found. |
| Suspicious code | None found. |
| Install-time code | 6 npm lifecycle scripts. 3 installer scripts |
| Committed binaries | 1 executable or compiled object committed; listed under the raw findings. |
| CI workflows | 31 workflows. 2 use pull_request_target, none check out the pull request head. 64 of 70 third-party actions pinned to a tag rather than a commit. |
| Network hosts | 40 distinct hosts referenced from source; most often github.com, unspeech.local, api.airi.build, example.test. 7 URLs to a bare IP address, listed under the raw findings. |
| Known vulnerabilities | 95 advisories across 3,110 pinned packages: 3 critical, 37 high, 44 moderate, 11 low. pnpm-lock.yaml: 3,110 packages, 95 advisories. |
| Project hygiene | Has security policy, licence file, contributing guide. Missing automated dependency updates, CodeQL. |
| OpenSSF Scorecard | Not scored: the project is not in Scorecard's weekly index. |
The raw findings
Every hit the scanner wrote out, with a link to the exact line at the scanned commit. Secrets candidates are redacted.
URLs to bare IP addresses (7)
| Where | Rule | Match |
|---|---|---|
| server/apps/api/src/libs/tests/env.test.ts:50 | ip-literal-url | 'https://198.18.0.1:5273', |
| server/apps/api/src/utils/tests/origin.test.ts:27 | ip-literal-url | expect(getTrustedOrigin('https://198.18.0.1:5273')).toBe('') |
| server/apps/api/src/utils/tests/origin.test.ts:30 | ip-literal-url | const extra = ['https://10.0.0.129:5273', 'https://198.18.0.1:5273', 'https://192.168.1.5:5273'] |
| server/apps/api/src/utils/tests/origin.test.ts:32 | ip-literal-url | expect(getTrustedOrigin('https://198.18.0.1:5273', extra)).toBe('https://198.18.0.1:5273') |
| server/apps/api/src/utils/tests/origin.test.ts:32 | ip-literal-url | expect(getTrustedOrigin('https://198.18.0.1:5273', extra)).toBe('https://198.18.0.1:5273') |
| services/computer-use-mcp/src/config.test.ts:27 | ip-literal-url | process.env.COMPUTER_USE_REMOTE_OBSERVATION_BASE_URL = 'http://20.196.212.37:8765/observations' |
| services/computer-use-mcp/src/config.test.ts:42 | ip-literal-url | expect(config.remoteObservationBaseUrl).toBe('http://20.196.212.37:8765/observations') |
npm lifecycle scripts (6)
apps/stage-tamagotchi-kirie/package.jsonpostinstall:node -e "require('node:fs').writeFileSync('node_modules/.gdignore', '')"apps/stage-tamagotchi/package.jsonpostinstall:electron-builder install-app-depsintegrations/vscode/vscode-airi/package.jsonprepare:pnpm run updatepackage.jsonpostinstall:pnpm exec simple-git-hooks && pnpm run build:packagespackages/model-driver-mediapipe/package.jsonpostinstall:tsx ./tasks/prepare-tasks.tsplugins/airi-plugin-web-extension/package.jsonpostinstall:wxt prepare
Installer scripts (3)
Committed binaries (1)
apps/stage-pocket/android/gradle/wrapper/gradle-wrapper.jar: JAR, 44 KB
Worst known vulnerabilities (24 of 95)
| Advisory | Severity | Package | Summary |
|---|---|---|---|
| GHSA-pw9m-5jxm-xr6h | critical | better-auth@1.4.22 | Better Auth: OAuth refresh-token replay via missing client authentication on oidc-provider and mcp plugins |
| GHSA-fjxv-7rqg-78g4 | critical | form-data@2.3.3 | form-data uses unsafe random function in form-data for choosing boundary |
| GHSA-8mmm-9v2q-x3f9 | critical | gh-pages@4.0.0 | tschaub gh-pages vulnerable to prototype pollution |
| GHSA-m9gg-hp2v-232j | high | @grpc/grpc-js@1.14.4 | @grpc/grpc-js: In certain configurations, getAuthContext can return unauthorized certificates as though they were author… |
| GHSA-392p-2q2v-4372 | high | better-auth@1.4.22 | Better Auth: OAuth refresh-token rotation forks the token family on concurrent redemption |
| GHSA-7w99-5wm4-3g79 | high | better-auth@1.4.22 | @better-auth/oauth-provider's OAuth authorization-code grant allows concurrent redemption when two token requests race t… |
| GHSA-86j7-9j95-vpqj | high | better-auth@1.4.22 | Better Auth has stored XSS in the auth-server origin via javascript: redirect_uri in oidc-provider and mcp |
| GHSA-9h47-pqcx-hjr4 | high | better-auth@1.4.22 | Better Auth has insecure cryptographic defaults in oidcProvider: alg=none advertised and plain PKCE accepted by default |
| GHSA-fmh4-wcc4-5jm3 | high | better-auth@1.4.22 | Better Auth vulnerable to unauthorized invitation acceptance via unverified email match in organization plugin |
| GHSA-g38m-r43w-p2q7 | high | better-auth@1.4.22 | Better Auth has an account takeover issue via OAuth auto-link to unverified pre-registered email |
| GHSA-qq9h-g4jm-xgf3 | high | better-auth@1.4.22 | Better Auth: Account takeover via pre-account hijacking on magic-link and email-OTP sign-in |
| GHSA-6j4f-fj2g-mc7p | high | brace-expansion@1.1.18 | brace-expansion: DoS via uncontrolled recursion in parseCommaParts causing stack exhaustion |
| GHSA-qhr7-859c-m2p7 | high | brace-expansion@1.1.18 | brace-expansion: DoS via uncontrolled recursion on nested brace groups causing stack exhaustion |
| GHSA-6j4f-fj2g-mc7p | high | brace-expansion@2.1.4 | brace-expansion: DoS via uncontrolled recursion in parseCommaParts causing stack exhaustion |
| GHSA-qhr7-859c-m2p7 | high | brace-expansion@2.1.4 | brace-expansion: DoS via uncontrolled recursion on nested brace groups causing stack exhaustion |
| GHSA-6j4f-fj2g-mc7p | high | brace-expansion@5.0.9 | brace-expansion: DoS via uncontrolled recursion in parseCommaParts causing stack exhaustion |
| GHSA-qhr7-859c-m2p7 | high | brace-expansion@5.0.9 | brace-expansion: DoS via uncontrolled recursion on nested brace groups causing stack exhaustion |
| GHSA-vfj7-8cjw-p6xm | high | braces@3.0.3 | braces vulnerable to stack-exhaustion denial of service through deeply nested patterns |
| GHSA-gpj5-g38j-94v9 | high | drizzle-orm@0.41.0 | Drizzle ORM has SQL injection via improperly escaped SQL identifiers |
| GHSA-qmv3-fv6v-rmhq | high | electron@43.4.1 | Electron: Sandboxed preload code cache can be poisoned by a compromised renderer |
| GHSA-2gc4-cqfq-p2gv | high | engine.io@6.6.9 | Socket.IO: Engine.IO Protocol Revision Mismatch DoS |
| GHSA-58mr-gqgx-xq4g | high | fast-uri@3.1.6 | fast-uri vulnerable to host confusion via an unclosed bracket in the URI authority |
| GHSA-qw65-cvwx-89v3 | high | fast-uri@3.1.6 | fast-uri vulnerable to authority injection via an unvalidated port in serialize |
| GHSA-hmw2-7cc7-3qxx | high | form-data@2.3.3 | form-data: CRLF injection in form-data via unescaped multipart field names and filenames |
Workflows worth a look
- .github/workflows/deploy-cloudflare-workers-preview-deploy.yml: pull_request_target
- .github/workflows/pr-triage-dispatch.yml: pull_request_target
By the numbers
| Stars | 50K |
|---|---|
| Forks | 4,981 |
| Contributors | 198 |
| Commits | 4,547 |
| Open issues | 93 |
| Open pull requests | 148 |
| Releases | 85 |
| Latest release | v0.12.0-beta.5 |
| Licence | MIT |
| Main language | TypeScript |
| Project age | 1 year |
| Last push | Oct 3, 2026 |
| Tracked files | 6,015 |
| Lines of code | 804K |
| Checkout size | 603 MB |
Lines by language: TypeScript 364.5K, JSON 166.8K, Vue 116.4K, Markdown 105.8K, YAML 26.9K, C# 10.9K.
Questions
Is Project AIRI free?
Yes. AIRI is MIT-licensed and free on the web, desktop and mobile. The model and voice providers you connect bill you separately; with Ollama for chat and local Kokoro for speech it can run without paid APIs. There is no official AIRI token, and the README warns against any that claims to be.
Can Project AIRI play games?
It can play Minecraft and chat in Discord voice channels today. A Factorio agent is a working proof of concept, Kerbal Space Program support is listed as done, and Helldivers 2 co-play is in progress. Game agents run as separate services alongside the main app.
Can I use my own avatar in Project AIRI?
Yes. It loads Live2D and VRM models, so you can use a model you own or bought, with automatic blinking, look-at and idle eye movement. The VRM support also suits avatars made for VRChat-style tools.
This post is part of GitHub Tools, where every repository is cloned and scanned before it is written up. The scan is a snapshot of one commit on one day; the repository has moved on since, so check it before you install.
