Thanks for your interest! This doc covers how to set up your local environment so commits and pushes pass CI on the first try.
Before a pull request can be merged, every human author of a commit in the pull request must have accepted the CubePlex Individual Contributor License Agreement. The first time you contribute, the CLA check will explain what is needed. To sign, post this exact comment on the pull request:
I have read and agree to the CubePlex Contributor License Agreement
The signature is recorded in the private cubeplex-cla
repository and reused for later CubePlex pull requests. You only need to sign
again when the CLA version changes. Contributions made on behalf of an employer
or another legal entity require a Corporate CLA; contact the maintainers before
submitting that contribution. Bots and automated commits are allowlisted by
the check.
The agreement keeps copyright ownership with the contributor while granting
CubePlex the rights needed to distribute community code under the CubePlex
Community License and code under the applicable Enterprise terms in
any directory named exactly ee. Copies, modifications, and compiled forms of
those Enterprise components remain covered even if they are moved outside an
ee directory.
Maintainers: the CLA workflow requires the CUBEPLEX_CLA_TOKEN repository
secret with write access to cubeplexai/cubeplex-cla. Do not commit that token
or put it in the public repository.
- Python 3.12+
- Node.js 20+
- pnpm 10+
- Docker (for running PostgreSQL / Redis / RustFS locally, optional)
git clone https://github.com/cubeplexai/cubeplex.git
cd cubeplex
# Agent skills — restore vendored skills (content + symlinks) from skills-lock.json
make skills-restore
# Backend
cd backend
make dev-install
make pre-commit-install-all # installs both pre-commit and pre-push hooks
cd ..
# Frontend
cd frontend
pnpm install
npx playwright install # only if you plan to run e2e locally
cd ..Skills live in .agents/skills/ and are symlinked into .claude/skills/. Two
kinds, tracked differently — .gitignore ignores everything under those dirs
and whitelists only the native skills, so adjusting the lock never touches
.gitignore:
-
Vendored skills — installed from a GitHub source via
npx skills. Only theirskills-lock.jsonentry is committed; their content and their.claude/skillssymlinks are gitignored and regenerated bymake skills-restore. Add / remove one with:npx skills add <owner/repo> -s <skill-name> # updates skills-lock.json npx skills remove <skill-name> # updates skills-lock.json
Nothing else to do — no
.gitignoreedit. (experimental_installonly restores content; in this single-agent repo it copies without symlinking, somake skills-restorewires the.claude/skillssymlinks afterward.) -
Native skills — hand-authored, cubeplex-specific (
feature-workflow,cubeplex-tdd,debug-cubeplex,pr-codex-review-loop). These are committed — their.agents/skills/<name>/content is the source of truth. Create one withnpx skills init <name>or by hand, then whitelist it in.gitignorewith two lines (!.agents/skills/<name>/and!.claude/skills/<name>) so it gets tracked.
We use pre-commit with two stages and a strict no-auto-fix policy — hooks only check, they never rewrite your files:
-
pre-commit (runs on
git commit, ~10 seconds):- File hygiene checks: large file (>500 KB), YAML / JSON / TOML validity, merge conflict markers, accidentally-committed private keys, stray
pdb/breakpoint()calls - Ruff
check --no-fixandruff format --checkon staged Python files - ESLint (no
--fix) and Prettier--checkon staged frontend files
- File hygiene checks: large file (>500 KB), YAML / JSON / TOML validity, merge conflict markers, accidentally-committed private keys, stray
-
pre-push (runs on
git push; only the sides that changed):- Backend
make check-ci(ruff + ruff-format + mypy + pytest unit) when the push includes backend code. Markdown underbackend/does not count. - Frontend
make check-ci(core build, lint, format, type-check, vitest,next build) when the push includes frontend code. Markdown underfrontend/does not count. - Changing the root
Makefileor.pre-commit-config.yamlruns both, because those files are the gate. - Docs-only and unrelated paths (
docs/,scripts/,deploy/, …) skip both checks. GitHub CI still runs the full suite on the PR.
- Backend
If a hook fails, the hook does NOT modify your files. Run the appropriate formatter manually and re-stage:
# Backend format issues
cd backend && make format && git add -u
# Frontend format issues
cd frontend && pnpm format && git add -uEvery PR runs 4 jobs: backend-check, frontend-check, e2e, test-ee-compat. All must pass before merge. Full spec: docs/dev/specs/2026-04-21-ci-baseline-design.md.
- Line length: 100 chars (Python and TS)
- Python: ruff format (double quotes), mypy strict
- TS: Prettier (single quote, no semi, 100 width), ESLint
# Backend dev server
cd backend && python main.py
# Frontend dev server
cd frontend && pnpm dev
# Run backend unit tests
cd backend && make check-ci
# Run frontend tests
cd frontend && pnpm -r testCutting a production or self-hosted release (version bump, tag, images, Helm chart, GitHub Release, and the user-facing deploy-doc snippets) is documented in docs/releasing.md. Do not put that process on the user-facing docs site.