## 1. Project Overview & Quickstart (RunanywhereAI/CONTRIBUTING)

# CONTRIBUTING

Open-source repository RunanywhereAI/CONTRIBUTING

### Repository Details
- **Repository:** [RunanywhereAI/CONTRIBUTING](https://github.com/RunanywhereAI/CONTRIBUTING)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (RunanywhereAI/docs)

## File: README.md

<h1 align="center">LibreChat Documentation</h1>







---

## What's New in LibreChat v0.8.8-rc2

- **Agent run control:** Interrupt an Agent before visible answer text, steer runs with files and quoted excerpts, durably queue follow-ups, and recover saved partial work with **Keep going** or **Answer now**.
- **Agent activity:** Optional generated labels group reasoning and tool work, summarize multi-step phases, and show the current reasoning direction.
- **Human-in-the-loop Agents:** Stream up to four related questions, pause for input or tool approval, and resume durably.
- **Unified Agent Builder:** Configure Skills, MCP, Code Interpreter, orchestration, Programmatic Tool Calling, model-spec controls, and per-tool background and intent settings in one Tools marketplace; Skills can be enabled for standalone runtime authoring without exposing the existing catalog.
- **Durable Agent automation:** Authenticated Agent Events support bound child actors, expected-action receipts, per-actor mailboxes, event batching, durable human pauses, and automatic detached Actions across built-in stream stores.
- **Deeper Subagent history:** Browse branch-aware child turns with bounded reasoning and stable live event views, load earlier activity, inspect event details, continue completed child chats, and automatically wake saved parent Agents when detached work settles.
- **Background tools:** Eligible Code Interpreter, MCP, Plugin, and Action tools can run while an Agent keeps working, with automatic delivery for supported completions and polling controls when needed.
- **Code Interpreter workflows:** Sandbox images return as viewable artifacts; highly experimental stateful sessions add scoped managed, attached, or personal environments, per-message file downloads, and guarded file-write and command permissions.
- **Agent extensibility:** Experimental Agent Plugins bundle deployment Skills, MCP servers, and opt-in command hooks; saved Agent teams run as isolated Subagent graphs.
- **Scheduled Chats (experimental):** Run saved Agents with presets or custom cron, selectable time zones, multi-day weekly cadence, and optional Chat Project destinations.
- **Memory and context:** Agents can use optionally isolated memory, preserve adaptive context fading across turns, and show categorized current-window usage, tokens, and optional cost.
- **Editable long pastes:** Long pasted text becomes an editable attachment that can be moved back into the composer; attachment-only turns and reliable Upload as Text downloads are also supported.
- **Projects, settings, and navigation:** Search conversation titles and message contents, manage project chats, use searchable settings and shortcuts, pin chats, choose clock/week conventions, and navigate faster on mobile.
- **Sharing and artifacts:** Stable shared links support personal copies; fullscreen previews, Mermaid export, PowerPoint templates, shell scripts, and original Office downloads expand file workflows.
- **Web search:** Keenable adds keyless search and page fetch, while SearXNG and Tavily gain richer controls and all web-tool egress uses stronger SSRF protection.
- **Security and authentication:** Default HTTP security headers, opt-in nonce CSP, authenticated local images, per-user Code Interpreter JWTs, stable SAML identity binding, live-session OpenID token refresh, and retired JWT-secret rejection harden deployments.
- **Models and reasoning:** Added GPT-5.6 with Responses reasoning controls, Claude Fable 5.1, Opus 5, and Sonnet 5, plus Gemini 3.8/3.7/3.6 Flash and Gemini 3.5 Flash-Lite.
- **Langfuse observability:** Configure encrypted in-app connections, tenant fanout, authenticated gateways, export-decision telemetry, and authorized session links in chats and shared views.
- **Administration:** Source-aware content filters can audit or block model-bound data, while tenant Insights, delegated configuration, encrypted secrets, and expiring violation scores improve operations.
- **Streaming and reliability:** Adaptive smoothing, Redis delta batching and failover recovery, automatic generation protocol v2, live MCP catalog refresh, Agent circuit breakers, and DocumentDB support improve long runs and scaled deployments.

Read the [full v0.8.8-rc2 changelog](https://www.librechat.ai/changelog/v0.8.8-rc2).

---

This repository powers **[www.librechat.ai](https://www.librechat.ai)**: the docs, guides, blog, and changelog for LibreChat. It is a [Next.js](https://nextjs.org) application built on [Fumadocs](https://fumadocs.dev), with content authored in MDX.

> Looking for the LibreChat app itself? It lives at **[LibreChat-AI/LibreChat](https://github.com/LibreChat-AI/LibreChat)**. Open code and product issues there, and documentation issues here.

## Table of Contents

- [What's New in LibreChat v0.8.8-rc2](#whats-new-in-librechat-v088-rc2)
- [Features](#features)
- [Tech Stack](#tech-stack)
- [Getting Started](#getting-started)
- [Project Structure](#project-structure)
- [Writing Documentation](#writing-documentation)
- [Available Scripts](#available-scripts)
- [Contributing](#contributing)
- [Community & Support](#community--support)
- [License](#license)

## Features

- 📚 **Complete documentation** covering setup, configuration, deployment, and every LibreChat feature.
- 📝 **Blog & changelog** authored in MDX, with release notes and long-form articles.
- 🤖 **Ask AI** — an in-page assistant (Vercel AI SDK + [OpenRouter](https://openrouter.ai)) that answers questions grounded in the docs.
- 🔍 **Instant search** — fast, fully client-side full-text search powered by [Orama](https://orama.com), with a prebuilt static index per language.
- 🌍 **14 languages** — English source with translations (中文, Español, Français, Deutsch, 日本語, Português, Italiano, Nederlands, Polski, Tiếng Việt, 한국어, Bahasa Indonesia, Türkçe), including dedicated tokenizers for CJK, Korean, Polish, and Vietnamese search.
- 🎨 **Polished UI** — responsive, accessible, light/dark themes out of the box via Fumadocs UI.
- ⚡ **Static-first & fast** — per-locale prebuilt search indexes, optimized images, and dynamic Open Graph images.
- 🔒 **Privacy-friendly** — cookieless, self-hosted analytics with no tracking banners.

## Tech Stack

| Layer           | Technology                                                                |
| --------------- | ------------------------------------------------------------------------- |
| Framework       | [Next.js](https://nextjs.org) 16 (App Router), React 19                   |
| Docs engine     | [Fumadocs](https://fumadocs.dev) (core, ui, mdx)                          |
| Content         | MDX                                                                       |
| Styling         | [Tailwind CSS](https://tailwindcss.com) v4                                |
| Search          | [Orama](https://orama.com) (static, per-locale index)                     |
| Ask AI          | [Vercel AI SDK](https://ai-sdk.dev) + [OpenRouter](https://openrouter.ai) |
| Rate limiting   | [Upstash](https://upstash.com) Redis                                      |
| Icons           | [Lucide](https://lucide.dev)                                              |
| Testing         | [Vitest](https://vitest.dev)                                              |
| Tooling         | ESLint, Prettier, Husky                                                   |
| Package manager | [pnpm](https://pnpm.io)                                                   |

## Getting Started

### Prerequisites

- [Node.js](https://nodejs.org) **22.x–24.x** (CI and production run 24)
- [pnpm](https://pnpm.io) **9.5+**

### Setup

```bash
# 1. Clone the repository
git clone https://github.com/LibreChat-AI/librechat.ai.git
cd librechat.ai

# 2. (Optional) create a local env file for Ask AI, rate limiting, etc.
cp .env.template .env.local

# 3. Install dependencies
pnpm install

# 4. Start the dev server
pnpm dev
```

Open [http://localhost:3333](http://localhost:3333) to view the site.

> Environment variables are optional for local docs work. You only need to fill in `.env.local` to exercise features like Ask AI or rate limiting. Always run `pnpm build` before opening a PR to catch build errors early.

### Web Bot Auth

Generate an Ed25519 signing key, then copy the printed assignment into `.env.local`:

```bash
pnpm web-bot-auth:keygen
```

In the production secret manager, store the JSON between the single quotes as the `WEB_BOT_AUTH_PRIVATE_JWK` value.

Set `WEB_BOT_AUTH_AGENT_ORIGIN` when the public site origin is not `https://www.librechat.ai`. The app publishes the corresponding public JWKS at `/.well-known/http-message-signatures-directory` and signs requests from the docs AI agent. The directory returns `503` and agent requests fail closed until the private key is configured, so a deployment cannot advertise an empty key set or silently send unsigned agent traffic.

## Project Structure

```
app/                # Next.js App Router: docs, blog, changelog pages + API routes
  api/
    chat/           # "Ask AI" endpoint (OpenRouter via the Vercel AI SDK)
    search/         # Per-locale static Orama search index
content/
  docs/             # Documentation pages (MDX), organized by section
  blog/             # Blog posts (MDX)
  changelog/        # Changelog entries (MDX)
components/         # React components (home, UI, icons, search dialog, etc.)
lib/                # Utilities: content sources, i18n, search, MDX components
public/             # Static assets (images, videos, icons)
scripts/            # Build, translation, and image-optimization scripts
source.config.ts    # Fumadocs content collections config
```

## Writing Documentation

Docs live in `content/docs/` and are grouped by section. Each directory has a `meta.json` that controls sidebar navigation and ordering:

```json
{
  "title": "Section Title",
  "icon": "Wrench",
  "pages": ["index", "page-one", "page-two"]
}
```

Only pages listed in the `pages` array appear in the sidebar, in the order given.

**Localization:** English (`.mdx`) is the source of truth. Translated pages use a locale suffix (for example `index.es.mdx`), and each locale's search index only includes pages that have a real translated file. Keep new content in English and let the translation workflow handle the rest.

## Docs Versions

`content/docs/` is the live version, served at `/docs` and labelled by `CURRENT_VERSION` in
`lib/versions.ts`. Every published release and release candidate is a frozen snapshot under
`content/docs-archive/<version>/`, served at `/<version>/docs` — for example
`/v0.8.5/docs/quick_start`. Version ids match `v<major>.<minor>[.|.x][-rc<n>]`; the
switcher orders them newest-first, with a release ranked above its own candidates.

Publish one with:

```bash
pnpm docs:archive v0.8.5 --ref=<commit-or-tag>
```

That copies the English docs out of git at `--ref` (default `HEAD`), drops every localized file,
and rewrites absolute `/docs/...` links to `/<version>/docs/...` so an archived page never links
back into the live docs. The sidebar version switcher is built from the directories that exist, so
no code change is needed to publish or retire a version.

Archived snapshots are deliberately inert: English-only, `noindex`, absent from the sitemap,
search index, `llms.txt`, the translation workflow and `pnpm sync:config-version` (they keep the
`librechat.yaml` version they shipped with).

Two limits are worth knowing:

- **The archive starts at v0.8.2.** This repository only gained `content/docs` in the Fumadocs
  migration, and every release up to v0.8.2 had its changelog backfilled in that single commit, so
  there is exactly one docs tree for all of them — published once as `v0.8.2`. Docs for v0.5.x–v0.8.1
  exist only as the pre-migration Nextra `pages/` tree and would need converting before they could
  be archived.
- **Snapshots are bundled, so they cost build memory.** Archived pages inherit real MDX imports
  (`next/image`, `@/components/...`) from the docs they snapshot, which on-demand compilation
  cannot resolve, so the collection is bundled like the live docs. `pnpm build` therefore runs with
  `--max-old-space-size=8192`. The bundle also has a hard ceiling: with 17 archived versions webpack
  fails with `RangeError: Invalid string length`, so only final releases are archived and a
  release's candidate snapshots are deleted once it ships (see `content/docs-archive/README.md`).

## Available Scripts

| Command                     | Description                                                  |
| --------------------------- | ------------------------------------------------------------ |
| `pnpm dev`                  | Start the dev server on port 3333                            |
| `pnpm build`                | Production build                                             |
| `pnpm start`                | Start the production server on port 3333                     |
| `pnpm lint`                 | Run ESLint (zero warnings allowed)                           |
| `pnpm lint:prettier`        | Check formatting with Prettier                               |
| `pnpm prettier`             | Format the codebase with Prettier                            |
| `pnpm typecheck`            | Generate MDX types and run `tsc --noEmit`                    |
| `pnpm test`                 | Run the Vitest suite                                         |
| `pnpm test:watch`           | Run Vitest in watch mode                                     |
| `pnpm check:config-version` | Fail if any `librechat.yaml` snippet has a stale `version:`  |
| `pnpm sync:config-version`  | Rewrite stale `librechat.yaml` `version:` snippets to latest |
| `pnpm analyze`              | Build and analyze the production bundle size                 |
| `pnpm optimize:images`      | Optimize images in `public/`                                 |
| `pnpm web-bot-auth:keygen`  | Generate an Ed25519 Web Bot Auth private JWK                 |
| `pnpm translate`            | Generate translations from the English source                |
| `pnpm docs:archive`         | Snapshot the English docs into `content/docs-archive`        |

The config version is sourced from the newest `content/changelog/config_v*.mdx` entry, whose
`version:` frontmatter must match its filename. Never hand-edit the `version:` line in a docs
snippet — run `pnpm sync:config-version`, which updates every `librechat.yaml` code fence under
`content/docs` (all locales included) and leaves unrelated YAML alone.

## Contributing

Contributions are welcome, from fixing a typo to writing a whole new guide.

1. Fork the repo and create a branch from `main`.
2. Make your changes and preview them locally with `pnpm dev`.
3. Before opening a PR, run `pnpm lint`, `pnpm typecheck`, and `pnpm build`.
4. Open a pull request describing what you changed and why.

For questions about the documentation, join the [Discord](https://discord.librechat.ai). For issues with the LibreChat application itself, please use the [main repository](https://github.com/LibreChat-AI/LibreChat).

## Community & Support

- 🌐 **Website:** [www.librechat.ai](https://www.librechat.ai)
- 💬 **Discord:** [discord.librechat.ai](https://discord.librechat.ai)
- 🧠 **Ask DeepWiki:** [deepwiki.com/LibreChat-AI/librechat.ai](https://deepwiki.com/LibreChat-AI/librechat.ai)
- 🚀 **Main app:** [LibreChat-AI/LibreChat](https://github.com/LibreChat-AI/LibreChat)

## License

Released under the [MIT License](./LICENSE).

---

## File: components.json

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": true,
  "tailwind": {
    "config": "tailwind.config.js",
    "css": "app/global.css",
    "baseColor": "slate",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

---

## File: package.json

{
  "name": "librechat.ai",
  "version": "1.0.0",
  "description": "librechat.ai",
  "packageManager": "pnpm@9.15.9",
  "engines": {
    "node": ">=22.0.0 <25"
  },
  "scripts": {
    "dev": "cross-env NODE_OPTIONS=--max-old-space-size=8192 next dev --webpack -p 3333",
    "build": "cross-env NODE_OPTIONS=--max-old-space-size=8192 next build --webpack",
    "postbuild": "node scripts/clean-cache.cjs",
    "start": "next start -p 3333",
    "analyze": "cross-env ANALYZE=true NODE_OPTIONS=--max-old-space-size=8192 next build --webpack",
    "optimize:images": "node scripts/optimize-images.mjs",
    "web-bot-auth:keygen": "node scripts/generate-web-bot-auth-key.mjs",
    "test": "vitest run",
    "test:watch": "vitest",
    "sync:config-version": "node scripts/sync-config-version.mjs --write",
    "check:config-version": "node scripts/sync-config-version.mjs --check",
    "docs:archive": "tsx scripts/archive-docs-version.ts",
    "typecheck": "fumadocs-mdx && tsc --noEmit",
    "lint": "eslint --cache --max-warnings 0 .",
    "lint:prettier": "prettier --cache --check --ignore-path .gitignore --ignore-path .prettierignore .",
    "prettier": "prettier --cache --write --ignore-path .gitignore --ignore-path .prettierignore .",
    "prepare": "node -e \"process.env.CI||require('child_process').execSync('husky',{stdio:'inherit'})\"",
    "translate": "npx tsx scripts/translate.ts",
    "screenshots": "tsx scripts/screenshots/capture.ts"
  },
  "homepage": "https://www.librechat.ai",
  "dependencies": {
    "@ai-sdk/react": "^3.0.143",
    "@glidejs/glide": "^3.6.0",
    "@hookform/resolvers": "^3.3.4",
    "@mdx-js/loader": "^3.1.1",
    "@mdx-js/react": "^3.1.1",
    "@openrouter/ai-sdk-provider": "^2.3.3",
    "@orama/orama": "3.1.18",
    "@orama/tokenizers": "^3.1.18",
    "@radix-ui/react-accordion": "^1.1.2",
    "@radix-ui/react-avatar": "^1.0.4",
    "@radix-ui/react-dialog": "^1.0.5",
    "@radix-ui/react-dropdown-menu": "^2.0.6",
    "@radix-ui/react-label": "^2.0.2",
    "@radix-ui/react-popover": "^1.1.15",
    "@radix-ui/react-select": "^2.0.0",
    "@radix-ui/react-separator": "^1.0.3",
    "@radix-ui/react-slot": "^1.0.2",
    "@radix-ui/react-tabs": "^1.0.4",
    "@supabase/supabase-js": "^2.86.2",
    "@upstash/ratelimit": "^2.0.8",
    "@upstash/redis": "^1.37.0",
    "@vercel/og": "^0.6.2",
    "@vidstack/react": "^1.15.6",
    "ace-builds": "^1.43.5",
    "ai": "^6.0.141",
    "ajv": "^8.18.0",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.1.1",
    "framer-motion": "^11.1.9",
    "fumadocs-core": "16.10.5",
    "fumadocs-mdx": "15.0.12",
    "fumadocs-ui": "16.10.5",
    "geist": "^1.3.1",
    "github-slugger": "^2.0.0",
    "gray-matter": "^4.0.3",
    "js-yaml": "^4.1.0",
    "lucide-react": "^0.378.0",
    "next": "16.4.0",
    "next-sitemap": "^4.2.3",
    "p-limit": "^7.3.0",
    "react": "^19.2.0",
    "react-ace": "^11.0.1",
    "react-dom": "^19.2.0",
    "react-hook-form": "^7.51.4",
    "react-hot-toast": "^2.4.1",
    "react-markdown": "^10.1.0",
    "react-social-icons": "^6.16.0",
    "react-tweet": "^3.2.1",
    "remark-gfm": "^4.0.1",
    "remark-mdx": "^3.1.1",
    "remark-parse": "^11.0.0",
    "sharp": "^0.33.3",
    "tailwind-merge": "^2.3.0",
    "tailwindcss": "^4.3.1",
    "tw-animate-css": "^1.4.0",
    "unified": "^11.0.5",
    "validator": "^13.15.23",
    "web-vitals": "^5.2.0",
    "zod": "^4.3.6"
  },
  "devDependencies": {
    "@eslint/compat": "^1",
    "@eslint/js": "^9",
    "@next/bundle-analyzer": "^15.1.4",
    "@next/eslint-plugin-next": "^15",
    "@playwright/test": "^1.58.2",
    "@tailwindcss/postcss": "^4.3.1",
    "@types/js-yaml": "^4.0.9",
    "@types/mdx": "^2.0.13",
    "@types/node": "^24.13.3",
    "@types/react": "^19.2.0",
    "@types/react-dom": "^19.2.0",
    "@types/validator": "^13.15.10",
    "autoprefixer": "^10.4.19",
    "cross-env": "^7.0.3",
    "eslint": "^9",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-import": "^2",
    "eslint-plugin-react": "^7.34.1",
    "eslint-plugin-react-hooks": "^5",
    "eslint-plugin-unicorn": "^56",
    "globals": "^15",
    "husky": "^9.0.11",
    "lint-staged": "^16.2.7",
    "playwright": "^1.58.2",
    "postcss": "^8.4.38",
    "prettier": "^3.2.5",
    "tsx": "4.22.4",
    "typescript": "^5.4.5",
    "typescript-eslint": "^8",
    "vitest": "^4.1.9",
    "webpack": "^5.104.1"
  },
  "optionalDependencies": {
    "crisp-sdk-web": "^1.0.25"
  },
  "pnpm": {
    "overrides": {
      "preact": ">=10.28.2",
      "webpack": ">=5.104.1",
      "diff": ">=5.2.2",
      "minimatch": ">=3.1.4",
      "serialize-javascript": ">=7.0.3"
    }
  },
  "nextBundleAnalysis": {
    "budget": 358400,
    "budgetPercentIncreaseRed": 20,
    "minimumChangeThreshold": 50,
    "showDetails": true
  },
  "lint-staged": {
    "*.{ts,tsx,js,jsx,mjs,cjs}": [
      "prettier --write",
      "eslint --fix"
    ]
  }
}