{"owner":"internetarchive","repo":"openlibrary","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# AGENTS.md\n\n> **Canonical guide:** [`docs/ai/README.md`](docs/ai/README.md) — read that file for full architecture, templates, data-model, and file-location details.\n\n## Quick Reference\n\n**Stack:** Python 3.14 / web.py (Infogami) + FastAPI · Templetor (legacy) / **Jinja2 (preferred for new code)** templates · jQuery, Vue 3, Lit · webpack · Solr 10\n\n> 📖 **Guides:** [`docs/ai/i18n.md`](docs/ai/i18n.md) — i18n best practices for Templetor, Jinja, and client-side strings. [`docs/ai/README.md`](docs/ai/README.md) — full architecture and data-model.\n\n> 🏗️ **FastAPI:** When working on FastAPI endpoints, always load the [FastAPI skill](https://raw.githubusercontent.com/fastapi/fastapi/refs/heads/master/fastapi/.agents/skills/fastapi/SKILL.md) and follow the existing patterns in the codebase. Don't invent new architectural patterns — match what's already there.\n\n**Dev setup:** `make git && docker compose up` → http://localhost:8080\n\n### Key Commands\n\n**Before committing**, run pre-commit on your changed files (requires Python 3.14 on host — `brew install python@3.14`):\n\n```bash\npre-commit run --files <file1> <file2> ...\n```\n\nThe `mypy` and `generate-pot` hooks will fail on the host (they need `infogami` which only lives in Docker) — that's expected. Everything else must pass. Common auto-fixes that pre-commit applies and you should do yourself first:\n\n- **Double quotes** — use `\"string\"` not `'string'` in all new Python code (the Ruff formatter enforces this)\n- **Import order** — imports must be sorted: stdlib → third-party (alphabetical within each group) → local (ruff isort enforces this)\n- **No trailing whitespace** on any line\n- **Single newline at EOF** — no blank lines at end of file\n- **Walrus operator** — prefer `if x := expr:` over `x = expr` / `if x:` (auto-walrus enforces this)\n- **Line length** — max 162 chars\n\nThe following commands should be run inside docker (with `docker compose run --rm home <command>`). The exception is `test-py-uv`, which runs faster outside Docker using `uv`:\n\n```bash\nmake test-py-uv             # Python tests (preferred — runs outside Docker with uv)\nmake test-py                # Python tests\n\n# Run a subset of Python tests by specifying a path:\nmake test-py-uv PYTEST_ARGS=\"openlibrary/tests/fastapi/\"\n# Or directly: uv run --with-requirements requirements_test.txt pytest openlibrary/tests/fastapi/\n\nnpm run test:js             # JS tests\nmake lint                   # Python lint (ruff)\nnpm run lint                # JS + CSS lint\nnpm run lint-fix            # Auto-fix JS/CSS\nnpm run watch               # Dev mode with hot reload\n```\n\n### Code Style\n\n- **Python:** Ruff for linting and `ruff format` for formatting, line length 162, double quotes\n- **JS:** ESLint, single quotes, no jQuery in new code\n- **CSS:** Stylelint — no hex/named colors, use variables\n- **i18n (Internationalization):** Do not split sentences into separate translatable strings/fragments with HTML links. Instead, use single, unified translatable strings with Python formatting placeholders (e.g. `%(link_start)s` / `%(link_end)s`) so translators can position links according to the target language's grammatical structure.\n- **Branches:** `{issue-number}/{type}/{slug}`\n\n### Entry Points\n\n| What | Where |\n|---|---|\n| App entry | `openlibrary/code.py` |\n| FastAPI | `openlibrary/asgi_app.py` |\n| Route handlers | `openlibrary/plugins/*/code.py` (legacy web.py) · **FastAPI routers** (preferred): `openlibrary/fastapi/*.py` |\n| Templates | `openlibrary/templates/` |\n| JS source | `openlibrary/plugins/openlibrary/js/` |\n| CSS source | `static/css/` |\n\n### Testing Authenticated Endpoints with curl\n\nThe dev environment has a pre-configured test user:\n\n| Property | Value |\n|----------|-------|\n| Username | `openlibrary` |\n| Password | `openlibrary` |\n| Key | `/people/openlibrary` |\n\n1. **Login to get a session cookie:**\n```bash\ncurl -s -c /tmp/cookies.txt -X POST \"http://localhost:8080/account/login.json\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\":\"openlibrary\",\"password\":\"openlibrary\"}'\n\n# View the cookie file\ncat /tmp/cookies.txt\n# Example output:\n# # Netscape HTTP Cookie File\n# localhost  FALSE   /       FALSE   0       session /people/openlibrary,2026-01-18T17:25:46,7897f\\$841a3bd2f8e9a5ca46f505fa557d57bd\n```\n\n2. **Use the session cookie in subsequent requests:**\n```bash\n# Just use -b to send the cookie automatically (no manual extraction needed)\ncurl -X POST \"http://localhost:18080/people/openlibrary/lists/OL1L/delete.json\" -b /tmp/cookies.txt\ncurl \"http://localhost:18080/people/openlibrary/lists/OL1L.json\" -b /tmp/cookies.txt\n```\n\n**Note:** Sessions expire — always login fresh before testing. Both web.py (port 8080) and FastAPI (port 18080) share the same auth system.\n\n### FastAPI and web.py Interaction\n\nOpen Library runs two web servers in parallel:\n- **web.py** (port 8080) — **Legacy** (web.py / Infogami) — no new endpoints here, use FastAPI\n- **FastAPI** (port 18080) — New async endpoints via nginx proxy\n\nWhen testing:\n- Both servers share the same database\n- Session cookies work on both (same auth system)\n- FastAPI uses ContextVars (`site.get()`) instead of `web.ctx.site`\n\nKey files for context management:\n- `openlibrary/utils/request_context.py` — Contains `site` ContextVar and other request context.\n- `openlibrary/plugins/openlibrary/code.py` — Sets up context vars in request processor\n"},"files":{"AGENTS.md":"# AGENTS.md\n\n> **Canonical guide:** [`docs/ai/README.md`](docs/ai/README.md) — read that file for full architecture, templates, data-model, and file-location details.\n\n## Quick Reference\n\n**Stack:** Python 3.14 / web.py (Infogami) + FastAPI · Templetor (legacy) / **Jinja2 (preferred for new code)** templates · jQuery, Vue 3, Lit · webpack · Solr 10\n\n> 📖 **Guides:** [`docs/ai/i18n.md`](docs/ai/i18n.md) — i18n best practices for Templetor, Jinja, and client-side strings. [`docs/ai/README.md`](docs/ai/README.md) — full architecture and data-model.\n\n> 🏗️ **FastAPI:** When working on FastAPI endpoints, always load the [FastAPI skill](https://raw.githubusercontent.com/fastapi/fastapi/refs/heads/master/fastapi/.agents/skills/fastapi/SKILL.md) and follow the existing patterns in the codebase. Don't invent new architectural patterns — match what's already there.\n\n**Dev setup:** `make git && docker compose up` → http://localhost:8080\n\n### Key Commands\n\n**Before committing**, run pre-commit on your changed files (requires Python 3.14 on host — `brew install python@3.14`):\n\n```bash\npre-commit run --files <file1> <file2> ...\n```\n\nThe `mypy` and `generate-pot` hooks will fail on the host (they need `infogami` which only lives in Docker) — that's expected. Everything else must pass. Common auto-fixes that pre-commit applies and you should do yourself first:\n\n- **Double quotes** — use `\"string\"` not `'string'` in all new Python code (the Ruff formatter enforces this)\n- **Import order** — imports must be sorted: stdlib → third-party (alphabetical within each group) → local (ruff isort enforces this)\n- **No trailing whitespace** on any line\n- **Single newline at EOF** — no blank lines at end of file\n- **Walrus operator** — prefer `if x := expr:` over `x = expr` / `if x:` (auto-walrus enforces this)\n- **Line length** — max 162 chars\n\nThe following commands should be run inside docker (with `docker compose run --rm home <command>`). The exception is `test-py-uv`, which runs faster outside Docker using `uv`:\n\n```bash\nmake test-py-uv             # Python tests (preferred — runs outside Docker with uv)\nmake test-py                # Python tests\n\n# Run a subset of Python tests by specifying a path:\nmake test-py-uv PYTEST_ARGS=\"openlibrary/tests/fastapi/\"\n# Or directly: uv run --with-requirements requirements_test.txt pytest openlibrary/tests/fastapi/\n\nnpm run test:js             # JS tests\nmake lint                   # Python lint (ruff)\nnpm run lint                # JS + CSS lint\nnpm run lint-fix            # Auto-fix JS/CSS\nnpm run watch               # Dev mode with hot reload\n```\n\n### Code Style\n\n- **Python:** Ruff for linting and `ruff format` for formatting, line length 162, double quotes\n- **JS:** ESLint, single quotes, no jQuery in new code\n- **CSS:** Stylelint — no hex/named colors, use variables\n- **i18n (Internationalization):** Do not split sentences into separate translatable strings/fragments with HTML links. Instead, use single, unified translatable strings with Python formatting placeholders (e.g. `%(link_start)s` / `%(link_end)s`) so translators can position links according to the target language's grammatical structure.\n- **Branches:** `{issue-number}/{type}/{slug}`\n\n### Entry Points\n\n| What | Where |\n|---|---|\n| App entry | `openlibrary/code.py` |\n| FastAPI | `openlibrary/asgi_app.py` |\n| Route handlers | `openlibrary/plugins/*/code.py` (legacy web.py) · **FastAPI routers** (preferred): `openlibrary/fastapi/*.py` |\n| Templates | `openlibrary/templates/` |\n| JS source | `openlibrary/plugins/openlibrary/js/` |\n| CSS source | `static/css/` |\n\n### Testing Authenticated Endpoints with curl\n\nThe dev environment has a pre-configured test user:\n\n| Property | Value |\n|----------|-------|\n| Username | `openlibrary` |\n| Password | `openlibrary` |\n| Key | `/people/openlibrary` |\n\n1. **Login to get a session cookie:**\n```bash\ncurl -s -c /tmp/cookies.txt -X POST \"http://localhost:8080/account/login.json\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\":\"openlibrary\",\"password\":\"openlibrary\"}'\n\n# View the cookie file\ncat /tmp/cookies.txt\n# Example output:\n# # Netscape HTTP Cookie File\n# localhost  FALSE   /       FALSE   0       session /people/openlibrary,2026-01-18T17:25:46,7897f\\$841a3bd2f8e9a5ca46f505fa557d57bd\n```\n\n2. **Use the session cookie in subsequent requests:**\n```bash\n# Just use -b to send the cookie automatically (no manual extraction needed)\ncurl -X POST \"http://localhost:18080/people/openlibrary/lists/OL1L/delete.json\" -b /tmp/cookies.txt\ncurl \"http://localhost:18080/people/openlibrary/lists/OL1L.json\" -b /tmp/cookies.txt\n```\n\n**Note:** Sessions expire — always login fresh before testing. Both web.py (port 8080) and FastAPI (port 18080) share the same auth system.\n\n### FastAPI and web.py Interaction\n\nOpen Library runs two web servers in parallel:\n- **web.py** (port 8080) — **Legacy** (web.py / Infogami) — no new endpoints here, use FastAPI\n- **FastAPI** (port 18080) — New async endpoints via nginx proxy\n\nWhen testing:\n- Both servers share the same database\n- Session cookies work on both (same auth system)\n- FastAPI uses ContextVars (`site.get()`) instead of `web.ctx.site`\n\nKey files for context management:\n- `openlibrary/utils/request_context.py` — Contains `site` ContextVar and other request context.\n- `openlibrary/plugins/openlibrary/code.py` — Sets up context vars in request processor\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md\n\n> **Canonical guide:** [`docs/ai/README.md`](docs/ai/README.md) — read that file for full architecture, templates, data-model, and file-location details.\n\n## Quick Reference\n\n**Stack:** Python 3.14 / web.py (Infogami) + FastAPI · Templetor (legacy) / **Jinja2 (preferred for new code)** templates · jQuery, Vue 3, Lit · webpack · Solr 10\n\n> 📖 **Guides:** [`docs/ai/i18n.md`](docs/ai/i18n.md) — i18n best practices for Templetor, Jinja, and client-side strings. [`docs/ai/README.md`](docs/ai/README.md) — full architecture and data-model.\n\n> 🏗️ **FastAPI:** When working on FastAPI endpoints, always load the [FastAPI skill](https://raw.githubusercontent.com/fastapi/fastapi/refs/heads/master/fastapi/.agents/skills/fastapi/SKILL.md) and follow the existing patterns in the codebase. Don't invent new architectural patterns — match what's already there.\n\n**Dev setup:** `make git && docker compose up` → http://localhost:8080\n\n### Key Commands\n\n**Before committing**, run pre-commit on your changed files (requires Python 3.14 on host — `brew install python@3.14`):\n\n```bash\npre-commit run --files <file1> <file2> ...\n```\n\nThe `mypy` and `generate-pot` hooks will fail on the host (they need `infogami` which only lives in Docker) — that's expected. Everything else must pass. Common auto-fixes that pre-commit applies and you should do yourself first:\n\n- **Double quotes** — use `\"string\"` not `'string'` in all new Python code (the Ruff formatter enforces this)\n- **Import order** — imports must be sorted: stdlib → third-party (alphabetical within each group) → local (ruff isort enforces this)\n- **No trailing whitespace** on any line\n- **Single newline at EOF** — no blank lines at end of file\n- **Walrus operator** — prefer `if x := expr:` over `x = expr` / `if x:` (auto-walrus enforces this)\n- **Line length** — max 162 chars\n\nThe following commands should be run inside docker (with `docker compose run --rm home <command>`). The exception is `test-py-uv`, which runs faster outside Docker using `uv`:\n\n```bash\nmake test-py-uv             # Python tests (preferred — runs outside Docker with uv)\nmake test-py                # Python tests\n\n# Run a subset of Python tests by specifying a path:\nmake test-py-uv PYTEST_ARGS=\"openlibrary/tests/fastapi/\"\n# Or directly: uv run --with-requirements requirements_test.txt pytest openlibrary/tests/fastapi/\n\nnpm run test:js             # JS tests\nmake lint                   # Python lint (ruff)\nnpm run lint                # JS + CSS lint\nnpm run lint-fix            # Auto-fix JS/CSS\nnpm run watch               # Dev mode with hot reload\n```\n\n### Code Style\n\n- **Python:** Ruff for linting and `ruff format` for formatting, line length 162, double quotes\n- **JS:** ESLint, single quotes, no jQuery in new code\n- **CSS:** Stylelint — no hex/named colors, use variables\n- **i18n (Internationalization):** Do not split sentences into separate translatable strings/fragments with HTML links. Instead, use single, unified translatable strings with Python formatting placeholders (e.g. `%(link_start)s` / `%(link_end)s`) so translators can position links according to the target language's grammatical structure.\n- **Branches:** `{issue-number}/{type}/{slug}`\n\n### Entry Points\n\n| What | Where |\n|---|---|\n| App entry | `openlibrary/code.py` |\n| FastAPI | `openlibrary/asgi_app.py` |\n| Route handlers | `openlibrary/plugins/*/code.py` (legacy web.py) · **FastAPI routers** (preferred): `openlibrary/fastapi/*.py` |\n| Templates | `openlibrary/templates/` |\n| JS source | `openlibrary/plugins/openlibrary/js/` |\n| CSS source | `static/css/` |\n\n### Testing Authenticated Endpoints with curl\n\nThe dev environment has a pre-configured test user:\n\n| Property | Value |\n|----------|-------|\n| Username | `openlibrary` |\n| Password | `openlibrary` |\n| Key | `/people/openlibrary` |\n\n1. **Login to get a session cookie:**\n```bash\ncurl -s -c /tmp/cookies.txt -X POST \"http://localhost:8080/account/login.json\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\":\"openlibrary\",\"password\":\"openlibrary\"}'\n\n# View the cookie file\ncat /tmp/cookies.txt\n# Example output:\n# # Netscape HTTP Cookie File\n# localhost  FALSE   /       FALSE   0       session /people/openlibrary,2026-01-18T17:25:46,7897f\\$841a3bd2f8e9a5ca46f505fa557d57bd\n```\n\n2. **Use the session cookie in subsequent requests:**\n```bash\n# Just use -b to send the cookie automatically (no manual extraction needed)\ncurl -X POST \"http://localhost:18080/people/openlibrary/lists/OL1L/delete.json\" -b /tmp/cookies.txt\ncurl \"http://localhost:18080/people/openlibrary/lists/OL1L.json\" -b /tmp/cookies.txt\n```\n\n**Note:** Sessions expire — always login fresh before testing. Both web.py (port 8080) and FastAPI (port 18080) share the same auth system.\n\n### FastAPI and web.py Interaction\n\nOpen Library runs two web servers in parallel:\n- **web.py** (port 8080) — **Legacy** (web.py / Infogami) — no new endpoints here, use FastAPI\n- **FastAPI** (port 18080) — New async endpoints via nginx proxy\n\nWhen testing:\n- Both servers share the same database\n- Session cookies work on both (same auth system)\n- FastAPI uses ContextVars (`site.get()`) instead of `web.ctx.site`\n\nKey files for context management:\n- `openlibrary/utils/request_context.py` — Contains `site` ContextVar and other request context.\n- `openlibrary/plugins/openlibrary/code.py` — Sets up context vars in request processor\n","category":"root","tokens":1350}]}