AGENTS.md · juggler-ai/juggler
AGENTS.md from juggler-ai/juggler: 309 lines covering Build / Test / Lint / Dev, Linting, Tests, Git commits and more.
Template by juggler-ai
Install
Works with Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code. Read the repository before you give any tool access to your data.
curl -fsSL https://raw.githubusercontent.com/juggler-ai/juggler/develop/AGENTS.md -o AGENTS.md
Read it and adapt it to your project before use.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: code-generation, testing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
What's in it
An AGENTS.md file: instructions coding agents (Codex, Cursor, Copilot, Gemini CLI and others) read before working in a repo.
- For
- Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Claude Code
- Length
- 309 lines
- File
AGENTS.md
Sections
- Build / Test / Lint / Dev
- Linting
- Tests
- Git commits
- Changelog
- Conventions
- Architecture
- Web UI
- Debugging the viewer
- Paths
- Vendored forks
First lines (shown under the repo's AGPL-3.0 license)
# Juggler ## Build / Test / Lint / Dev ```bash make build # Lint + build Go binaries (bin/juggler, bin/juggler-app, bin/juggler-test) make test # All tests (unit + integration + browser); RUN='<name>' runs one make go-build # Build Go binaries only (skip linting) make test-full # Lint + tests. Run before opening a PR. make lint # All linters (Go + JS + CSS) — the only way to lint everything make fix # Auto-fix what the linters can (gofmt, eslint/stylelint --fix); then re-lint make dev # Build and run server make build-windows # Cross-compile bin/windows/*.exe (pure-Go, no cgo) ``` `make test-full` (lint, build and every test) **must** pass before any task is complete; iterate with `make test RUN='<name>'`. `make build` is for launching the app — `make test` already builds everything it tests. ### Run them in the foreground They are ordinary commands that take a few minutes (`make test` is typically 3–6). Run the bare command with a timeout long enough to cover it — 20 minutes — and wait for it to finish. **Never** start a build or test run as a background task, poll it, watch it with a monitor, wait on its pid, or loop until the process exits. It gains nothing: you get the identical output several turns later, having spent those turns guessing an interval — too short burns turns, too long stalls the task, and "wait for the process to disappear" wedges on the first thing that outlives it. If a run genuinely exceeds the timeout, that is a hang worth reporting, not a reason to relaunch it detached. **Never pipe them through `tail`, `head`, `grep` or `tee`, redirect them to a file and read it back, or append `|| true`.** The output is already the summary (see Tests below), and `tail` is the worst choice of the lot: a failure is written top-down, so truncating to the tail keeps the summary line you already had and cuts the assertion that says what broke. ## Linting - **`make lint` and `make lint-files` are the only sanctioned ways to lint.** Never invoke `golangci-lint`, `go vet`, `gofmt`, `eslint`, or `stylelint` directly — every config, flag, ignore pattern, and pinned tool version lives in the `Makefile` / `scripts/lint-files`, and a hand-rolled invocation silently diverges from what CI enforces. - To lint specific files (routed by extension to the same linters): ```bash make lint-files FILES="cmd/juggler/worker/foo.go web/js/bar.js" ``` - **Before fixing lint failures by hand, run `make fix`** — it applies every auto-fix the linters can (gofmt, `golangci-lint --fix`, `eslint --fix`, `stylelint --fix`) using the same configs and globs as `make lint`, then tells you to re-lint. It never fixes type errors (lint-types), dead code (lint-deadcode), or missing imports in the docs' JavaScript examples (lint-docs) — those still need a human. `make fix` and `make fix-files` are the only sanctioned ways to auto-fix; don't run `gofmt -w`, `eslint --fix`, or `stylelint --fix` directly (same drift reason as lint). Per-file: ```bash make fix-files FILES="cmd/juggler/worker/foo.go web/css/bar.css" ``` ## Tests - `make test` runs the whole suite (Go unit + integration + browser) without `-v`, so its output already is the summary: one `ok <pkg> <time>` line per passing package, and on failure only the failing tests' own output. Each layer announces itself, the first failing layer stops the run — so a failure is the last thing on screen — and a `✗` line under it names the layer. The same text is teed to `bin/test*.log` purely for afterwards; the log and the terminal hold the same thing, so there is nothing to tail or grep. - **To run one specific test, pass `RUN='<regex>'`** — a `go test -run` pattern matched against test-function names. It also turns on `-v` so you see that test's own output, and silences the packages that hold no matching test (which under `-v` would otherwise announce themselves and bury the one you asked for). This is the sanctioned way to iterate on a single test; **don't run `node`, the browser harness, or `go test` by hand** — the target builds the right binary, sets the flags CI uses, and tees the log for you. ```bash make test RUN='TestDiffView' # one test, whichever layer it's in make test RUN='TestDiffView/collapsed' # one subtest make test-go RUN='TestWorker' # restrict to the fast unit layer ``` - Browser tests launch `bin/juggler-testsrv --assets-from-disk`, serving the local `web/` tree. That is the test-capable server `make test` builds beside the app (`make test-build` on its own), stamped `-test` so a server a suite spawned says so when it talks to the update endpoint; `bin/juggler` stays the app you launch. Once it exists, web-only edits don't need a rebuild — rerun `make test RUN='<name>'` (Go builds are incremental, so this is cheap). Rebuild only for Go / embedded-asset / build-file changes. - Browser-test lanes share one offscreen pool window. They do not reliably paint, so a test must not await `requestAnimationFrame` or a post-layout `ResizeObserver` delivery; exercise a synchronous seam instead. Lane viewport width also varies by platform and may cross the 36rem phone breakpoint, so geometry that depends on a breakpoint belongs in an explicitly sized iframe. - rAF delivery in a lane is platform-split: frames never arrive on macOS or Linux (WebKitGTK), but Windows (WebView2) delivers them — so product code deferred through `requestAnimationFrame` is exercised only on Windows CI. Test such behaviour by calling the deferred function directly. - The pool is `JUGGLER_TEST_WINDOWS` subprocesses x `JUGGLER_TEST_IFRAMES` lanes, and the lanes inside one subprocess share a single content process — one JS heap, one main thread. Raising iframes while dropping windows to 1 serialises the suite onto that thread and produces cascades of arbitrary timeouts. - **A lane is an iframe, and the lanes in one window share a single session history.** A `pushState` or `back()` in any lane traverses that joint history and delivers the `popstate` to whichever lane's entry it popped — so one lane closing a menu could dismiss the overlay another lane had just opened. Nothing in a lane may touch `window.history` casually: the overlay Back-button sentinel (`popup-manager.js`) stands down unless the app owns the history (`window.top === window`), and the two suites that test it switch it on for their own duration via `__setBackIntegrationForTests` while stubbing the History API. **A test must never traverse the real one**, however carefully it balances its own entries: a sibling lane loading its next test page puts an entry on top of the shared stack, so the `back()` lands on the sibling — which is sent back a document — and this lane is delivered no `popstate` at all. A stub answering with a `popstate` of its own, in a later task, reproduces everything a real traversal was there to show. - **Model limits go stale silently. `TestCatalogDrift` is how you find out.** Providers publish new models and retire old ones constantly, and a wrong context window has no symptom — the model works and merely compacts far sooner than it needed to. The audit compares what each provider serves right now against what the built-in catalogs say, using whatever keys you have configured, and names the providers it had to skip: ```bash JUGGLER_MODELS_AUDIT=1 make test-go RUN='TestCatalogDrift' ``` It is opt-in (one network call per provider) and skipped in `make test`. Run it after any vendor announcement, and before a release. The no-network half, `TestCatalogInvariants`, runs every time and checks every catalogued model for limits that cannot be right. - Suite timings are load-sensitive. A browser test that fails in a full run and passes alone is not a regression in the code it asserts on — re-run the exact subtest in isolation before investigating it. It is not automatically "just load" either: that shape has twice turned out to be a real harness fault that only a busy machine reaches. - **Every wait in a test rides the per-test deadline** (`budgetFor` / `deadlineFor` in `web/js-tests/utilities/test-deadline.js`), never a bare nominal timeout of its own. A number chosen when a lane had the pool to itself measures the pool rather than the code once nine lanes share a machine. `unit:test-budget` asserts this contract; add a case to it when you add a wait. - A wait whose expiry does not itself fail the test — one that answers a dialog or a prompt something else is blocked on — must record why it gave up. Silence there turns a missed deadline into a hang that gets reported much later, against whatever was in flight at the time. ## Git commits - Commit messages: **one line, minimal, past tense** (e.g. `Fixed cross-conversation cancel leak`). ## Changelog - Add entries under `[Unreleased]` in `CHANGELOG.md` as you make user-facing changes; release tooling rolls that section into a dated version section when a release is cut. - **Each release is a single flat list of changes** — no `Added`/`Changed`/ `Fixed` subsection headers. - **Entries are terse one-liners**: ~12 words, the user-visible headline only. Match the length of the existing entries. ## Conventions
Signals
- Stars
- 804
- Forks
- 55
- Open issues
- 12
- Last commit (this folder)
- Oct 19, 2026 (9 days ago)
- Last release
- Oct 23, 2026 (5 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- AGPL-3.0
- Repository
- github.com/juggler-ai/juggler
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from juggler-ai
Cite this page
AGENTS.md · juggler-ai/juggler. Agent Mart. https://agentmart.dev/templates/juggler-ai-juggler-agents-md (last updated 2026-10-24)