diff --git a/.gitignore b/.gitignore
index 65edfe50..55a92a1d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@
# Build output
**/dist/
+**/.vitepress/cache/
**/dist-exe/
**/*.tsbuildinfo
server/src/web/embeddedAssets.generated.ts
diff --git a/README.md b/README.md
index f4edd93c..19e6363b 100644
--- a/README.md
+++ b/README.md
@@ -17,152 +17,50 @@ Run Claude Code / Codex / Gemini sessions locally and control them remotely thro
## Installation
-### Homebrew (macOS/Linux)
+```bash
+npm install -g @twsxtd/hapi
+```
+
+Or with Homebrew:
```bash
brew install tiann/tap/hapi
```
-### npm/npx
+Other options: [Installation guide](docs/guide/installation.md)
+
+## Quickstart
+
+1. Start the server:
```bash
-npx @twsxtd/hapi
+hapi server
```
-Or install globally:
+2. Start a coding session:
```bash
-npm install -g @twsxtd/hapi
+hapi
```
-### Prebuilt binary
+3. Open the UI at `http://localhost:3006` and log in with the token in `~/.hapi/settings.json`.
-Download from [Releases](https://github.com/tiann/hapi/releases).
-
-**macOS users**: Remove the quarantine attribute before running:
-
-```bash
-xattr -d com.apple.quarantine ./hapi
-```
-
-### Docker
-
-Pull the pre-built image from GitHub Container Registry:
-
-```bash
-docker pull ghcr.io/tiann/hapi-server:latest
-```
-
-Run the server:
+## Docker (server only)
```bash
docker run -d --name hapi -p 3006:3006 -v hapi-data:/data ghcr.io/tiann/hapi-server:latest
```
-
-More options (Telegram + environment variables)
+More setup options: [Installation guide](docs/guide/installation.md)
-#### Environment Variables
+## Docs
-| Variable | Default | Description |
-|----------|---------|-------------|
-| `WEBAPP_PORT` | `3006` | Server listening port |
-| `CLI_API_TOKEN` | (auto-generated) | Access token for CLI and web UI |
-| `TELEGRAM_BOT_TOKEN` | - | Telegram bot token (optional) |
-| `WEBAPP_URL` | - | Public URL for Telegram Mini App |
-
-#### With Telegram Support
-
-```bash
-docker run -d \
- --name hapi \
- -p 3006:3006 \
- -v hapi-data:/data \
- -e WEBAPP_URL="https://your-domain.example" \
- -e TELEGRAM_BOT_TOKEN="your-bot-token" \
- ghcr.io/tiann/hapi-server:latest
-```
-
-#### Build from Source
-
-```bash
-docker build -t hapi-server -f server/Dockerfile .
-```
-
-
-
-## Quickstart
-
-1. Start the server on a machine you control:
-
-```bash
-hapi server
-# or: npx @twsxtd/hapi server
-```
-
-2. If the server has no public IP, expose it over HTTPS:
- - Cloudflare Tunnel: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
- - Tailscale: https://tailscale.com/kb/
-
-3. Run the CLI on the machine where you want sessions:
-
-```bash
-# If the server is not on localhost:3006
-export HAPI_SERVER_URL="https://your-domain.example"
-
-hapi
-# or: npx @twsxtd/hapi
-```
-
-4. Open the UI in a browser at the server URL and log in with `CLI_API_TOKEN`.
-
-### Finding Your Access Token
-
-On first run, an Access Token is automatically generated and saved to `~/.hapi/settings.json`.
-
-View your token:
-
-```bash
-cat ~/.hapi/settings.json | grep cliApiToken
-```
-
-Or set your own via environment variable (takes priority over generated token):
-
-```bash
-export CLI_API_TOKEN="your-secret-token"
-```
-
-## Telegram Mini App (optional)
-
-To use Telegram for notifications and the Mini App:
-
-1. Create a bot with @BotFather and get the token.
-
-2. Expose your server over HTTPS (Cloudflare Tunnel, Tailscale, etc.).
-
-3. Add environment variables:
-
-```
-WEBAPP_URL="https://your-domain.example"
-TELEGRAM_BOT_TOKEN="..."
-```
-
-4. Start the server and send `/start` to the bot.
-
-5. Run `/app` in the bot chat to open the Mini App.
-
-6. If prompted, enter `CLI_API_TOKEN` to bind your Telegram account. After binding, you can open the Mini App without re-entering the token, and notifications only go to bound users.
-
-## Multi-agent support
-
-- `hapi` - Start a Claude Code session.
-- `hapi codex` - Start an OpenAI Codex session.
-- `hapi gemini` - Start a Google Gemini session.
-
-## CLI config file
-
-You can store the token in `~/.hapi/settings.json` instead of an env var.
-Environment variables take priority over the file.
+- [Quick Start](docs/guide/quick-start.md)
+- [Installation](docs/guide/installation.md)
+- [PWA](docs/guide/pwa.md)
+- [How it Works](docs/guide/how-it-works.md)
+- [Why HAPI](docs/guide/why-hapi.md)
+- [FAQ](docs/guide/faq.md)
## Requirements
@@ -175,9 +73,3 @@ Environment variables take priority over the file.
bun install
bun run build:single-exe
```
-
-## Docs
-
-- `cli/README.md` - CLI usage and config
-- `server/README.md` - Server setup and architecture
-- `web/README.md` - Web app behavior and dev workflow
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
new file mode 100644
index 00000000..8929801c
--- /dev/null
+++ b/docs/.vitepress/config.ts
@@ -0,0 +1,47 @@
+import { defineConfig } from 'vitepress'
+
+export default defineConfig({
+ title: 'HAPI',
+ description: 'Control your AI agents from anywhere',
+
+ head: [
+ ['link', { rel: 'icon', href: '/favicon.ico' }],
+ ],
+
+ themeConfig: {
+ logo: '/logo.svg',
+
+ nav: [
+ { text: 'Quick Start', link: '/guide/quick-start' },
+ { text: 'App', link: 'https://app.hapi.run', target: '_blank' }
+ ],
+
+ sidebar: [
+ { text: 'Quick Start', link: '/guide/quick-start' },
+ { text: 'Installation', link: '/guide/installation' },
+ { text: 'PWA', link: '/guide/pwa' },
+ { text: 'How it Works', link: '/guide/how-it-works' },
+ { text: 'Why HAPI', link: '/guide/why-hapi' },
+ { text: 'FAQ', link: '/guide/faq' }
+ ],
+
+ socialLinks: [
+ { icon: 'github', link: 'https://github.com/tiann/hapi' }
+ ],
+
+ footer: {
+ message: 'Released under the LGPL-3.0 License.',
+ copyright: 'Copyright © 2024-present'
+ },
+
+ search: {
+ provider: 'local'
+ }
+ },
+
+ vite: {
+ server: {
+ allowedHosts: true
+ }
+ }
+})
diff --git a/docs/WHY_NOT_HAPPY.md b/docs/WHY_NOT_HAPPY.md
deleted file mode 100644
index 29aad4cd..00000000
--- a/docs/WHY_NOT_HAPPY.md
+++ /dev/null
@@ -1,271 +0,0 @@
-# Why Not Happy?
-
-[Happy](https://github.com/slopus/happy) is an excellent project. So why build HAPI?
-
-**The short answer**: Happy is designed for cloud hosting with multiple users. HAPI is designed for self-hosting with a single user. These different goals lead to fundamentally different architectures.
-
-Happy's cloud-first design requires:
-- End-to-end encryption (because you don't trust the server)
-- Distributed database + cache + storage (because you need to scale)
-- Complex deployment (Docker, multiple services, config files)
-
-HAPI's local-first design simplifies everything:
-- No E2EE needed (your data never leaves your machine)
-- Single embedded database (no scaling required)
-- One-command deployment (single binary, zero config)
-
-**TL;DR**: If you want to self-host for personal use, HAPI removes all the complexity that Happy needs for its cloud service.
-
----
-
-## 1. Architecture Overview
-
-### Happy: Cloud-First
-
-```
-┌─────────────────────────────────────────────────────────────────────────────────┐
-│ PUBLIC INTERNET │
-│ │
-│ │
-│ ┌─────────────┐ ┌─────────────────────────────────┐ │
-│ │ │ │ │ │
-│ │ Mobile App │◄─────── E2EE ───────►│ Cloud Server │ │
-│ │ │ │ │ │
-│ └─────────────┘ │ ┌───────────────────────────┐ │ │
-│ │ │ │ │ │
-│ │ │ Encrypted Database │ │ │
-│ │ │ (server cannot read) │ │ │
-│ │ │ │ │ │
-│ │ └───────────────────────────┘ │ │
-│ │ │ │
-│ └────────────────┬────────────────┘ │
-│ │ │
-│ │ E2EE │
-│ │ │
-└──────────────────────────────────────────────────────────────┼───────────────────┘
- │
-┌──────────────────────────────────────────────────────────────┼─────────────────────┐
-│ PRIVATE NETWORK │ │
-│ │ │
-│ ▼ │
-│ ┌──────────────────────────────────────────────┐ │
-│ │ │ │
-│ │ CLI │ │
-│ │ │ │
-│ │ ┌────────────────────────────────────┐ │ │
-│ │ │ Encryption Keys │ │ │
-│ │ │ (only client holds the keys) │ │ │
-│ │ └────────────────────────────────────┘ │ │
-│ │ │ │
-│ └──────────────────────────────────────────────┘ │
-│ │
-└───────────────────────────────────────────────────────────────────────────────────┘
-
-
-Data Flow:
-┌────────────────────────────────────────────────────────────────────────────────────┐
-│ │
-│ CLI ◄───────► Cloud Server ◄───────► App │
-│ │ │ │ │
-│ │ (encrypt) │ (ciphertext) │ (decrypt) │
-│ ▼ ▼ ▼ │
-│ Keys ──────► [Encrypted Data] ◄────── Keys │
-│ │ │
-│ ▼ │
-│ Server stores │
-│ encrypted blobs │
-│ (zero knowledge) │
-│ │
-└────────────────────────────────────────────────────────────────────────────────────┘
-```
-
-### HAPI: Local-First
-
-```
-┌────────────────────────────────────────────────────────────────────────────────────┐
-│ PRIVATE NETWORK │
-│ │
-│ ┌──────────────────────────────────────────────────────────────────────────┐ │
-│ │ │ │
-│ │ Single Process / Binary │ │
-│ │ │ │
-│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
-│ │ │ │ │ │ │ │ │ │
-│ │ │ CLI │◄──►│ Server │◄──►│ Web App │ │ │
-│ │ │ │ │ │ │ (embedded) │ │ │
-│ │ └──────────────┘ └──────┬───────┘ └──────────────┘ │ │
-│ │ │ │ │
-│ │ ▼ │ │
-│ │ ┌────────────────┐ │ │
-│ │ │ │ │ │
-│ │ │ Local Database│ │ │
-│ │ │ (plaintext) │ │ │
-│ │ │ │ │ │
-│ │ └────────────────┘ │ │
-│ │ │ │
-│ └──────────────────────────────────────────────────────────────────────────┘ │
-│ │ │
-│ │ localhost │
-└────────────────────────────────────────┼───────────────────────────────────────────┘
- │
- ▼
-┌───────────────────────────────────────────────────────────────────────────────────┐
-│ TUNNEL (Optional) │
-│ │
-│ localhost ────────► public URL (TLS) │
-│ │
-└────────────────────────────────────────┬──────────────────────────────────────────┘
- │
- ▼
-┌───────────────────────────────────────────────────────────────────────────────────┐
-│ PUBLIC INTERNET │
-│ │
-│ ┌───────────────────────────────┐ │
-│ │ │ │
-│ │ Remote Clients │ │
-│ │ (PWA / Mini App) │ │
-│ │ │ │
-│ └───────────────────────────────┘ │
-│ │
-└───────────────────────────────────────────────────────────────────────────────────┘
-
-
-Data Flow:
-┌────────────────────────────────────────────────────────────────────────────────────┐
-│ │
-│ CLI ◄────────► Server ◄────────► App │
-│ │ │
-│ │ (same machine / process) │
-│ ▼ │
-│ Local Database │
-│ (data never leaves) │
-│ │ │
-│ ▼ │
-│ Tunnel provides │
-│ external access │
-│ (TLS encryption) │
-│ │
-└────────────────────────────────────────────────────────────────────────────────────┘
-```
-
----
-
-## 2. Key Architectural Differences
-
-### 2.1 Data Location
-
-| Aspect | Happy | HAPI |
-|--------|-------|------|
-| **Where data lives** | Cloud server | Your local machine |
-| **Who can access** | Server stores encrypted blobs (cannot read) | Only you (data never uploaded) |
-| **Trust model** | Don't trust server → need E2EE | Trust local environment → TLS sufficient |
-
-### 2.2 Deployment Model
-
-```
-Happy:
-┌───────────────────────────────────────────────────────────────────────┐
-│ │
-│ Distributed Services (4+ components) │
-│ │
-│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
-│ │ Database │ │ Cache │ │ Storage │ │ Server │ │
-│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
-│ │
-│ Requires: Container orchestration, multiple config files │
-│ │
-└───────────────────────────────────────────────────────────────────────┘
-
-HAPI:
-┌───────────────────────────────────────────────────────────────────────┐
-│ │
-│ Single Binary (everything bundled) │
-│ │
-│ ┌─────────────────────────────────────────────────────────────┐ │
-│ │ CLI + Server + Web App + Database (embedded) │ │
-│ └─────────────────────────────────────────────────────────────┘ │
-│ │
-│ Requires: One command to run │
-│ │
-└───────────────────────────────────────────────────────────────────────┘
-```
-
-### 2.3 Security Approach
-
-| Aspect | Happy | HAPI |
-|--------|-------|------|
-| **Problem to solve** | Data on untrusted server | External access to local data |
-| **Solution** | End-to-end encryption | Tunnel with TLS |
-| **Complexity** | High (key management, crypto) | Low (tunnel setup) |
-| **Data at rest** | Encrypted | Plaintext (protected by OS) |
-
----
-
-## 3. Why Different Architectures?
-
-### Happy's Constraints
-
-```
-Goal: Multi-user cloud platform
- │
- ├──► Users don't trust your server
- │ │
- │ └──► Must encrypt everything (E2EE)
- │
- ├──► Many concurrent users
- │ │
- │ └──► Must scale horizontally (distributed DB + cache)
- │
- └──► Multiple devices per user
- │
- └──► Must sync state across devices (complex sync logic)
-
-Result: Sophisticated but complex architecture
-```
-
-### HAPI's Simplifications
-
-```
-Goal: Single-user self-hosted tool
- │
- ├──► Data stays on your machine
- │ │
- │ └──► No E2EE needed (you trust yourself)
- │
- ├──► Only one user
- │ │
- │ └──► No scaling needed (simple embedded database)
- │
- └──► One primary device
- │
- └──► Minimal sync logic (tunnel for remote access)
-
-Result: Simple and portable architecture
-```
-
----
-
-## 4. Summary
-
-| Dimension | Happy | HAPI |
-|-----------|-------|------|
-| **Philosophy** | Cloud-first | Local-first |
-| **Data location** | Server (encrypted) | Local (plaintext) |
-| **Deployment** | Multiple services | Single binary |
-| **Scaling** | Horizontal | None needed |
-| **Encryption** | Application-layer E2EE | Transport-layer TLS |
-| **Target user** | Teams, cloud users | Individuals, self-hosters |
-
----
-
-## 5. Conclusion
-
-The architectural differences stem from fundamentally different product goals:
-
-- **Happy**: Built for multi-user cloud scenarios. Solves the "untrusted server" problem with E2EE, at the cost of deployment complexity.
-
-- **HAPI**: Built for single-user self-hosted scenarios. Solves the "remote access" problem with tunneling, achieving one-command deployment.
-
-**Choose Happy if**: You need multi-user collaboration or team sharing.
-
-**Choose HAPI if**: You want personal use, data sovereignty, and minimal setup.
diff --git a/docs/bun.lock b/docs/bun.lock
new file mode 100644
index 00000000..57d541a6
--- /dev/null
+++ b/docs/bun.lock
@@ -0,0 +1,353 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "hapi-docs",
+ "devDependencies": {
+ "vitepress": "^1.6.4",
+ },
+ },
+ },
+ "packages": {
+ "@algolia/abtesting": ["@algolia/abtesting@1.12.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-oWknd6wpfNrmRcH0vzed3UPX0i17o4kYLM5OMITyMVM2xLgaRbIafoxL0e8mcrNNb0iORCJA0evnNDKRYth5WQ=="],
+
+ "@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.17.7", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", "@algolia/autocomplete-shared": "1.17.7" } }, "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q=="],
+
+ "@algolia/autocomplete-plugin-algolia-insights": ["@algolia/autocomplete-plugin-algolia-insights@1.17.7", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A=="],
+
+ "@algolia/autocomplete-preset-algolia": ["@algolia/autocomplete-preset-algolia@1.17.7", "", { "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA=="],
+
+ "@algolia/autocomplete-shared": ["@algolia/autocomplete-shared@1.17.7", "", { "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg=="],
+
+ "@algolia/client-abtesting": ["@algolia/client-abtesting@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-oRSUHbylGIuxrlzdPA8FPJuwrLLRavOhAmFGgdAvMcX47XsyM+IOGa9tc7/K5SPvBqn4nhppOCEz7BrzOPWc4A=="],
+
+ "@algolia/client-analytics": ["@algolia/client-analytics@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-EPBN2Oruw0maWOF4OgGPfioTvd+gmiNwx0HmD9IgmlS+l75DatcBkKOPNJN+0z3wBQWUO5oq602ATxIfmTQ8bA=="],
+
+ "@algolia/client-common": ["@algolia/client-common@5.46.2", "", {}, "sha512-Hj8gswSJNKZ0oyd0wWissqyasm+wTz1oIsv5ZmLarzOZAp3vFEda8bpDQ8PUhO+DfkbiLyVnAxsPe4cGzWtqkg=="],
+
+ "@algolia/client-insights": ["@algolia/client-insights@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-6dBZko2jt8FmQcHCbmNLB0kCV079Mx/DJcySTL3wirgDBUH7xhY1pOuUTLMiGkqM5D8moVZTvTdRKZUJRkrwBA=="],
+
+ "@algolia/client-personalization": ["@algolia/client-personalization@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-1waE2Uqh/PHNeDXGn/PM/WrmYOBiUGSVxAWqiJIj73jqPqvfzZgzdakHscIVaDl6Cp+j5dwjsZ5LCgaUr6DtmA=="],
+
+ "@algolia/client-query-suggestions": ["@algolia/client-query-suggestions@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-EgOzTZkyDcNL6DV0V/24+oBJ+hKo0wNgyrOX/mePBM9bc9huHxIY2352sXmoZ648JXXY2x//V1kropF/Spx83w=="],
+
+ "@algolia/client-search": ["@algolia/client-search@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-ZsOJqu4HOG5BlvIFnMU0YKjQ9ZI6r3C31dg2jk5kMWPSdhJpYL9xa5hEe7aieE+707dXeMI4ej3diy6mXdZpgA=="],
+
+ "@algolia/ingestion": ["@algolia/ingestion@1.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-1Uw2OslTWiOFDtt83y0bGiErJYy5MizadV0nHnOoHFWMoDqWW0kQoMFI65pXqRSkVvit5zjXSLik2xMiyQJDWQ=="],
+
+ "@algolia/monitoring": ["@algolia/monitoring@1.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-xk9f+DPtNcddWN6E7n1hyNNsATBCHIqAvVGG2EAGHJc4AFYL18uM/kMTiOKXE/LKDPyy1JhIerrh9oYb7RBrgw=="],
+
+ "@algolia/recommend": ["@algolia/recommend@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-NApbTPj9LxGzNw4dYnZmj2BoXiAc8NmbbH6qBNzQgXklGklt/xldTvu+FACN6ltFsTzoNU6j2mWNlHQTKGC5+Q=="],
+
+ "@algolia/requester-browser-xhr": ["@algolia/requester-browser-xhr@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2" } }, "sha512-ekotpCwpSp033DIIrsTpYlGUCF6momkgupRV/FA3m62SreTSZUKjgK6VTNyG7TtYfq9YFm/pnh65bATP/ZWJEg=="],
+
+ "@algolia/requester-fetch": ["@algolia/requester-fetch@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2" } }, "sha512-gKE+ZFi/6y7saTr34wS0SqYFDcjHW4Wminv8PDZEi0/mE99+hSrbKgJWxo2ztb5eqGirQTgIh1AMVacGGWM1iw=="],
+
+ "@algolia/requester-node-http": ["@algolia/requester-node-http@5.46.2", "", { "dependencies": { "@algolia/client-common": "5.46.2" } }, "sha512-ciPihkletp7ttweJ8Zt+GukSVLp2ANJHU+9ttiSxsJZThXc4Y2yJ8HGVWesW5jN1zrsZsezN71KrMx/iZsOYpg=="],
+
+ "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
+
+ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
+
+ "@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="],
+
+ "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
+
+ "@docsearch/css": ["@docsearch/css@3.8.2", "", {}, "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ=="],
+
+ "@docsearch/js": ["@docsearch/js@3.8.2", "", { "dependencies": { "@docsearch/react": "3.8.2", "preact": "^10.0.0" } }, "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ=="],
+
+ "@docsearch/react": ["@docsearch/react@3.8.2", "", { "dependencies": { "@algolia/autocomplete-core": "1.17.7", "@algolia/autocomplete-preset-algolia": "1.17.7", "@docsearch/css": "3.8.2", "algoliasearch": "^5.14.2" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 19.0.0", "react": ">= 16.8.0 < 19.0.0", "react-dom": ">= 16.8.0 < 19.0.0", "search-insights": ">= 1 < 3" }, "optionalPeers": ["@types/react", "react", "react-dom", "search-insights"] }, "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg=="],
+
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.21.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
+
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.21.5", "", { "os": "android", "cpu": "arm" }, "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg=="],
+
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.21.5", "", { "os": "android", "cpu": "arm64" }, "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A=="],
+
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.21.5", "", { "os": "android", "cpu": "x64" }, "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA=="],
+
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.21.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ=="],
+
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.21.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw=="],
+
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.21.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g=="],
+
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.21.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ=="],
+
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.21.5", "", { "os": "linux", "cpu": "arm" }, "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA=="],
+
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.21.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q=="],
+
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.21.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg=="],
+
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg=="],
+
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg=="],
+
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.21.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w=="],
+
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.21.5", "", { "os": "linux", "cpu": "none" }, "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA=="],
+
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.21.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A=="],
+
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.21.5", "", { "os": "linux", "cpu": "x64" }, "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ=="],
+
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.21.5", "", { "os": "none", "cpu": "x64" }, "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg=="],
+
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.21.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow=="],
+
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.21.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg=="],
+
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.21.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A=="],
+
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.21.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA=="],
+
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.21.5", "", { "os": "win32", "cpu": "x64" }, "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw=="],
+
+ "@iconify-json/simple-icons": ["@iconify-json/simple-icons@1.2.64", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-SMmm//tjZBvHnT0EAzZLnBTL6bukSkncM0pwkOXjr0FsAeCqjQtqoxBR0Mp+PazIJjXJKHm1Ju0YgnCIPOodJg=="],
+
+ "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
+
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
+ "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.54.0", "", { "os": "android", "cpu": "arm" }, "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng=="],
+
+ "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.54.0", "", { "os": "android", "cpu": "arm64" }, "sha512-Skx39Uv+u7H224Af+bDgNinitlmHyQX1K/atIA32JP3JQw6hVODX5tkbi2zof/E69M1qH2UoN3Xdxgs90mmNYw=="],
+
+ "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.54.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-k43D4qta/+6Fq+nCDhhv9yP2HdeKeP56QrUUTW7E6PhZP1US6NDqpJj4MY0jBHlJivVJD5P8NxrjuobZBJTCRw=="],
+
+ "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.54.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-cOo7biqwkpawslEfox5Vs8/qj83M/aZCSSNIWpVzfU2CYHa2G3P1UN5WF01RdTHSgCkri7XOlTdtk17BezlV3A=="],
+
+ "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.54.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-miSvuFkmvFbgJ1BevMa4CPCFt5MPGw094knM64W9I0giUIMMmRYcGW/JWZDriaw/k1kOBtsWh1z6nIFV1vPNtA=="],
+
+ "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.54.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KGXIs55+b/ZfZsq9aR026tmr/+7tq6VG6MsnrvF4H8VhwflTIuYh+LFUlIsRdQSgrgmtM3fVATzEAj4hBQlaqQ=="],
+
+ "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-EHMUcDwhtdRGlXZsGSIuXSYwD5kOT9NVnx9sqzYiwAc91wfYOE1g1djOEDseZJKKqtHAHGwnGPQu3kytmfaXLQ=="],
+
+ "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.54.0", "", { "os": "linux", "cpu": "arm" }, "sha512-+pBrqEjaakN2ySv5RVrj/qLytYhPKEUwk+e3SFU5jTLHIcAtqh2rLrd/OkbNuHJpsBgxsD8ccJt5ga/SeG0JmA=="],
+
+ "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-NSqc7rE9wuUaRBsBp5ckQ5CVz5aIRKCwsoa6WMF7G01sX3/qHUw/z4pv+D+ahL1EIKy6Enpcnz1RY8pf7bjwng=="],
+
+ "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.54.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-gr5vDbg3Bakga5kbdpqx81m2n9IX8M6gIMlQQIXiLTNeQW6CucvuInJ91EuCJ/JYvc+rcLLsDFcfAD1K7fMofg=="],
+
+ "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-gsrtB1NA3ZYj2vq0Rzkylo9ylCtW/PhpLEivlgWe0bpgtX5+9j9EZa0wtZiCjgu6zmSeZWyI/e2YRX1URozpIw=="],
+
+ "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.54.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-y3qNOfTBStmFNq+t4s7Tmc9hW2ENtPg8FeUD/VShI7rKxNW7O4fFeaYbMsd3tpFlIg1Q8IapFgy7Q9i2BqeBvA=="],
+
+ "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-89sepv7h2lIVPsFma8iwmccN7Yjjtgz0Rj/Ou6fEqg3HDhpCa+Et+YSufy27i6b0Wav69Qv4WBNl3Rs6pwhebQ=="],
+
+ "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.54.0", "", { "os": "linux", "cpu": "none" }, "sha512-ZcU77ieh0M2Q8Ur7D5X7KvK+UxbXeDHwiOt/CPSBTI1fBmeDMivW0dPkdqkT4rOgDjrDDBUed9x4EgraIKoR2A=="],
+
+ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.54.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-2AdWy5RdDF5+4YfG/YesGDDtbyJlC9LHmL6rZw6FurBJ5n4vFGupsOBGfwMRjBYH7qRQowT8D/U4LoSvVwOhSQ=="],
+
+ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-WGt5J8Ij/rvyqpFexxk3ffKqqbLf9AqrTBbWDk7ApGUzaIs6V+s2s84kAxklFwmMF/vBNGrVdYgbblCOFFezMQ=="],
+
+ "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.54.0", "", { "os": "linux", "cpu": "x64" }, "sha512-JzQmb38ATzHjxlPHuTH6tE7ojnMKM2kYNzt44LO/jJi8BpceEC8QuXYA908n8r3CNuG/B3BV8VR3Hi1rYtmPiw=="],
+
+ "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.54.0", "", { "os": "none", "cpu": "arm64" }, "sha512-huT3fd0iC7jigGh7n3q/+lfPcXxBi+om/Rs3yiFxjvSxbSB6aohDFXbWvlspaqjeOh+hx7DDHS+5Es5qRkWkZg=="],
+
+ "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.54.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-c2V0W1bsKIKfbLMBu/WGBz6Yci8nJ/ZJdheE0EwB73N3MvHYKiKGs3mVilX4Gs70eGeDaMqEob25Tw2Gb9Nqyw=="],
+
+ "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.54.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-woEHgqQqDCkAzrDhvDipnSirm5vxUXtSKDYTVpZG3nUdW/VVB5VdCYA2iReSj/u3yCZzXID4kuKG7OynPnB3WQ=="],
+
+ "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.54.0", "", { "os": "win32", "cpu": "x64" }, "sha512-dzAc53LOuFvHwbCEOS0rPbXp6SIhAf2txMP5p6mGyOXXw5mWY8NGGbPMPrs4P1WItkfApDathBj/NzMLUZ9rtQ=="],
+
+ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.54.0", "", { "os": "win32", "cpu": "x64" }, "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg=="],
+
+ "@shikijs/core": ["@shikijs/core@2.5.0", "", { "dependencies": { "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg=="],
+
+ "@shikijs/engine-javascript": ["@shikijs/engine-javascript@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^3.1.0" } }, "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w=="],
+
+ "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw=="],
+
+ "@shikijs/langs": ["@shikijs/langs@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0" } }, "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w=="],
+
+ "@shikijs/themes": ["@shikijs/themes@2.5.0", "", { "dependencies": { "@shikijs/types": "2.5.0" } }, "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw=="],
+
+ "@shikijs/transformers": ["@shikijs/transformers@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/types": "2.5.0" } }, "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg=="],
+
+ "@shikijs/types": ["@shikijs/types@2.5.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw=="],
+
+ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
+
+ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
+
+ "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
+
+ "@types/linkify-it": ["@types/linkify-it@5.0.0", "", {}, "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q=="],
+
+ "@types/markdown-it": ["@types/markdown-it@14.1.2", "", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog=="],
+
+ "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
+
+ "@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],
+
+ "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
+
+ "@types/web-bluetooth": ["@types/web-bluetooth@0.0.21", "", {}, "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA=="],
+
+ "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
+
+ "@vitejs/plugin-vue": ["@vitejs/plugin-vue@5.2.4", "", { "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA=="],
+
+ "@vue/compiler-core": ["@vue/compiler-core@3.5.26", "", { "dependencies": { "@babel/parser": "^7.28.5", "@vue/shared": "3.5.26", "entities": "^7.0.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w=="],
+
+ "@vue/compiler-dom": ["@vue/compiler-dom@3.5.26", "", { "dependencies": { "@vue/compiler-core": "3.5.26", "@vue/shared": "3.5.26" } }, "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A=="],
+
+ "@vue/compiler-sfc": ["@vue/compiler-sfc@3.5.26", "", { "dependencies": { "@babel/parser": "^7.28.5", "@vue/compiler-core": "3.5.26", "@vue/compiler-dom": "3.5.26", "@vue/compiler-ssr": "3.5.26", "@vue/shared": "3.5.26", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA=="],
+
+ "@vue/compiler-ssr": ["@vue/compiler-ssr@3.5.26", "", { "dependencies": { "@vue/compiler-dom": "3.5.26", "@vue/shared": "3.5.26" } }, "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw=="],
+
+ "@vue/devtools-api": ["@vue/devtools-api@7.7.9", "", { "dependencies": { "@vue/devtools-kit": "^7.7.9" } }, "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g=="],
+
+ "@vue/devtools-kit": ["@vue/devtools-kit@7.7.9", "", { "dependencies": { "@vue/devtools-shared": "^7.7.9", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA=="],
+
+ "@vue/devtools-shared": ["@vue/devtools-shared@7.7.9", "", { "dependencies": { "rfdc": "^1.4.1" } }, "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA=="],
+
+ "@vue/reactivity": ["@vue/reactivity@3.5.26", "", { "dependencies": { "@vue/shared": "3.5.26" } }, "sha512-9EnYB1/DIiUYYnzlnUBgwU32NNvLp/nhxLXeWRhHUEeWNTn1ECxX8aGO7RTXeX6PPcxe3LLuNBFoJbV4QZ+CFQ=="],
+
+ "@vue/runtime-core": ["@vue/runtime-core@3.5.26", "", { "dependencies": { "@vue/reactivity": "3.5.26", "@vue/shared": "3.5.26" } }, "sha512-xJWM9KH1kd201w5DvMDOwDHYhrdPTrAatn56oB/LRG4plEQeZRQLw0Bpwih9KYoqmzaxF0OKSn6swzYi84e1/Q=="],
+
+ "@vue/runtime-dom": ["@vue/runtime-dom@3.5.26", "", { "dependencies": { "@vue/reactivity": "3.5.26", "@vue/runtime-core": "3.5.26", "@vue/shared": "3.5.26", "csstype": "^3.2.3" } }, "sha512-XLLd/+4sPC2ZkN/6+V4O4gjJu6kSDbHAChvsyWgm1oGbdSO3efvGYnm25yCjtFm/K7rrSDvSfPDgN1pHgS4VNQ=="],
+
+ "@vue/server-renderer": ["@vue/server-renderer@3.5.26", "", { "dependencies": { "@vue/compiler-ssr": "3.5.26", "@vue/shared": "3.5.26" }, "peerDependencies": { "vue": "3.5.26" } }, "sha512-TYKLXmrwWKSodyVuO1WAubucd+1XlLg4set0YoV+Hu8Lo79mp/YMwWV5mC5FgtsDxX3qo1ONrxFaTP1OQgy1uA=="],
+
+ "@vue/shared": ["@vue/shared@3.5.26", "", {}, "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A=="],
+
+ "@vueuse/core": ["@vueuse/core@12.8.2", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" } }, "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ=="],
+
+ "@vueuse/integrations": ["@vueuse/integrations@12.8.2", "", { "dependencies": { "@vueuse/core": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" }, "peerDependencies": { "async-validator": "^4", "axios": "^1", "change-case": "^5", "drauu": "^0.4", "focus-trap": "^7", "fuse.js": "^7", "idb-keyval": "^6", "jwt-decode": "^4", "nprogress": "^0.2", "qrcode": "^1.5", "sortablejs": "^1", "universal-cookie": "^7" }, "optionalPeers": ["async-validator", "axios", "change-case", "drauu", "focus-trap", "fuse.js", "idb-keyval", "jwt-decode", "nprogress", "qrcode", "sortablejs", "universal-cookie"] }, "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g=="],
+
+ "@vueuse/metadata": ["@vueuse/metadata@12.8.2", "", {}, "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A=="],
+
+ "@vueuse/shared": ["@vueuse/shared@12.8.2", "", { "dependencies": { "vue": "^3.5.13" } }, "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w=="],
+
+ "algoliasearch": ["algoliasearch@5.46.2", "", { "dependencies": { "@algolia/abtesting": "1.12.2", "@algolia/client-abtesting": "5.46.2", "@algolia/client-analytics": "5.46.2", "@algolia/client-common": "5.46.2", "@algolia/client-insights": "5.46.2", "@algolia/client-personalization": "5.46.2", "@algolia/client-query-suggestions": "5.46.2", "@algolia/client-search": "5.46.2", "@algolia/ingestion": "1.46.2", "@algolia/monitoring": "1.46.2", "@algolia/recommend": "5.46.2", "@algolia/requester-browser-xhr": "5.46.2", "@algolia/requester-fetch": "5.46.2", "@algolia/requester-node-http": "5.46.2" } }, "sha512-qqAXW9QvKf2tTyhpDA4qXv1IfBwD2eduSW6tUEBFIfCeE9gn9HQ9I5+MaKoenRuHrzk5sQoNh1/iof8mY7uD6Q=="],
+
+ "birpc": ["birpc@2.9.0", "", {}, "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw=="],
+
+ "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
+
+ "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
+
+ "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
+
+ "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
+
+ "copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="],
+
+ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
+
+ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
+
+ "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
+
+ "emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="],
+
+ "entities": ["entities@7.0.0", "", {}, "sha512-FDWG5cmEYf2Z00IkYRhbFrwIwvdFKH07uV8dvNy0omp/Qb1xcyCWp2UDtcwJF4QZZvk0sLudP6/hAu42TaqVhQ=="],
+
+ "esbuild": ["esbuild@0.21.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
+
+ "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
+
+ "focus-trap": ["focus-trap@7.7.0", "", { "dependencies": { "tabbable": "^6.3.0" } }, "sha512-DJJDHpEgoSbP8ZE1MNeU2IzCpfFyFdNZZRilqmfH2XiQsPK6PtD8AfJqWzEBudUQB2yHwZc5iq54rjTaGQ+ljw=="],
+
+ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
+
+ "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
+
+ "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
+
+ "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
+
+ "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
+
+ "is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="],
+
+ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
+
+ "mark.js": ["mark.js@8.11.1", "", {}, "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ=="],
+
+ "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="],
+
+ "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="],
+
+ "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="],
+
+ "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="],
+
+ "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="],
+
+ "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
+
+ "minisearch": ["minisearch@7.2.0", "", {}, "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg=="],
+
+ "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
+
+ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
+
+ "oniguruma-to-es": ["oniguruma-to-es@3.1.1", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ=="],
+
+ "perfect-debounce": ["perfect-debounce@1.0.0", "", {}, "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
+
+ "preact": ["preact@10.28.1", "", {}, "sha512-u1/ixq/lVQI0CakKNvLDEcW5zfCjUQfZdK9qqWuIJtsezuyG6pk9TWj75GMuI/EzRSZB/VAE43sNWWZfiy8psw=="],
+
+ "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
+
+ "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
+
+ "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
+
+ "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="],
+
+ "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
+
+ "rollup": ["rollup@4.54.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.54.0", "@rollup/rollup-android-arm64": "4.54.0", "@rollup/rollup-darwin-arm64": "4.54.0", "@rollup/rollup-darwin-x64": "4.54.0", "@rollup/rollup-freebsd-arm64": "4.54.0", "@rollup/rollup-freebsd-x64": "4.54.0", "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", "@rollup/rollup-linux-arm-musleabihf": "4.54.0", "@rollup/rollup-linux-arm64-gnu": "4.54.0", "@rollup/rollup-linux-arm64-musl": "4.54.0", "@rollup/rollup-linux-loong64-gnu": "4.54.0", "@rollup/rollup-linux-ppc64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-musl": "4.54.0", "@rollup/rollup-linux-s390x-gnu": "4.54.0", "@rollup/rollup-linux-x64-gnu": "4.54.0", "@rollup/rollup-linux-x64-musl": "4.54.0", "@rollup/rollup-openharmony-arm64": "4.54.0", "@rollup/rollup-win32-arm64-msvc": "4.54.0", "@rollup/rollup-win32-ia32-msvc": "4.54.0", "@rollup/rollup-win32-x64-gnu": "4.54.0", "@rollup/rollup-win32-x64-msvc": "4.54.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw=="],
+
+ "search-insights": ["search-insights@2.17.3", "", {}, "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ=="],
+
+ "shiki": ["shiki@2.5.0", "", { "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/langs": "2.5.0", "@shikijs/themes": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
+
+ "speakingurl": ["speakingurl@14.0.1", "", {}, "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ=="],
+
+ "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
+
+ "superjson": ["superjson@2.2.6", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA=="],
+
+ "tabbable": ["tabbable@6.3.0", "", {}, "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ=="],
+
+ "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
+
+ "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
+
+ "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
+
+ "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
+
+ "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="],
+
+ "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
+
+ "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
+
+ "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
+
+ "vite": ["vite@5.4.21", "", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="],
+
+ "vitepress": ["vitepress@1.6.4", "", { "dependencies": { "@docsearch/css": "3.8.2", "@docsearch/js": "3.8.2", "@iconify-json/simple-icons": "^1.2.21", "@shikijs/core": "^2.1.0", "@shikijs/transformers": "^2.1.0", "@shikijs/types": "^2.1.0", "@types/markdown-it": "^14.1.2", "@vitejs/plugin-vue": "^5.2.1", "@vue/devtools-api": "^7.7.0", "@vue/shared": "^3.5.13", "@vueuse/core": "^12.4.0", "@vueuse/integrations": "^12.4.0", "focus-trap": "^7.6.4", "mark.js": "8.11.1", "minisearch": "^7.1.1", "shiki": "^2.1.0", "vite": "^5.4.14", "vue": "^3.5.13" }, "peerDependencies": { "markdown-it-mathjax3": "^4", "postcss": "^8" }, "optionalPeers": ["markdown-it-mathjax3", "postcss"], "bin": { "vitepress": "bin/vitepress.js" } }, "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg=="],
+
+ "vue": ["vue@3.5.26", "", { "dependencies": { "@vue/compiler-dom": "3.5.26", "@vue/compiler-sfc": "3.5.26", "@vue/runtime-dom": "3.5.26", "@vue/server-renderer": "3.5.26", "@vue/shared": "3.5.26" }, "peerDependencies": { "typescript": "*" }, "optionalPeers": ["typescript"] }, "sha512-SJ/NTccVyAoNUJmkM9KUqPcYlY+u8OVL1X5EW9RIs3ch5H2uERxyyIUI4MRxVCSOiEcupX9xNGde1tL9ZKpimA=="],
+
+ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
+ }
+}
diff --git a/docs/guide/faq.md b/docs/guide/faq.md
new file mode 100644
index 00000000..5c867d1f
--- /dev/null
+++ b/docs/guide/faq.md
@@ -0,0 +1,177 @@
+# FAQ
+
+## General
+
+### What is HAPI?
+
+HAPI is a local-first, self-hosted platform for running and controlling AI coding agents (Claude Code, Codex, Gemini) remotely. It lets you start coding sessions on your computer and monitor/control them from your phone.
+
+### What does HAPI stand for?
+
+HAPI (哈皮) is a Chinese transliteration of "Happy", reflecting the project's goal of making AI coding assistance a happier experience by freeing you from the terminal.
+
+### Is HAPI free?
+
+Yes, HAPI is open source and free to use under the LGPL-3.0 license.
+
+### What AI agents does HAPI support?
+
+- **Claude Code** (recommended)
+- **OpenAI Codex**
+- **Google Gemini**
+
+## Setup & Installation
+
+### Do I need a server?
+
+HAPI includes an embedded server. Just run `hapi server` on your machine - no external server required.
+
+### How do I access HAPI from my phone?
+
+For local network access:
+```
+http://:3006
+```
+
+For internet access, set up a tunnel (Cloudflare Tunnel, Tailscale, or ngrok).
+
+### What's the access token for?
+
+The `CLI_API_TOKEN` is a shared secret that authenticates:
+- CLI connections to the server
+- Web app logins
+- Telegram account binding
+
+It's auto-generated on first server start and saved to `~/.hapi/settings.json`.
+
+### Can I use HAPI without Telegram?
+
+Yes. Telegram is optional. You can use the web app directly in any browser or install it as a PWA.
+
+## Usage
+
+### How do I approve permissions remotely?
+
+1. When your AI agent requests permission (e.g., to edit a file), you'll see a notification
+2. Open HAPI on your phone
+3. Navigate to the active session
+4. Approve or deny the pending permission
+
+### Can I start sessions remotely?
+
+Yes, with daemon mode:
+
+1. Run `hapi daemon start` on your computer
+2. Your machine appears in the "Machines" list in the web app
+3. Tap to spawn new sessions from anywhere
+
+### How do I see what files were changed?
+
+In the session view, tap the "Files" tab to:
+- Browse project files
+- View git status
+- See diffs of changed files
+
+### Can I send messages to the AI from my phone?
+
+Yes. Open any session and use the chat interface to send messages directly to the AI agent.
+
+## Security
+
+### Is my data safe?
+
+Yes. HAPI is local-first:
+- All data stays on your machine
+- Nothing is uploaded to external servers
+- The database is stored locally in `~/.hapi/`
+
+### How secure is the token authentication?
+
+The auto-generated token is 256-bit (cryptographically secure). For external access, always use HTTPS via a tunnel.
+
+### Can others access my HAPI instance?
+
+Only if they have your access token. For additional security:
+- Use a strong, unique token
+- Always use HTTPS for external access
+- Consider Tailscale for private networking
+
+## Troubleshooting
+
+### "Connection refused" error
+
+- Ensure server is running: `hapi server`
+- Check firewall allows port 3006
+- Verify `HAPI_SERVER_URL` is correct
+
+### "Invalid token" error
+
+- Re-run `hapi auth login`
+- Check token matches in CLI and server
+- Verify `~/.hapi/settings.json` has correct `cliApiToken`
+
+### Daemon won't start
+
+```bash
+# Check status
+hapi daemon status
+
+# Clear stale lock file
+rm ~/.hapi/daemon.state.json.lock
+
+# Check logs
+hapi daemon logs
+```
+
+### Claude Code not found
+
+Install Claude Code or set custom path:
+```bash
+npm install -g @anthropic-ai/claude-code
+# or
+export HAPI_CLAUDE_PATH=/path/to/claude
+```
+
+### How do I run diagnostics?
+
+```bash
+hapi doctor
+```
+
+This checks server connectivity, token validity, agent availability, and more.
+
+## Comparison
+
+### HAPI vs Happy
+
+| Aspect | Happy | HAPI |
+|--------|-------|------|
+| Design | Cloud-first | Local-first |
+| Users | Multi-user | Single user |
+| Deployment | Multiple services | Single binary |
+| Data | Encrypted on server | Never leaves your machine |
+
+See [Why HAPI](/guide/why-hapi) for detailed comparison.
+
+### HAPI vs running Claude Code directly
+
+| Feature | Claude Code | HAPI + Claude Code |
+|---------|-------------|-------------------|
+| Remote access | No | Yes |
+| Mobile control | No | Yes |
+| Permission approval | Terminal only | Phone/web |
+| Session persistence | No | Yes |
+| Multi-machine | Manual | Built-in |
+
+## Contributing
+
+### How can I contribute?
+
+Visit our [GitHub repository](https://github.com/tiann/hapi) to:
+- Report issues
+- Submit pull requests
+- Suggest features
+
+### Where do I report bugs?
+
+Open an issue on [GitHub Issues](https://github.com/tiann/hapi/issues).
diff --git a/docs/guide/how-it-works.md b/docs/guide/how-it-works.md
new file mode 100644
index 00000000..233b59e2
--- /dev/null
+++ b/docs/guide/how-it-works.md
@@ -0,0 +1,166 @@
+# How it Works
+
+HAPI consists of three interconnected components that work together to provide remote AI agent control.
+
+## Architecture Overview
+
+```
+┌────────────────────────────────────────────────────────────────────────────┐
+│ Your Local Machine │
+│ │
+│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
+│ │ │ │ │ │ │ │
+│ │ HAPI CLI │◄───────►│ HAPI Server │◄───────►│ Web App │ │
+│ │ │ Socket │ │ SSE │ (embedded) │ │
+│ │ + AI Agent │ .IO │ + SQLite │ │ │ │
+│ │ │ │ + REST API │ │ │ │
+│ └──────────────┘ └──────┬───────┘ └──────────────┘ │
+│ │ │
+│ │ localhost:3006 │
+└───────────────────────────────────┼────────────────────────────────────────┘
+ │
+ ┌─────────▼─────────┐
+ │ Tunnel (Optional)│
+ │ Cloudflare/ngrok │
+ └─────────┬─────────┘
+ │
+┌───────────────────────────────────┼────────────────────────────────────────┐
+│ Public Internet │
+│ │ │
+│ ┌─────────────────────────┼─────────────────────────┐ │
+│ │ ▼ │ │
+│ │ ┌──────────────┐ ┌──────────────┐ │ │
+│ │ │ │ │ │ │ │
+│ │ │ Telegram │ │ PWA / │ │ │
+│ │ │ Mini App │ │ Browser │ │ │
+│ │ │ │ │ │ │ │
+│ │ └──────────────┘ └──────────────┘ │ │
+│ │ │ │
+│ └───────────────────────────────────────────────────┘ │
+│ Your Phone │
+└────────────────────────────────────────────────────────────────────────────┘
+```
+
+## Components
+
+### HAPI CLI
+
+The CLI is a wrapper around AI coding agents (Claude Code, Codex, Gemini). It:
+
+- Starts and manages coding sessions
+- Registers sessions with the HAPI server
+- Relays messages and permission requests
+- Provides MCP (Model Context Protocol) tools
+
+**Key Commands:**
+```bash
+hapi # Start Claude Code session
+hapi codex # Start OpenAI Codex session
+hapi gemini # Start Google Gemini session
+hapi daemon start # Run background service for remote session spawning
+```
+
+### HAPI Server
+
+The server is the central hub that connects everything:
+
+- **HTTP API** - RESTful endpoints for sessions, messages, permissions
+- **Socket.IO** - Real-time bidirectional communication with CLI
+- **SSE (Server-Sent Events)** - Live updates pushed to web clients
+- **SQLite Database** - Persistent storage for sessions and messages
+- **Telegram Bot** - Notifications and Mini App integration
+
+### Web App
+
+A React-based PWA that provides the mobile interface:
+
+- **Session List** - View all active and past sessions
+- **Chat Interface** - Send messages and view agent responses
+- **Permission Management** - Approve or deny tool access
+- **File Browser** - Browse project files and view git diffs
+- **Remote Spawn** - Start new sessions on any connected machine
+
+## Data Flow
+
+### Starting a Session
+
+```
+1. User runs `hapi` in terminal
+ │
+ ▼
+2. CLI starts Claude Code (or other agent)
+ │
+ ▼
+3. CLI connects to server via Socket.IO
+ │
+ ▼
+4. Server creates session in database
+ │
+ ▼
+5. Web clients receive SSE update
+ │
+ ▼
+6. Session appears in mobile app
+```
+
+### Permission Request Flow
+
+```
+1. AI agent requests tool permission (e.g., file edit)
+ │
+ ▼
+2. CLI sends permission request to server
+ │
+ ▼
+3. Server stores request and notifies via SSE + Telegram
+ │
+ ▼
+4. User receives notification on phone
+ │
+ ▼
+5. User approves/denies in web app or Telegram
+ │
+ ▼
+6. Server relays decision to CLI via Socket.IO
+ │
+ ▼
+7. CLI informs AI agent, execution continues
+```
+
+### Message Flow
+
+```
+User (Phone) Server CLI
+ │ │ │
+ │──── Send message ──────►│ │
+ │ │─── Socket.IO emit ───►│
+ │ │ │
+ │ │ ├── AI processes
+ │ │ │
+ │ │◄── Stream response ───│
+ │◄─────── SSE ────────────│ │
+ │ │ │
+```
+
+## Communication Protocols
+
+### CLI ↔ Server: Socket.IO
+
+Real-time bidirectional communication for:
+- Session registration and heartbeat
+- Message relay (user input → agent)
+- Permission requests and responses
+- Metadata and state updates
+- RPC method invocation
+
+### Server ↔ Web: REST + SSE
+
+- **REST API** for actions (send message, approve permission)
+- **SSE stream** for real-time updates (new messages, status changes)
+
+### External Access: Tunnel
+
+For remote access outside your local network:
+- **Cloudflare Tunnel** (recommended) - Free, secure, reliable
+- **Tailscale** - Mesh VPN for private networks
+- **ngrok** - Quick setup for testing
diff --git a/docs/guide/installation.md b/docs/guide/installation.md
new file mode 100644
index 00000000..cef6b787
--- /dev/null
+++ b/docs/guide/installation.md
@@ -0,0 +1,219 @@
+# Installation
+
+Install the HAPI CLI and set up the server.
+
+## Prerequisites
+
+- Claude Code, OpenAI Codex CLI, or Google Gemini CLI installed
+
+## Install the CLI
+
+```bash
+npm install -g @twsxtd/hapi
+```
+
+Or with Homebrew:
+
+```bash
+brew install tiann/tap/hapi
+```
+
+## Other install options
+
+
+npx (no install)
+
+```bash
+npx @twsxtd/hapi
+```
+
+
+
+Prebuilt binary
+
+Download the latest release from [GitHub Releases](https://github.com/tiann/hapi/releases).
+
+```bash
+xattr -d com.apple.quarantine ./hapi
+chmod +x ./hapi
+sudo mv ./hapi /usr/local/bin/
+```
+
+
+
+Docker (server only)
+
+```bash
+docker pull ghcr.io/tiann/hapi-server:latest
+
+docker run -d \
+ --name hapi-server \
+ -p 3006:3006 \
+ -v ~/.hapi:/root/.hapi \
+ -e CLI_API_TOKEN=your-secret-token \
+ ghcr.io/tiann/hapi-server:latest
+```
+
+
+
+Build from source
+
+```bash
+git clone https://github.com/tiann/hapi.git
+cd hapi
+bun install
+bun build:single-exe
+
+./cli/dist/hapi
+```
+
+
+## Server setup
+
+Start the server:
+
+```bash
+hapi server
+```
+
+The server listens on `http://localhost:3006` by default.
+
+On first run, HAPI:
+
+1. Creates `~/.hapi/`
+2. Generates a secure access token
+3. Prints the token and saves it to `~/.hapi/settings.json`
+
+
+Config files
+
+```
+~/.hapi/
+├── settings.json # Main configuration
+├── hapi.db # SQLite database (server)
+├── daemon.state.json # Daemon process state
+└── logs/ # Log files
+```
+
+
+
+Environment variables
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `CLI_API_TOKEN` | Auto-generated | Shared secret for authentication |
+| `HAPI_SERVER_URL` | `http://localhost:3006` | Server URL for CLI |
+| `WEBAPP_PORT` | `3006` | HTTP server port |
+| `HAPI_HOME` | `~/.hapi` | Config directory path |
+| `DB_PATH` | `~/.hapi/hapi.db` | Database file path |
+| `CORS_ORIGINS` | - | Allowed CORS origins |
+
+
+## CLI setup
+
+If the server is not on localhost, set these before running `hapi`:
+
+```bash
+export HAPI_SERVER_URL="http://your-server:3006"
+export CLI_API_TOKEN="your-token-here"
+```
+
+Or use interactive login:
+
+```bash
+hapi auth login
+```
+
+Authentication commands:
+
+```bash
+hapi auth status
+hapi auth login
+hapi auth logout
+```
+
+Each machine gets a unique ID stored in `~/.hapi/settings.json`. This allows:
+
+- Multiple machines to connect to one server
+- Remote session spawning on specific machines
+- Machine health monitoring
+
+## Operations
+
+### Remote access
+
+Cloudflare Tunnel (recommended):
+
+https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
+
+```bash
+export WEBAPP_URL="https://your-tunnel.trycloudflare.com"
+```
+
+Tailscale:
+
+https://tailscale.com/download
+
+```bash
+sudo tailscale up
+```
+
+Access via your Tailscale IP:
+
+```
+http://100.x.x.x:3006
+```
+
+ngrok:
+
+```bash
+ngrok http 3006
+```
+
+### Telegram setup
+
+Enable Telegram notifications and Mini App access:
+
+1. Message [@BotFather](https://t.me/BotFather) and create a bot
+2. Set the bot token and public URL
+3. Start the server and bind your account
+
+```bash
+export TELEGRAM_BOT_TOKEN="your-bot-token"
+export WEBAPP_URL="https://your-public-url"
+
+hapi server
+```
+
+Then message your bot with `/start`, open the app, and enter your `CLI_API_TOKEN`.
+
+### Daemon setup
+
+Run a background service for remote session spawning:
+
+```bash
+hapi daemon start
+hapi daemon status
+hapi daemon logs
+hapi daemon stop
+```
+
+With the daemon running:
+
+- Your machine appears in the "Machines" list
+- You can spawn sessions remotely from the web app
+- Sessions persist even when the terminal is closed
+
+### Security notes
+
+- Keep tokens secret and rotate if needed
+- Use HTTPS for public access
+- Restrict CORS origins in production
+
+
+Firewall example (ufw)
+
+```bash
+ufw allow from 192.168.1.0/24 to any port 3006
+```
+
diff --git a/docs/guide/pwa.md b/docs/guide/pwa.md
new file mode 100644
index 00000000..44478dd6
--- /dev/null
+++ b/docs/guide/pwa.md
@@ -0,0 +1,187 @@
+# Progressive Web App (PWA)
+
+HAPI's web interface is a fully-featured PWA that can be installed on your phone for a native app-like experience.
+
+## What is PWA?
+
+A Progressive Web App (PWA) is a web application that can be installed on your device and works like a native app:
+
+- **Home screen icon** - Launch HAPI like any other app
+- **Full screen mode** - No browser chrome, immersive experience
+- **Offline support** - Basic functionality works without internet
+- **Auto-updates** - Always get the latest version
+
+## Installing HAPI PWA
+
+### Android (Chrome/Edge)
+
+1. Open HAPI in Chrome or Edge browser
+2. Look for the **"Install HAPI"** banner at the bottom
+3. Tap **"Install"**
+4. HAPI appears on your home screen
+
+::: tip
+If you don't see the install banner, tap the three-dot menu and select **"Add to Home screen"** or **"Install app"**.
+:::
+
+### iOS (Safari)
+
+1. Open HAPI in Safari browser
+2. Tap the **Share** button (square with arrow)
+3. Scroll down and tap **"Add to Home Screen"**
+4. Tap **"Add"** in the top right corner
+
+::: warning
+iOS requires Safari for PWA installation. Chrome/Firefox on iOS don't support the "Add to Home Screen" feature.
+:::
+
+### Desktop (Chrome/Edge)
+
+1. Open HAPI in your browser
+2. Click the install icon in the address bar (⊕)
+3. Or use the menu: **"Install HAPI..."**
+4. HAPI opens as a standalone window
+
+## PWA Features
+
+### Offline Mode
+
+When offline, HAPI can:
+
+- Display cached session lists
+- Show previously loaded messages
+- Queue actions for when you're back online
+
+An offline indicator appears when you lose connection.
+
+### Auto-Update
+
+HAPI automatically checks for updates:
+
+- Updates are checked hourly in the background
+- When a new version is available, you'll see a prompt
+- Click "Reload" to get the latest version
+
+### Background Sync
+
+Actions taken offline are synced when reconnected:
+
+- Pending messages are sent
+- Permission decisions are relayed
+- Session state is refreshed
+
+## Caching Strategy
+
+HAPI uses intelligent caching:
+
+| Content | Strategy | Duration |
+|---------|----------|----------|
+| App shell | Cache first | Until update |
+| Sessions API | Network first | 5 minutes |
+| Machines API | Network first | 10 minutes |
+| Static assets | Cache first | Forever |
+
+## Notifications
+
+::: warning Work in Progress
+Push notifications are planned for a future release. Currently, notifications work through:
+- Telegram bot (recommended)
+- Keeping the app open in background
+:::
+
+## Managing Your PWA
+
+### Check Install Status
+
+HAPI shows different UI based on install status:
+
+- **Not installed** - Shows install prompt
+- **Installing** - Shows progress indicator
+- **Installed** - No prompt shown
+
+### Uninstalling
+
+**Android:**
+1. Long-press the HAPI icon
+2. Drag to "Uninstall" or tap the X
+
+**iOS:**
+1. Long-press the HAPI icon
+2. Tap "Remove App" → "Delete App"
+
+**Desktop:**
+1. Open HAPI
+2. Click the three-dot menu
+3. Select "Uninstall HAPI"
+
+### Clearing Cache
+
+If you experience issues:
+
+1. Open HAPI in browser (not installed version)
+2. Open Developer Tools (F12)
+3. Go to Application → Storage
+4. Click "Clear site data"
+
+## Best Practices
+
+### Battery Optimization
+
+On Android, disable battery optimization for HAPI to ensure:
+- Background sync works reliably
+- Notifications arrive promptly
+
+Settings → Apps → HAPI → Battery → Unrestricted
+
+### Data Usage
+
+HAPI uses minimal data:
+
+- Initial load: ~500KB
+- Cached after first load
+- Only syncs changed data
+
+### Multiple Devices
+
+You can install HAPI on multiple devices:
+
+- All devices use the same server
+- Sessions sync across devices
+- Same access token works everywhere
+
+## Troubleshooting
+
+### Install Button Not Showing
+
+- Ensure you're using HTTPS (required for PWA)
+- Try refreshing the page
+- Check if already installed
+
+### App Not Updating
+
+1. Close the app completely
+2. Reopen and wait for update prompt
+3. If stuck, clear cache and reinstall
+
+### Offline Mode Not Working
+
+- Ensure you've loaded the app at least once online
+- Check if ServiceWorker is registered (DevTools → Application)
+- Clear cache and reload
+
+### iOS-Specific Issues
+
+- Must use Safari for installation
+- No background sync on iOS
+- Limited offline capabilities
+
+## Telegram Mini App Alternative
+
+If PWA doesn't suit your needs, consider the Telegram Mini App:
+
+- Works inside Telegram
+- No separate installation
+- Same features as PWA
+- Integrated notifications
+
+See [Installation Guide](/guide/installation#telegram-setup) for Telegram setup.
diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md
new file mode 100644
index 00000000..b0275dfc
--- /dev/null
+++ b/docs/guide/quick-start.md
@@ -0,0 +1,55 @@
+# Quick Start
+
+Get HAPI running in a few minutes.
+
+## Step 1: Install HAPI
+
+::: code-group
+
+```bash [npm]
+npm install -g @twsxtd/hapi
+```
+
+```bash [Homebrew]
+brew install tiann/tap/hapi
+```
+
+```bash [npx (one-off)]
+npx @twsxtd/hapi
+```
+
+:::
+
+Other install options: [Installation](/guide/installation)
+
+## Step 2: Start the server
+
+```bash
+hapi server
+```
+
+On first run, HAPI prints an access token and saves it to `~/.hapi/settings.json`.
+
+## Step 3: Start a coding session
+
+```bash
+hapi
+```
+
+This starts Claude Code wrapped with HAPI. The session appears in the web UI.
+
+## Step 4: Open the UI
+
+Open your browser:
+
+```
+http://localhost:3006
+```
+
+Or from another device on the same network:
+
+```
+http://:3006
+```
+
+Enter your access token to log in.
diff --git a/docs/guide/why-hapi.md b/docs/guide/why-hapi.md
new file mode 100644
index 00000000..7d87f633
--- /dev/null
+++ b/docs/guide/why-hapi.md
@@ -0,0 +1,192 @@
+# Why HAPI?
+
+[Happy](https://github.com/slopus/happy) is an excellent project. So why build HAPI?
+
+**The short answer**: Happy is designed for cloud hosting with multiple users. HAPI is designed for self-hosting with a single user. These different goals lead to fundamentally different architectures.
+
+## TL;DR
+
+| Aspect | Happy | HAPI |
+|--------|-------|------|
+| **Design** | Cloud-first | Local-first |
+| **Users** | Multi-user | Single user |
+| **Data** | Encrypted on server | Never leaves your machine |
+| **Deployment** | Multiple services | Single binary |
+| **Complexity** | High (E2EE, scaling) | Low (one command) |
+
+**Choose HAPI if**: You want personal use, data sovereignty, and minimal setup.
+
+**Choose Happy if**: You need multi-user collaboration or team sharing.
+
+## Architecture Comparison
+
+### Happy: Cloud-First
+
+Happy's cloud design requires:
+
+- **End-to-end encryption** - Because you don't trust the server
+- **Distributed database + cache** - Because you need to scale
+- **Complex deployment** - Docker, multiple services, config files
+
+```
+┌─────────────────────────────────────────────────────────────────────────┐
+│ PUBLIC INTERNET │
+│ │
+│ ┌─────────────┐ ┌─────────────────────────────────┐│
+│ │ │ │ ││
+│ │ Mobile App │◄───── E2EE ───────►│ Cloud Server ││
+│ │ │ │ ││
+│ └─────────────┘ │ ┌─────────────────────────────┐││
+│ │ │ Encrypted Database │││
+│ │ │ (server cannot read) │││
+│ │ └─────────────────────────────┘││
+│ └────────────────┬────────────────┘│
+│ │ E2EE │
+└───────────────────────────────────────────────────────┼─────────────────┘
+ ▼
+ ┌───────────────────┐
+ │ CLI │
+ │ (holds the keys) │
+ └───────────────────┘
+```
+
+### HAPI: Local-First
+
+HAPI's local design simplifies everything:
+
+- **No E2EE needed** - Your data never leaves your machine
+- **Single embedded database** - No scaling required
+- **One-command deployment** - Single binary, zero config
+
+```
+┌────────────────────────────────────────────────────────────────────────┐
+│ PRIVATE NETWORK │
+│ │
+│ ┌────────────────────────────────────────────────────────────────┐ │
+│ │ Single Process / Binary │ │
+│ │ │ │
+│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
+│ │ │ CLI │◄──►│ Server │◄──►│ Web App │ │ │
+│ │ └──────────┘ └────┬─────┘ └──────────┘ │ │
+│ │ │ │ │
+│ │ ▼ │ │
+│ │ ┌────────────────┐ │ │
+│ │ │ Local Database │ │ │
+│ │ │ (plaintext) │ │ │
+│ │ └────────────────┘ │ │
+│ └────────────────────────────────────────────────────────────────┘ │
+│ │ │
+│ ▼ localhost │
+└────────────────────────────┼───────────────────────────────────────────┘
+ │
+ ┌────────▼────────┐
+ │ Tunnel (Optional)│
+ │ for remote access│
+ └─────────────────┘
+```
+
+## Key Differences
+
+### Data Location
+
+| Aspect | Happy | HAPI |
+|--------|-------|------|
+| **Where data lives** | Cloud server | Your local machine |
+| **Who can access** | Server stores encrypted blobs | Only you |
+| **Trust model** | Don't trust server → E2EE | Trust local → TLS sufficient |
+
+### Deployment Model
+
+**Happy** requires orchestrating multiple components:
+
+```
+┌───────────────────────────────────────────────────────────────────┐
+│ Distributed Services (4+ components) │
+│ │
+│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
+│ │ Database │ │ Cache │ │ Storage │ │ Server │ │
+│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
+│ │
+│ Requires: Container orchestration, multiple config files │
+└───────────────────────────────────────────────────────────────────┘
+```
+
+**HAPI** bundles everything:
+
+```
+┌───────────────────────────────────────────────────────────────────┐
+│ Single Binary (everything bundled) │
+│ │
+│ ┌─────────────────────────────────────────────────────────────┐ │
+│ │ CLI + Server + Web App + Database (embedded) │ │
+│ └─────────────────────────────────────────────────────────────┘ │
+│ │
+│ Requires: One command to run │
+└───────────────────────────────────────────────────────────────────┘
+```
+
+### Security Approach
+
+| Aspect | Happy | HAPI |
+|--------|-------|------|
+| **Problem** | Data on untrusted server | External access to local data |
+| **Solution** | End-to-end encryption | Tunnel with TLS |
+| **Complexity** | High (key management) | Low (tunnel setup) |
+| **Data at rest** | Encrypted | Plaintext (protected by OS) |
+
+## Why Different Architectures?
+
+### Happy's Constraints
+
+```
+Goal: Multi-user cloud platform
+ │
+ ├──► Users don't trust your server
+ │ └──► Must encrypt everything (E2EE)
+ │
+ ├──► Many concurrent users
+ │ └──► Must scale horizontally
+ │
+ └──► Multiple devices per user
+ └──► Must sync state across devices
+```
+
+**Result**: Sophisticated but complex architecture
+
+### HAPI's Simplifications
+
+```
+Goal: Single-user self-hosted tool
+ │
+ ├──► Data stays on your machine
+ │ └──► No E2EE needed
+ │
+ ├──► Only one user
+ │ └──► No scaling needed
+ │
+ └──► One primary device
+ └──► Minimal sync logic
+```
+
+**Result**: Simple and portable architecture
+
+## Summary
+
+| Dimension | Happy | HAPI |
+|-----------|-------|------|
+| **Philosophy** | Cloud-first | Local-first |
+| **Data location** | Server (encrypted) | Local (plaintext) |
+| **Deployment** | Multiple services | Single binary |
+| **Scaling** | Horizontal | None needed |
+| **Encryption** | Application-layer E2EE | Transport-layer TLS |
+| **Target user** | Teams, cloud users | Individuals, self-hosters |
+
+## Conclusion
+
+The architectural differences stem from fundamentally different goals:
+
+- **Happy**: Built for multi-user cloud scenarios. Solves the "untrusted server" problem with E2EE, at the cost of deployment complexity.
+
+- **HAPI**: Built for single-user self-hosted scenarios. Solves the "remote access" problem with tunneling, achieving one-command deployment.
+
+If you want to self-host for personal use, HAPI removes all the complexity that Happy needs for its cloud service.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..0eca41b1
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,14 @@
+---
+layout: home
+title: HAPI Documentation
+---
+
+
diff --git a/docs/package.json b/docs/package.json
new file mode 100644
index 00000000..8016aaa6
--- /dev/null
+++ b/docs/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "hapi-docs",
+ "version": "1.0.0",
+ "description": "HAPI Documentation",
+ "type": "module",
+ "scripts": {
+ "docs:dev": "vitepress dev",
+ "docs:build": "vitepress build",
+ "docs:preview": "vitepress preview"
+ },
+ "keywords": ["hapi", "ai", "agent", "documentation"],
+ "author": "",
+ "license": "LGPL-3.0-or-later",
+ "devDependencies": {
+ "vitepress": "^1.6.4"
+ }
+}
diff --git a/docs/public/favicon.ico b/docs/public/favicon.ico
new file mode 100644
index 00000000..11e41499
Binary files /dev/null and b/docs/public/favicon.ico differ
diff --git a/docs/public/logo.svg b/docs/public/logo.svg
new file mode 100644
index 00000000..723b90f8
--- /dev/null
+++ b/docs/public/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file