<!-- claude-slack-attribution -->
_Requested by **roshan desai** · [Slack
thread](https://onyx-company.slack.com/archives/C07V90R4GTX/p1792009768004209?thread_ts=1792009768.004209&cid=C07V90R4GTX)_
Before: an agent could start work on a stale branch or an old `main`, so
it read an out-of-date feature map (`.agents/feature-map/`) and missed
recent changes.
After: at session start, Claude Code and Codex fetch `origin/main` and
tell the agent to rebase on it only when the branch has merge conflicts
with `origin/main` or its merge base with `origin/main` is more than 3
days old. Otherwise the hook is silent. Keeping a branch current avoids
a much more involved conflict resolution later.
This adds a SessionStart hook that, when it fires, reports how far HEAD
is behind `origin/main`, why (conflicts, stale, or both) and which
`.agents/` files changed on main since the branch diverged. A branch
that already contains `origin/main`, or is only a few recent commits
behind without conflicts, gets no message.
How: `.agents/hooks/ensure_latest_main.py` runs `git fetch origin main`
(20 second limit, no credential prompts) and checks for conflicts with
`git merge-tree --write-tree HEAD origin/main` (exit 1) and for
staleness (merge-base commit date older than `_STALE_AFTER_DAYS = 3`),
and prints a message that the agent reads as context only if either
applies. It never rebases, pulls or touches the working tree, and it
always exits 0, so an offline or failed fetch only adds a note. It is
wired for the `startup` and `resume` sources in `.claude/settings.json`
and `.codex/hooks.json`. Other agents (for example Cursor, which has no
hook config in this repo) get the same rule as a line in `AGENTS.md`.
Set `ONYX_SKIP_MAIN_SYNC_CHECK=1` (or `true`, `yes`, `on`) to turn it
off; `0` or `false` leaves it on. It also repeats the check, fetching at
most once an hour, on later prompts.
## How Has This Been Tested?
External dependency tests
(`backend/tests/external_dependency_unit/scripts/test_ensure_latest_main_repos.py`,
run by the `scripts` group of the PR workflow) run the script against
throwaway git repos: up to date, fresh and clean (silent), merge base
older than 3 days (warns), conflicting (warns), a dirty or
untracked-only tree, an offline remote, malformed payloads,
skip-variable values, fetch throttling, and a directory that is not a
repo. All exit 0 and leave the working tree unchanged. A stubbed unit
test (`backend/tests/unit/scripts/test_ensure_latest_main.py`) covers
the ssh command handling. `ruff` and `mypy --strict` pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01TYt2dm3XFyAdzZygsG6CN7
---
_Generated by [Claude
Code](https://claude.ai/code/session_01TYt2dm3XFyAdzZygsG6CN7)_
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Agents now check at session start and on later prompts whether their
checkout conflicts with `origin/main` or is stale, so they stop working
from an outdated `.agents/feature-map/` and missing recent changes.
- Claude Code and Codex run a new hook that fetches `origin/main` and
tells the agent how to update, without ever pulling, rebasing, or
touching the working tree.
- The hook speaks only when the branch has merge conflicts with
`origin/main` (via `git merge-tree --write-tree`) or its merge base is
more than 3 days old; a branch that is merely a few recent commits
behind stays silent. It always exits 0, so offline or hanging fetches
degrade gracefully, and on prompts it fetches at most once an hour. Set
`ONYX_SKIP_MAIN_SYNC_CHECK` to a truthy value to disable it. When a
merge or rebase is already in progress, it tells the agent to finish or
abort it instead of starting another update.
- Other agents without hook config get the same rule in `AGENTS.md`, and
the suggested update command uses an explicit refspec so it works in
single-branch clones.
- Git-repo integration tests run under the external dependency test
group; the unit file keeps the one fully stubbed test.
<sup>Written for commit ad0de70fed.
Summary will update on new commits.</sup>
<a
href="https://cubic.dev/pr/onyx-dot-app/onyx/pull/16043?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="View guided diff"
src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a>
<a
href="https://www.cubic.dev/action/auto-fix/pr/onyx-dot-app/onyx/16043?returnTo=https%3A%2F%2Fgithub.com%2Fonyx-dot-app%2Fonyx%2Fpull%2F16043&source=description"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img
alt="Turn on auto-fix"
src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added checks at session start and during later prompts to flag
branches that may conflict with `main` or have an outdated merge base,
with guidance for updating. Checks use the last known remote state if
fetching fails and do not change the working tree.
* Prompt-triggered fetches are limited to once per hour.
* **Documentation**
* Added guidance for keeping work up to date while preserving
uncommitted changes.
* **Tests**
* Added coverage for up-to-date, stale, conflicting, offline, and other
branch scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude <noreply@anthropic.com>
9.5 KiB
PROJECT KNOWLEDGE BASE
This file provides guidance to AI agents when working with code in this repository.
KEY NOTES
- Python deps live in a
uv-managed virtualenv at.venv(repo root). If it doesn't exist yet, create it withuv sync --frozen, thensource .venv/bin/activate. - Test secrets (API keys etc.) are resolved by
backend/tests/utils/aws_secrets.py, in order: process env vars → the gitignored.vscode/.env(also used by the pytest commands inbackend/AGENTS.md; create it by copying.vscode/env_template.txt) → AWS Secrets Manager (requiresaws sso login). Tests declare what they need via@pytest.mark.secrets(TestSecret.X). If a key you need still can't be resolved, ask the user rather than skipping tests. - If using
playwrightto explore the frontend, log in with usernameadmin_user@example.comand passwordTestPassword123!(the admin user created by the playwright global setup — seeweb/tests/e2e/constants.ts). If it doesn't exist yet, register it via the signup page; the first user registered automatically becomes admin. The app can be accessed athttp://localhost:3000. - You should assume that all Onyx services are running. To verify, you can check the
backend/logdirectory to make sure we see logs coming out from the relevant service. - To connect to the Postgres database, use:
PGPASSWORD="${POSTGRES_PASSWORD:-password}" psql -h "${POSTGRES_HOST:-localhost}" -U postgres -c "<SQL>". This works on a host checkout and inside the devcontainer. If nopsqlclient is available, fall back todocker exec onyx-relational_db-1 psql -U postgres -c "<SQL>"(no-it— agent shells have no TTY). - When making calls to the backend, always go through the frontend. E.g. make a call to
http://localhost:3000/api/personanothttp://localhost:8080/api/persona - If
.agents-local.mdexists at the repo root and its rules are not already in your context, read and follow it. It carries developer-local agent guidance and is never committed. - Before you start work, check that your branch does not need a rebase on
origin/main. Rebase if the branch has merge conflicts with main. Rebase if the branch is stale: more than 3 days since it diverged from or last synced with main. Keeping a branch current prevents a much more involved conflict resolution later. Claude Code and Codex run this check at session start and on later prompts. The hook is.agents/hooks/ensure_latest_main.py. It fetches at most once an hour. It is silent unless a rebase is needed. Other agents: rungit fetch origin +refs/heads/main:refs/remotes/origin/main. Check for conflicts withgit merge-tree --write-tree HEAD origin/main. Exit status 1 means conflicts. Other non-zero codes are errors, not conflicts. Check the age withgit show -s --format=%cr $(git merge-base HEAD origin/main). To update, rungit rebase origin/main. Usegit merge origin/mainfor a shared branch. Onmain, rungit pull --ff-only origin main. If a merge or rebase is already in progress, finish it or abort it first. Never discard uncommitted changes to do this.
Project Overview
Onyx (formerly Danswer) is an open-source Gen-AI and Enterprise Search platform that connects to company documents, apps, and people. It features a modular architecture with both Community Edition (MIT licensed) and Enterprise Edition offerings.
Technology Stack
- Backend: Python 3.13, FastAPI, SQLAlchemy, Alembic, Celery
- Frontend: Next.js 16, React 19, TypeScript, Tailwind CSS
- Database: PostgreSQL with Redis caching
- Search: OpenSearch-backed keyword and vector document index
- Auth: OAuth2, SAML, multi-provider support
- AI/ML: LangChain, LiteLLM, multiple embedding models
Repository Layout & Sub-project Guides
Each sub-project has its own agents file with the standards for that area — read it before working there:
backend/— FastAPI app + Celery workers.onyx/is the Community Edition core,ee/mirrors its layout for Enterprise features,alembic/holds migrations,tests/the test suites. Standards (Celery, migrations, testing, error handling, LLM tracing):backend/AGENTS.md.web/— Next.js frontend. Standards (also coverdesktop/, the Tauri shell):web/AGENTS.md.mobile/— React Native + Expo app. Standards:mobile/AGENTS.md. Mobile differs from web on several points (no DOM, NativeWind, expo-router), so do not assume the web rules apply there.
Explore the tree with ls rather than relying on docs for the full package list.
Feature Map
.agents/feature-map/ maps the product: every surface, what it does, the code behind
it, and how the parts connect. Use it before you change a product surface, when you
review a diff or PR, and when you need to know what a feature does or what a change
can break. The feature-map skill (.agents/skills/feature-map/SKILL.md) gives the
procedure.
- Look up a code path in
.agents/feature-map/PATHS.mdto find its component. - The step-by-step review procedure is
.agents/feature-map/VERIFYING.md. - Onyx overloads words such as Persona, Tool, turn, and SearchDoc. Read
.agents/feature-map/GLOSSARY.mdbefore trusting a name.
If you change behaviour a component document describes, update that document in the
same pull request. The feature-map-integrity pre-commit hook fails when a file the
map cites is renamed or deleted.
Skills
Shared agent skills live in .agents/skills/. .claude/skills, .cursor/skills and
.codex/skills are symlinks to it, so add or edit skills only in .agents/skills/.
Code Quality
# Install and run pre-commit hooks
pre-commit install
pre-commit run --all-files
# Faster: run only on the files you touched
pre-commit run --files <path> [<path> ...]
Claude Code and Codex also run pre-commit on the files you changed in a turn when
you end it (.agents/hooks/pre_commit_on_stop.py, wired as UserPromptSubmit and
Stop hooks in .claude/settings.json and .codex/hooks.json). Files that were
already dirty when the turn started are skipped unless you change them. Codex runs
the hooks only after you trust the project .codex/ layer. If pre-commit fails, fix
the reported problems before you finish. When the repo has the feature map
(.agents/feature-map/stale_docs.py), the same hook also names any feature-map
component whose code the turn changed but whose document the branch did not. Update
the document if your change alters what it states.
NOTE: Always make sure everything is strictly typed (both in Python and Typescript).
NOTE: Keep code comments brief and focused on information that stays relevant long-term.
Writing
These rules apply to all prose you write: docs, commit messages, PR descriptions, reports, and replies.
Follow ASD-STE100 Simplified Technical English for technical text:
- Use approved words only. Each word has one meaning.
- Use one word for one idea. Do not use two words for the same thing.
- Write short sentences. Use 20 words or less for instructions.
- Use active voice. Write "Turn the switch", not "The switch must be turned".
- Write short paragraphs. Keep one topic in each paragraph.
- Keep code comments focused on information that is relevant long-term or for future readers.
Testing
There are 4 main types of tests: unit, external dependency unit, integration, and playwright e2e
(web/tests/e2e). Commands and guidance for all four live in backend/AGENTS.md; shared fixtures
and deeper detail in backend/tests/README.md. Prefer integration tests over the other types.
Logs
When (1) writing integration tests or (2) doing live tests (e.g. curl / playwright) you can get access
to logs via the backend/log/<service_name>_debug.log file. All Onyx services (api_server, web_server, celery_X)
will be tailing their logs to this file.
Security Considerations
- Never commit API keys or secrets to the repository
- Use the encrypted credential storage for connector credentials
- Follow existing RBAC patterns for new features
Creating a Plan
When creating a plan in the plans directory (gitignored — create it if it doesn't exist), make sure to
include at least these elements:
Issues to Address What the change is meant to do.
Important Notes Things you come across in your research that are important to the implementation.
Implementation strategy How you are going to make the changes happen. High level approach.
Tests What unit (use rarely), external dependency unit, integration, and playwright tests you plan to write to verify the correct behavior. Don't overtest. Usually, a given change only needs one type of test.
Do NOT include these: Timeline, Rollback plan
This is a minimal list - feel free to include more. Do NOT write code as part of your plan. Keep it high level. You can reference certain files or functions though.
Before writing your plan, make sure to do research. Explore the relevant sections in the codebase.
Reuse Existing Standards
Before you add a helper, utility, pattern or convention, search the codebase for one that does the same job, and use it. For example, use the existing rate limiting, caching, URL validation, router and settings patterns. Do not invent a parallel mechanism. If the existing one does not do enough, extend it so other callers get the change too. A new pattern needs a reason that the existing ones cannot meet.
Best Practices
In addition to the other content in this file, best practices for contributing
to the codebase can be found in the "Engineering Best Practices" section of
CONTRIBUTING.md. Understand its contents and follow them.