diff --git a/.agents/skills/pr-description/SKILL.md b/.agents/skills/pr-description/SKILL.md
new file mode 100644
index 0000000000..1b4ba4acf8
--- /dev/null
+++ b/.agents/skills/pr-description/SKILL.md
@@ -0,0 +1,35 @@
+---
+name: pr-description
+description: Write a PR description for the current Firefly feature branch and copy it to the clipboard — Jira ticket link, a what/why summary sized to the change, and a Testing section with the branch's dev build URL. Use when the user asks to write, draft, or generate a PR/pull-request description, or invokes /pr-description.
+---
+
+Write a PR description for the current feature branch and copy it to the clipboard.
+
+## Steps
+
+1. **Find the base branch.** Firefly PRs target `dev`, or an `rc-*` branch for release fixes. Run `git fetch origin` and pick whichever of `origin/dev` and the `origin/rc-*` branches has the fewest commits in `git rev-list --count ..HEAD`. Use it as `` below.
+
+2. **Understand the changes.** Run these in parallel:
+ - `git log ..HEAD --oneline`
+ - `git diff ...HEAD --stat`
+
+ Then read the key changed files to understand what the code actually does — not just the commit messages.
+
+3. **Get the ticket** from the branch name (`FIREFLY-1234-short-desc` → `FIREFLY-1234`; also `IRSA-…`). Link it as `https://jira.ipac.caltech.edu/browse/`.
+
+4. **Learn the author's style** from their recent PRs:
+ - `gh pr list --repo Caltech-IPAC/firefly --author @me --state merged --limit 5 --json number,title,body`
+ - Note the tone, tense, header levels, and bullets vs prose — and match them.
+ - If the author has no past PRs, use the structure in step 5 as is.
+ - Saved preferences from the author (memory, CLAUDE.md) take precedence over anything inferred here.
+
+5. **Draft the description in markdown:**
+ - **Ticket line** at the top, linking the Jira ticket (e.g. `Fixes [FIREFLY-1234](https://jira.ipac.caltech.edu/browse/FIREFLY-1234)`).
+ - **What and why**, sized to the change. For a small fix: one tight paragraph covering the problem, the cause, and the fix. For a larger change: add bullets or a short section for non-obvious design decisions and their trade-offs. Skip obvious choices.
+ - Briefly define library-specific terms in plain words.
+ - If the change has a counterpart PR in another repo (e.g. an IFE PR), link it.
+ - **`## Testing`** — first the dev build URL: `https://.irsakubedev.ipac.caltech.edu/firefly/` (append the app path if the change is in a specific app). Then concrete steps a reviewer can follow: what to load, what to click, what they should see. Put caveats and known issues to verify here too.
+
+6. **Show the draft** to the user and iterate until they approve. Remind them that the dev build URL only works once the branch's test build has been run.
+
+7. **Copy the final version to the clipboard** with `pbcopy` on macOS (`xclip -selection clipboard` or `wl-copy` on Linux). If none of these is available, print it for the user to copy.
diff --git a/.claude/skills b/.claude/skills
new file mode 120000
index 0000000000..2b7a412b8f
--- /dev/null
+++ b/.claude/skills
@@ -0,0 +1 @@
+../.agents/skills
\ No newline at end of file
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000000..1c4c130944
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,61 @@
+# AGENTS.md
+
+Guidance for AI coding agents working in the Firefly repo. Human-facing docs live in `README.md`, `CONTRIBUTING.md` and `docs/`.
+
+## Project overview
+
+Firefly is IPAC's astronomy data visualization and archive UI toolkit: a React/Redux client (images, tables, charts) backed by a Java server (Tomcat webapp). It's a large, mature codebase that has been through several generations of code patterns.
+
+## Repo map
+
+- `src/firefly/js/` — client code
+ - `visualize/` images, HiPS and coordinates; `tables/` table model and UI; `charts/` Plotly-based charts
+ - `ui/` components, dialogs and search panels; `core/` Redux store, reducers and sagas; `api/` public JS API; `util/` helpers
+ - `*Cntlr.js` files (e.g. `charts/ChartsCntlr.js`) define a state slice's action types, `dispatch*` functions and reducer
+ - tests live next to the code in `__tests__/` folders, named `-test.js`
+- `src/firefly/java/edu/caltech/ipac/` — server code (`firefly/`, `table/`, `visualize/`, `util/`, `astro/`)
+- `src/firefly/test/` — Java tests, mirroring the `java/` package layout
+- `buildScript/` — Gradle build logic (`tasks.gincl` defines the tasks below)
+- `docs/` — developer docs, e.g. `development-process.md`, `jstest-notes.md`
+
+## Build, test, lint
+
+```shell
+gradle :firefly:buildAndDeploy # build the war and deploy to local Tomcat — needed first, and after server (Java) changes
+gradle :firefly:devMode # watch JS and rebuild straight into the deployed webapp — the usual client dev loop
+```
+
+While iterating, check only what you touched:
+
+```shell
+yarn test-unit js/charts/__tests__/ChartUtil-test.js # one Jest file, run from src/firefly/
+npx eslint src/firefly/js/charts/ChartUtil.js # lint changed files, run from repo root
+```
+
+Before calling a change done, run the full suites CI runs: `gradle :firefly:jsTest`, `gradle :firefly:jsLint`, and `gradle :firefly:test` if Java changed.
+
+## Code conventions
+
+- Match the surrounding code's style, reuse existing utilities, and follow established patterns rather than reinventing them. The exception is a pattern that's clearly legacy or bug-prone. Use the modern approach there, and say that you did.
+- Use descriptive names — no single-letter or cryptic abbreviations like `t`, `xs`, `ll`; the name should say what the value holds.
+- For debug output, use `Logger` from `util/Logger.js` rather than `console.log`. Turn it on in the browser console with `window.firefly.debug = 'debug'`; filter it with `window.firefly.debugTags = 'Table'`.
+- Add short comments where the reason isn't obvious (a temporary hardcode, a subtle check); don't narrate what the code does.
+- JSDoc: when a function also has rest params, document destructured props as `@param {object} props` / `@param props.field` to satisfy `jsdoc/check-param-names`.
+- Tests: one helper per function under test, named after that function. Avoid chained generic helpers and hidden defaults — each test should show its inputs.
+- Before upgrading a JS dependency, check `package-json-doc.md` for why some packages are held at older versions.
+
+## How to approach a change
+
+- **Find the nearest cousin first.** Read the full round trip of an existing analog — component *and* the reducer/controller/server handler under it — not just a similar-looking call site. It reveals the ordering, side effects and edge cases you'll need to handle.
+- **Weigh decisions by blast radius, not diff size.** Local, reversible edits: just make them. New data flows, persisted state, endpoints, or edits to shared reducers/utilities: propose a short plan and get confirmation before editing.
+- **Build and debug one layer at a time.** Prove an endpoint with a raw request before wiring UI; prove render before selection; selection before persistence.
+- **Suspect stale state.** Redux state, server caches and long sessions outlive the code that filled them. When a bug contradicts verified code, try a hard reload or cache reset before re-reading the code.
+- **Reactive flows need a live check.** For new subscription/effect chains across files, code review isn't enough — ask for the interaction to be exercised live, more than once.
+- **Set scope early and keep it.** Name what's deferred; raise tempting adjacent fixes instead of folding them in.
+- **Remove superseded code in the same edit** — old functions, unused imports, stale comments — once you've confirmed it's actually dead.
+
+## Git workflow
+
+- Branches: `FIREFLY--short-desc`, created from `dev` (or the current `rc-*` branch for release fixes). Commit messages start with the ticket, e.g. `FIREFLY-1234: ...`.
+- PRs target `dev` (or the `rc-*` branch) and are squashed before merge. Full process: `docs/development-process.md`.
+- Don't commit, push, or rebase unless asked.