AGENTS.md — orientation for AI coding agents on vibe-qc¶
This file is for any AI coding assistant working on this repo
(aider + DeepSeek / Llama / GPT, Claude Code, Cursor, …). It is
the single entry point: read this first, then follow the
pointers below. If you are a Claude Code session, also read
CLAUDE.md in full — it carries the same project
rules with Claude-specific detail.
Keep this file accurate when the project shifts; it is committed and shared across every contributor and agent.
What vibe-qc is¶
vibe-qc is a quantum-chemistry code for molecules and solids — a Python frontend over a C++17 core. It computes electronic-structure energies, gradients, and properties:
Molecular — RHF / UHF, RKS / UKS DFT (all of libxc’s 500+ functionals), RMP2 / UMP2, analytic nuclear gradients, D3(BJ) dispersion, post-SCF properties. Validated against PySCF to machine precision.
Periodic — 1D / 2D / 3D Hartree–Fock and KS-DFT, Monkhorst–Pack k-meshes, Ewald summation, band structure + DOS. Stable in the molecular-limit regime; being hardened for tight-cell bulk work.
Long-term target — the cyclic cluster model (CCM) for solids (the
v2.0feature). Seedocs/roadmap.md.
The native numerical core links libint (Gaussian integrals),
libxc (XC functionals), spglib (crystal symmetry),
libecpint (ECP integrals), FFTW3 (FFT), Eigen, and
pybind11 — all vendored under third_party/ by
scripts/setup_native_deps.sh. Licensed MPL 2.0.
Naming: the brand is vibe-qc (hyphen), the Python package is
import vibeqc (no hyphen). Same code, two spellings. Not on
PyPI yet — install is `git clone + ./scripts/setup_native_deps.sh
pip install -e .
perdocs/installation.md`.
Repo map — where things live¶
python/vibeqc/ Python API. Molecular + periodic drivers, ASE
integration, I/O, banner, SCF-log formatting.
runner.py molecular run_job / run_rhf / run_rks / … entry
molecule.py Atom, Molecule
periodic_runner.py periodic SCF entry
periodic_*_dispatch.py RHF / RKS driver dispatch (Ewald vs GDF paths)
periodic_*.py periodic Fock / density / gradient / GDF blocks
kpoints.py Monkhorst–Pack meshes, IBZ reduction, band paths
ase.py / ase_periodic.py ASE Calculator integration
banner.py runtime version banner (vibe-qc + linked libs)
scf_log.py / structured_log.py .out / NDJSON output formatting
basis_crystal.py CRYSTAL-format basis-set parser
basis_library/ bundled basis sets (.g94); ecp_library/ for ECPs
output/ unified output infrastructure
plan.py OutputPlan, OutputRole, OutputFormat, PlannedFile
writer.py OutputWriter — per-job coordinator, owns manifest
manifest.py ManifestUpdater, FileOutcome — .system TOML lifecycle
formats/ per-format writers (xyz, molden, cube, cif, …)
qvf.py QVF (.qvf) writer + validator + CLI
qvf_manifest.schema.json JSON Schema for manifest.json
cpp/include/vibeqc/ C++17 public headers (integrals, SCF, DFT grid, …)
cpp/src/ C++17 implementation
bindings.cpp pybind11 bindings — THE Python <-> C++ boundary
rhf.cpp uhf.cpp rks.cpp uks.cpp molecular SCF kernels
integrals.cpp ecp.cpp df.cpp integral kernels
periodic_*.cpp periodic Fock / SCF / gradient / XC
ewald.cpp fft_poisson.cpp lattice_sum.cpp periodic Coulomb
diis.cpp guess.cpp linear_dependence.cpp SCF convergence machinery
tests/ pytest regression suite — every commit must pass
docs/ Sphinx + Furo docs site (deployed at vibe-qc.com)
handovers/ long-lived per-workstream handover trackers (see rule 10);
handovers/README.md is the index
examples/ runnable example scripts (molecular/ periodic/ …)
studies/ research studies (e.g. asbestos-polymorphs)
scripts/ setup_native_deps.sh + per-dep build helpers
third_party/ vendored native deps (gitignored, build artifact)
vibe-queue/ co-located `vq` job-queue tool — SEPARATE sub-project
with its own pyproject.toml; don't entangle it with
the QC core unless the task is explicitly about vq.
When you need to find something:
Looking for… |
Start at |
|---|---|
How to produce a visualisation archive |
|
How to work with basis sets |
|
How to invoke a calculation |
|
Molecular SCF math |
|
Periodic SCF math |
|
The Python↔C++ API surface |
|
A concept explained for users |
|
What’s known-broken right now |
|
What’s planned |
|
Per-component licensing |
|
Build, test, docs¶
# one-time: fetch + build vendored native deps (15-40 min, idempotent)
./scripts/setup_native_deps.sh
# editable install into a project-local venv
python3 -m venv .venv
.venv/bin/pip install -e '.[test]'
# verify
.venv/bin/python -c "from vibeqc import print_banner; print_banner()"
.venv/bin/python -m pytest tests/ # must pass before any commit
# docs
sphinx-build -b html docs/ docs/_build/html
Requires Python 3.11+ and a C++17 compiler. Full per-platform
dependency lists are in docs/installation.md.
Code style¶
C++17. Four-space indent, brace on the same line for control flow. Everything in
cpp/lives undernamespace vibeqc { … }. Matchcpp/src/rhf.cpp/cpp/src/integrals.cpp.Python 3.11+. PEP 8, four-space indent. Start every module with
from __future__ import annotations. Type hints on public API; local helpers may skip them.Prefer editing existing modules over adding new ones. If a new file is genuinely the right call, follow the neighbours’ layout.
Don’t add dependencies casually — new native deps need a roadmap conversation; new Python deps belong in optional extras.
Full contributor note: CONTRIBUTING.md.
Project rules an agent MUST follow¶
These are non-negotiable. The authoritative, fully-explained version
is CLAUDE.md — read it. Condensed:
Licensing discipline. vibe-qc is MPL 2.0 and ships to academic
open-source users. Before bundling/vendoring/fetching any new data or dependency, check redistribution terms. When unclear, don’t bundle — use the on-demand fetcher pattern. Escalate licensing questions to the maintainer.
No imports from other QC programs. vibe-qc has its own implementation of every method it ships. Never add
import pyscf(or psi4, orca, cp2k, vasp, nwchem, gamess, …) to anything underpython/vibeqc/orcpp/. Libraries (libint, libxc, spglib, libecpint, Eigen, FFTW3, pybind11, ASE, NumPy, SciPy) are linkable building blocks and fine. The litmus test: “does this run on its own as a QC program?” If yes, it’s forbidden as a runtime import. Parity testing against external programs is done out-of-process via subprocess runners (examples/regression/runner_<program>.py).Branch model + push discipline.
mainis active development;releaseis fast-forward-only public. To push:git fetch,git pull --rebase origin main, thengit push origin HEAD:main. Never force-pushmain/release, nevergit commit --amenda pushed commit, never skip pre-commit hooks (--no-verify) unless the maintainer explicitly asks.Every commit ships green. Pre-commit hooks pass, tests pass, CI passes. If a hook fails, fix the cause — don’t bypass it. Activate the personal-info hook once per clone:
git config --local core.hooksPath .githooks. CI status is queryable from the CLI:glab api "projects/19/pipelines?per_page=5"(numeric project id; theglab cisubcommands 404 against this instance). Full recipe:CLAUDE.md§ 2 “Checking CI after a push”.Periodic SCF oscillation = a bug, not a convergence problem. If a periodic SCF oscillates or lands at an impossible energy, don’t paper over it with damping / level-shift / quadratic fallback / threshold-tuning. Reproduce against a reference, find the gauge / Madelung / image-summing root cause, file a regression test.
Privacy hygiene. The repo is public. Never commit credentials, real IP addresses, or author home paths (
/Users/<name>/…,/home/<name>/…) — use~/,<vibe-qc-checkout>, or a placeholder. The maintainer identity in repo content ismpei@vibe-qc.comand nothing else.Scope discipline — escalate, don’t decide unilaterally. No grand refactors without maintainer approval. Stop and ask the maintainer on: licensing questions, branch-policy edge cases, CHANGELOG/release-note wording, anything contradicting a rule above, or anything you’d describe as “pretty sure this is fine but…”. Asking is cheap; wrong-and-pushed is expensive.
Citation database ownership. Any merge that adds, removes, or renames a method, functional, basis set, ECP, dispersion model, or third-party linked library to vibe-qc MUST update the citation database at
python/vibeqc/output/citations/database.tomlin the same merge:add or remove the matching
[entries.<key>]block,add, update, or remove the matching route under
[routes.<category>](software/integrals/basis_sets/functionals/methods/libraries),extend
tests/test_citations.pyso the feature triggers the expected references (the_REQUIRED_FUNCTIONALS/_REQUIRED_BASIS_SETSparametrised lists are the belt-and-braces coverage gate — add yours).
The database is the single source of truth:
docs/citing.mdanddocs/user_guide/functionals.md § Citationswill be auto-rendered from it (Sphinx directive, Phase O7). Do not hand-edit those sections to introduce new references — update the database, and the docs follow.On the
basissetdevbranch the 87 BSE-fetched basis sets get a siblingdatabase_basissetdev.toml; that file does not exist onmain(per rule 4 ofCLAUDE.md, basissetdev does not merge into main for v0.8.x).Full schema + the runtime assembly contract live in
docs/design_output_module.md. Skipping this rule means published runs will silently omit a reference and the maintainer has to chase the gap after the fact — please don’t.Companion PDF library (optional). If a
../librarysibling repo is present — the maintainer’s reference-PDF library, the physical counterpart ofdatabase.toml— and you add a citation whose paper isn’t already there, append its DOI to../library/download-doi.txt: a comment line plus the bare DOI under the matching# === <topic> ===section (format per that repo’sREADME.md). That file is your only write target — never commit, fetch PDFs, run its sync scripts, or modify anything else in that repo; the maintainer acquires PDFs separately. Skip silently if../libraryisn’t present.Stay wired into
main— land small, ship release-ready. Land work in small milestones that each leavemaintag-able, not merely compiling. The 0.8.x / 0.9 releases hurt because chats drifted and landed half-finished work the release chat then had to audit. Before every push, verify repo-wide: full build + full test suite green, CI green onmain, no half-finished code paths, incomplete features self-gated (flag / experimental marker / basissetdev-conditional) with the decision documented, CHANGELOG[Unreleased]accurate (claim only what is done and tested), and docs in parity this milestone. After everygit pull --rebase, review what other chats landed (git log <last-sync>..origin/main) and re-test if it touches your area — a clean rebase catches textual conflicts only, not a changed API or behaviour. Keep a persistent handover file current (the.release-status/drop-box, orhandovers/HANDOVER_<TOPIC>.md) so another session can resume cold. Full detail:CLAUDE.md§ 14.Handovers live in
handovers/— keep them there, retire when done. Long-lived per-workstream trackers live in the top-levelhandovers/directory, one file per workstream namedHANDOVER_<TOPIC>.md, indexed byhandovers/README.md. Rules:Do not create handovers at the repo root, and do not put them under
docs/. They are dev coordination artifacts, not user docs, and the.githooks/check_no_em_dashes.pypre-commit hook bans em/en dashes in the prose of anydocs/**/*.md(it scans the full staged content, so even moving or path-editing a dash-bearing file underdocs/trips it).handovers/is deliberately outside that scope. New handover →handovers/HANDOVER_<TOPIC>.md; add a line tohandovers/README.md.Retirement = deletion (not archival) once the workstream is complete and landed: the record stays in git history (
git log --all -- handovers/HANDOVER_<TOPIC>.md). Before deleting, grep repo-wide for inbound references (code / tests / docs /CLAUDE.md/ CHANGELOG[Unreleased]); a handover that code still cites by name is kept until those anchors are repointed. Precedent:535ed7f0,58d84f4c.Reference handovers by their
handovers/…path from code comments and docs. Never point a user-facing error/warning string at a handover — send users todocs/user_guide/instead; handovers are internal.
Known-broken — check before trusting numbers¶
The current set of known bugs and workarounds lives in
docs/index.md (the “Open in the v0.7.x
maintenance window” admonition) and CHANGELOG.md.
It moves fast — read it there rather than trusting a list here.
As of this writing the high-impact open items are the dense-crystal
periodic-XC error on overlapping-image ionic cells, the incomplete
CASSCF analytic nuclear gradient, and the gated GAPW / slab-Ewald /
BIPOLE-gradient numerical issues tracked in
handovers/HANDOVER_OPEN_BUGS_V014.md. The old f-shell RHF-gradient
and current-build DF l >= 1 auxiliary-kernel failures are fixed and
have active regression coverage (a stale libint install can still
reproduce the historical DF crash). Always check the live inventory.
See also¶
CLAUDE.md— full project standing rules.CONTRIBUTING.md— code style, commits, MR process.docs/roadmap.md— milestone ladder v0.1 → v2.0.docs/release_process.md— branch model, release procedure, documentation cadence.docs/license.md— full licensing inventory.docs/design_qvf_format.md— QVF format specification (container, manifest, kind registry, consumer contract).docs/handover_qvf_writer.md— QVF writer implementation status, progress, next steps.docs/consumer_qvf_reference.md— Python reference showing how to open a .qvf, verify sha256, extract structure + density.vibe-view/HANDOVER.md— QVF consumer (GPU-accelerated 3D viewer) status and progress.docs/using_claude.md— how end users drive vibe-qc calculations through an AI assistant (distinct from this file, which is for agents editing the code).