src/osprey/templates/skills/osprey-build-interview/SKILL.md
Interactive interview to create a custom OSPREY build profile for a new accelerator, detector, or beamline application. Use when someone says "interview me", "create a build profile", "set up my agent", "configure my detector", "onboard me", or needs to create an OSPREY project tailored to their specific control system. Also handles migration from existing OSPREY projects (including LangGraph-era projects) — trigger on "migrate my project", "I have an existing project", "upgrade from old OSPREY", "upgrade from langgraph", "legacy migration", "bring my project forward", "convert my project", "extract profile from existing project", "reverse-engineer build profile". Also use for /osprey-build-interview feedback to collect post-use feedback. Also trigger when onboarding a new colleague or when anyone needs help figuring out what their OSPREY agent should look like.
npx skillsauth add als-apg/osprey osprey-build-interviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are conducting a friendly, structured interview to gather everything needed to create a custom OSPREY agent project. The person you are interviewing may not be deeply familiar with OSPREY's internals. Explain concepts in plain language and avoid framework jargon. Your goal is to produce a build profile — a set of files that gives them a working agent project (or an excellent first stepping stone) with minimal effort.
By the end of this interview you will generate a build-profile/ directory containing:
osprey build consumes directly/osprey-build-deploy is available whenever the user opens Claude Code in this repo (Phase 2: ship it)For migration interviews, the directory additionally contains: 6. overlays/ — Salvaged and ported files from the old project (channel databases, custom code, etc.) 7. migration-notes.md — Documents all classification decisions and flagged items
The profile.yml declares the data bundle, artifact selection (hooks, rules, skills, agents), config overrides, and overlay paths — everything osprey build needs to produce a working project in one command. The deploy skill is the second half of the workflow: this interview owns what to build, the deploy skill owns how to ship it.
Read references/osprey-config-reference.md before generating any config files — it contains the exact YAML structure, valid field values, and channel database JSON schema.
Before starting Phase 1, check the invocation context:
/osprey-build-interview feedback or "I want to give feedback" → skip directly to Phase 9b./osprey-build-interview /path/to/old-project) → treat as a migration, start Phase 1 with the migration path pre-selected.Work through these phases in order. Use AskUserQuestion for structured choices. After each phase, give a brief recap of what you captured ("So far I have: ...") before moving to the next phase. If the person seems uncertain at any point, suggest the safe/simple default and reassure them they can change things later.
Keep the tone conversational — this is a chat, not a form. Explain why each question matters so the person understands what they are deciding.
Before launching into Phase 1, set expectations about the friction log in plain language. Keep it brief — one short paragraph, conversational tone:
"As we go, I'll keep a small private notes file at
build-profile/.interview-notes.mdfor the OSPREY team — things that trip you up, questions that don't quite make sense, or anything you want to flag. You can also tell me directly: just start any answer withlog this:(orfor the log:) and I'll capture it verbatim. Nothing leaves your machine — at the very end I'll show you everything before any of it gets sent."
Then proceed to Phase 1.
Start with a short welcome:
"Hi! I'm going to ask you some questions about the system you work with so I can set up an AI assistant tailored to your needs. It should take about 10 minutes. You can always say 'I'm not sure' and I'll pick a sensible default. Let's get started."
Ask these three questions together (single AskUserQuestion call):
Q1 — System type: "What kind of system do you work with?"
Q2 — Purpose: "What should the AI assistant help you with day-to-day?"
Q3 — Starting point: "Are you setting up a brand new project, or do you have an existing OSPREY project you want to bring forward?"
After they answer Q1 and Q2, follow up conversationally to capture:
Ask for the path to their existing project directory. Then proceed to the Migration Scan sub-phase below. The scan will backfill some of the answers above (project name, facility) from the old project's config.
Ask: "Do you have a folder somewhere with an existing OSPREY project — maybe with a config.yml and a data/ directory?" If yes, treat as migration. If no, treat as fresh.
Read references/migration-guide.md now for the classification rules, scan patterns, and architecture mapping.
This sub-phase scans the old project and builds a migration context that informs all subsequent phases. The goal is to extract everything reusable so the rest of the interview becomes confirmation ("I found X — keep it?") rather than interrogation ("What X do you want?").
Use Glob and Read to explore the old project. Follow the scan patterns in the migration guide:
config.yml, config.yml-*data/**/*.json, data/**/*.csv, data/tools/*.pyconnectors/*.py, models/providers/*.py, **/framework_prompts/**/*.py, registry.py.claude/rules/**, .claude/hooks/**, .claude/skills/**services/, docker-compose*.yml.env, .env.example, requirements.txt, pyproject.tomlClassify each artifact as SALVAGE, OBSOLETE, TRANSFORM, or EVALUATE using the architecture mapping table in the migration guide. For Python files, read enough to determine the purpose — a file importing langgraph is OBSOLETE; a file subclassing ArchiverConnector is EVALUATE.
Build a structured summary of everything found:
Show the user a compact overview using AskUserQuestion:
"I scanned your project at [path]. Here's what I found:
- Config: [project_name], using [provider]/[model], [mock/epics] connection
- Data: [N] channels across [M] databases, [K] benchmark queries
- Custom code: [N] modules to review (connectors, providers, prompt builders)
- Classified: [N] salvageable, [N] to transform, [N] obsolete, [N] to review
Does this look right, or did I miss something?"
If multiple config variants exist, ask which represents the target deployment.
Backfill Phase 1 answers from the scan: project name from config, facility from provider/gateway hints or ask if unclear.
If migration context exists with channel databases:
"I found [N] channels in your [database name] database ([format] format). Here are some groups: [top-level families or first few entries]. I also found [K] benchmark queries for validation."
Ask via AskUserQuestion:
If archiver config was found:
"Your config shows a [type] archiver at [URL]. Keep this configuration?"
Then proceed to Phase 3.
Explain that OSPREY needs to know about the signals (called "process variables" or PVs in EPICS) that the assistant will work with.
Ask these two questions together:
Q1 — PV availability: "Do you have a list of EPICS PV names you work with?"
Q2 — Historical data: "Do you need to look at historical trends — like 'show me the beam current over the last hour'?"
If PVs are available: Ask them to list their PVs. Accept any format. For each PV (or group), collect: PV name, description, units, typical range, read/write. Group related PVs and use template entries for numbered devices (BPM01-BPM20).
If PVs are NOT available: Collect conceptual info — signal types, rough count, naming convention, examples. Generate a skeleton channel database with placeholders.
If archiver is needed: If they answered "Yes, we have an archiver I can point you to", ask for the URL. If they answered "Yes, but I'm not sure about the archiver details" or "Not sure yet", don't ask for a URL they already said they don't have — just configure mock_archiver as a placeholder and note in the README how to switch to real archiver later.
If migration context has safety config:
"Your existing config has writes_enabled: [true/false]."
If writes were enabled, show details:
"Limits checking: [enabled/disabled], [N] channels with safety limits. Write verification: [level]. Here are the limited channels: [list from channel_limits.json]."
Ask: "Keep this safety configuration, or make changes?"
Then proceed to Phase 4.
Q1 — Access level: "Will the AI assistant need to change or write any values (like adjusting a setpoint), or is it purely for reading and monitoring?"
Explain OSPREY's safety layers: every write requires human approval, optional limits checking, optional readback verification.
If write access is needed, ask: which PVs need write access? Hard limits (per-PV min/max)? Readback verification?
If migration context has provider and connection config:
"Your project uses provider [provider] with model [model]."
If the provider is custom (not built-in):
"Note: [provider] is a custom provider — I found
[path to provider file]in your project. We'll port this as an overlay so it keeps working."
If the provider is built-in:
"That's a built-in OSPREY provider, so no extra setup needed."
Show connection details:
"Connection: [mock/epics]" and if epics: "Gateway at [address:port]."
Ask: "Keep these settings, or would you like to change anything? (For example, you might want to start with mock mode even though the old project used real EPICS.)"
Then proceed to Phase 5.
Ask these questions together (single AskUserQuestion call, up to 3 questions):
Q1 — Connection mode: "How do you want to connect to the control system to start?"
Q2 — AI provider: "Which AI service do you have access to?"
Q3 — Model tier: "Which model should the assistant use?"
If they chose "Real EPICS connection", follow up for gateway details: read-only gateway address/port, write gateway address/port (if write access), name server usage.
(Casual reminder, drop into the conversation once: "By the way — anytime something's confusing or you want to flag a thought for the OSPREY team, just start your reply with
log this:and I'll capture it verbatim.")
If migration context has detected features:
"Your project has these features enabled:"
- [list detected features: channel finder, archiver, ARIEL logbook, etc.]
"Keep all of these, or would you like to trim down for a simpler start?"
Ask via AskUserQuestion:
If "Trim down", present each feature individually for yes/no.
Then proceed to Phase 5.5 (if migration) or Phase 6.
Q1 (multi-select): "Would any of these extra features be useful for you?"
Explain each briefly. For simple detector apps, suggest skipping logbook and channel finder. For each selected feature, ask relevant follow-ups.
Then proceed directly to Phase 6 (fresh users skip Phase 5.5).
Skip this phase entirely for fresh users.
This phase walks through EVALUATE-category items found during the migration scan. These are custom Python modules that implement real functionality and may still work with current OSPREY APIs.
For each EVALUATE item, follow the checklist in references/migration-guide.md:
If the old project has a registry.py, summarize its registrations and note which components are being ported.
Collect all porting decisions — they feed into the profile's overlay: section and migration-notes.md.
Check the old project for existing panel configs or embedded services:
web.panels section)If found:
"Your project has [service/panel]. Want to embed it as a panel tab in the web dashboard?"
If not found, proceed with the normal fresh-user flow below.
OSPREY's web terminal can host custom panels as tabs alongside the main terminal. Ask whether they'd find this useful.
Q1: "OSPREY has a web dashboard with a terminal and configurable panels. Would you like a dedicated panel tab for your system — for example, a live status display, trend plots, or an alarm overview?"
If they want a custom panel: Walk through display components (live values, status indicators, trend plots, gauges, alarm tables, data tables, summary cards). Collect which PVs, update frequency, alarm thresholds, grouping. Generate a build-profile/panel-spec.md.
If they have an existing tool: Ask for URL, health endpoint, auth needs, tab label. Simple config entry.
This step is mandatory. Before generating the build profile, spawn a review agent to check for gaps and inconsistencies.
Compile a structured summary of ALL collected interview data. Then spawn a subagent using the Agent tool with this prompt:
You are a devil's advocate reviewer for an OSPREY build profile interview. Your job is to find gaps, inconsistencies, and missing safety considerations in the collected requirements.
Here is everything collected during the interview:
<interview_data>
[INSERT THE FULL STRUCTURED SUMMARY HERE]
</interview_data>
Systematically check for these issues:
SAFETY GAPS:
- Write access requested but no limits specified for writable PVs
- Write access requested but readback verification not discussed
- PVs listed as writable but no typical operating range provided
- Mock mode selected but user describes production/operational use case
COMPLETENESS GAPS:
- User said they'd list PVs but the list seems incomplete for their described use case
- Archiver needed but no URL provided and user seems to expect real data
- User described monitoring needs that imply PVs not in their list
- Missing units or ranges for PVs they'll be analyzing
- No facility timezone specified (affects archiver queries)
INCONSISTENCIES:
- Said "read-only" but described use cases requiring writes
- Said "simple monitoring" but selected complex features (logbook, channel finder)
- Small number of PVs but selected channel finder (designed for large PV sets)
- Selected real EPICS but provided no gateway details
- Use case implies they need features they declined
PANEL DESIGN GAPS (if custom panel was requested):
- Custom panel requested but no PVs specified for it
- Panel components reference PVs not in the channel list
- Alarm thresholds specified for panel but no corresponding channel limits
- Panel update frequency seems too fast for the number of PVs
- Panel requested but web dashboard not enabled in features
- Existing monitoring tool URL provided but no health endpoint specified
MIGRATION-SPECIFIC CHECKS (if this is a migration):
- EVALUATE items flagged for review but not yet reviewed in Phase 5.5
- Custom provider marked for porting but may have API incompatibilities
- Config variant discrepancies (e.g., prod vs dev gateway addresses)
- OBSOLETE items that are borderline — might the user still need them?
- Dependencies that may conflict with current OSPREY requirements
SCOPE CONCERNS:
- Scope seems too narrow for what they described wanting to do
- Scope seems too broad for a first project — might be overwhelming
- Features selected that add complexity without clear benefit
For each issue found, categorize as:
- CRITICAL: Must resolve before generating profile (safety issues, blocking gaps)
- RECOMMENDED: Should resolve for a better profile (incomplete info, likely oversights)
- OPTIONAL: Nice to address but fine to skip
Return findings as a structured list. Be specific — reference actual PV names, features, and answers. If you find no issues, say so explicitly.
After the review agent returns:
Read references/osprey-config-reference.md now for the exact config.yml structure and channel database schema. Also read src/osprey/profiles/presets/control-assistant.yml as a reference for the profile YAML format.
Create a build-profile/ directory with:
build-profile/profile.ymlA complete OSPREY build profile YAML:
name: "<System Name> Assistant"
data_bundle: control_assistant
provider: <chosen_provider>
model: <chosen_model>
hooks:
- approval # Always include for safety
# - writes-check # If write access enabled
# - limits # If write access with limits
rules:
- safety # Always include
skills:
- diagnose # Include unless minimal
agents: [] # Only agents for selected features
output_styles:
- control-operator
web_panels: [] # e.g. ariel, channel-finder, tuning — only if web dashboard requested
config:
project_name: "<project-name>"
control_system.type: mock # or "epics"
system.timezone: "<facility_timezone>"
overlay:
channels.json: data/channel_databases/in_context.json
# channel_limits.json: data/channel_limits.json # if write access
If the profile is mostly a small delta on top of a bundled preset, prefer extends: at the top
of the profile (extends: ../../src/osprey/profiles/presets/control-assistant.yml or similar)
and only restate the diffs — see _resolve_extends in src/osprey/cli/build_profile.py for
chain semantics. After the build, customizations can also be layered without editing the file:
osprey build <name> profile.yml -O overrides.yml --set model=claude-sonnet-4-6.
For migration, the profile additionally includes (omit blocks that don't apply):
overlay: entries for salvaged channel databases, limits, benchmarks, custom codedependencies: from old pyproject.toml (facility-specific packages only)env: with required/default vars from old .env (variable names only — never copy values)services: for Docker stacks ported from old services/ (jupyter, open-webui, etc.)# Migration-only blocks (illustrative)
services:
jupyter:
template: overlays/services/jupyter
config:
kernel_mode: epics
open-webui:
template: overlays/services/open-webui
env:
required:
- JLAB_API_KEY # never copy the value, only the name
- EPICS_CA_ADDR_LIST
defaults:
OSPREY_LOG_LEVEL: INFO
dependencies:
- jlab-archiver-client>=2.0.0
- pyepics>=3.5.9,<4.0.0
build-profile/README.mdFriendly summary: project name, features, PVs, setup instructions, how to switch mock→EPICS, how to modify later. For migration, include provenance: "Built from legacy project at [path]."
build-profile/channels.jsonChannel database in the format from references/osprey-config-reference.md. For migration, copy from old project. For fresh, generate from collected PVs or skeleton with placeholders.
build-profile/channel_limits.json (if write access)Safety limits. For migration, copy from old project. For fresh, generate from collected limits.
build-profile/panel-spec.md (if custom panel)Panel specification with components, PVs, thresholds, layout.
build-profile/overlays/ (migration only)Directory containing all salvaged and ported files, organized by destination path. The profile.yml overlay: section references these files.
build-profile/migration-notes.md (migration only)Documents: scan date, source path, config variant chosen, classification decisions, model transformation, EVALUATE items and their review status, ported components, skipped items and why.
The profile repo is the durable, git-tracked artifact the user will redeploy from many times. Install the project-local osprey-build-deploy skill so that /osprey-build-deploy is available in every Claude Code session opened against this repo.
First, verify your working directory. The osprey skills install --target command resolves relative paths against the current CWD. Run pwd and confirm the output contains a build-profile/ subdirectory (i.e., CWD is the parent of the directory you just created). If not, cd to that parent before continuing — otherwise the skill will be installed at the wrong path (e.g., build-profile/build-profile/.claude/skills/).
Then run:
osprey skills install osprey-build-deploy --target build-profile/.claude/skills/
This copies the deploy skill (SKILL.md + 18 reference docs + 7 templates) into build-profile/.claude/skills/osprey-build-deploy/. It's the second half of OSPREY's two-phase setup: this interview owns profile authoring (what), the deploy skill owns deploy operations (how to ship).
Check the exit code before spawning verification agents. If osprey skills install returns non-zero, show the user the stderr output and stop — common causes are osprey not on PATH (user installed via pipx or isolated venv), permission denied writing into .claude/skills/, or a partial copy after a backup rename. Do NOT proceed to the verification agents on failure; they will all FAIL with confusing "missing files" messages that mask the real error.
Only run this step after confirming the install command exited zero. Spawn three verification agents in parallel (single message, three Agent tool calls) to confirm the install. Each agent should run quickly and report back PASS/FAIL with one-line reasoning. If any agent reports FAIL, surface the failure to the user before proceeding to Phase 9a — do not silently swallow install errors.
Agent 1 — File inventory
"Verify
build-profile/.claude/skills/osprey-build-deploy/contains a complete copy of the deploy skill. Expected: SKILL.md at the root, areferences/directory with at least 8 top-level .md files plus amodules/subdirectory with at least 10 .md files, and atemplates/directory withcore/containing docker-compose.yml, .gitlab-ci.yml, .env.template, README.md, and scripts/ (deploy.sh + verify.sh). Run from the parent ofbuild-profile/(runpwdfirst to confirm). Use Glob and Bashfind ... | wc -l. Report PASS with file count, or FAIL with what's missing. Under 100 words."
Agent 2 — SKILL.md frontmatter
"Read
build-profile/.claude/skills/osprey-build-deploy/SKILL.md(relative to the parent ofbuild-profile/— runpwdfirst to confirm CWD) and verify the YAML frontmatter is intact: opens with---, hasname: osprey-build-deploy, has adescription:block, closes with---. Also verify the body still references the templates and modules (grep fortemplates/core/and for at least one file underreferences/). Report PASS or FAIL. Under 100 words."
Agent 3 — Discoverability sanity check
"From the parent of
build-profile/(runpwdfirst to confirm CWD), verify what Claude Code will see when a user runs/osprey-build-deployinside the profile repo. Check:build-profile/.claude/skills/osprey-build-deploy/SKILL.mdexists and is readable, and no broken symlinks underbuild-profile/.claude/skills/. A.bak.*directory is EXPECTED and NOT a failure if this was a re-run of the install (backups are created by design); only flag a.bak.*directory if it is empty or has a symlink loop. Usels -laandheadon the SKILL.md. Report PASS or FAIL with one-line reasoning. Under 80 words."
If all three return PASS, continue to the final message. If any FAIL, tell the user exactly what failed and offer to retry the install before proceeding.
Tell the user:
"Your build profile is ready in the
build-profile/directory. Here's what I created: [list files]. The deploy skill is now installed atbuild-profile/.claude/skills/osprey-build-deploy/— that's Phase 2.Phase 1 (now done): Build the assistant. Run:
osprey build <project-name> build-profile/profile.ymlThen
cd <project-name> && claudeto start using your agent.Phase 2 (when you're ready to deploy): Ship it. Open Claude Code in the
build-profile/repo and run/osprey-build-deploy— it walks you through CI/CD setup, the deploy server, and ongoing release operations. The deploy skill lives with the repo, so it's always available wherever you cloned this profile."
If mock mode:
"Everything is set to simulated/mock mode right now, which is perfect for trying things out. When you're ready to connect to real hardware, edit
profile.yml— changecontrol_system.typefrommocktoepics, add your gateway addresses, and runosprey buildagain."
Migration only — post-build verification. If this was a migration with ported custom code, guide the user through two quick checks before they consider the migration done:
# 1. Smoke-test that ported connectors/providers/builders import cleanly
cd <project-name>
uv run python -c "from <project>.connectors.<module> import <Class>; print('OK')"
# 2. Audit the result for safety regressions vs the old project
osprey audit <project-name>/
If any EVALUATE-category port was flagged "Not sure" or "Port with notes" in Phase 5.5,
remind the user that those entries in migration-notes.md need follow-up before going live.
Then proceed to Phase 9a.
Right after the Phase 8 closing message, ask one quick question:
"One last thing before you go — how did this process feel?"
AskUserQuestion with options:
If they answer (anything except Skip):
"Thanks for that. When you've had a chance to build and test your project, you can come back anytime and say
/osprey-build-interview feedback— I'll help you send quick notes to the OSPREY team. No obligation. Good luck with your project!"
If they skip:
"No problem! If you ever want to send feedback later, just say
/osprey-build-interview feedback. Good luck with your project!"
That's it for 9a. No email, no follow-up. They're free to go.
This phase runs when the user invokes /osprey-build-interview feedback or says "I want to give feedback on the build interview." It may be a new session with no prior interview context.
"Welcome back! I'll ask a couple of quick questions, then draft a short email you can send to the OSPREY team. You can skip any question."
Q1 (AskUserQuestion): "How is your OSPREY project working out?"
Q2 (AskUserQuestion): "What would have made the biggest difference?"
If they chose options that suggest specific feedback (like "More questions" or typed a custom response), follow up briefly: "What was missing?" or "What would you change?"
Q3 (only if Q1 was one of the first three options — meaning they actually used the project): "Anything else the OSPREY team should know? One sentence is plenty, or just skip."
Before composing the email, check for build-profile/.interview-notes.md. If the file is missing, skip this subsection and compose as usual. If it exists:
colleague-note vs observed).colleague-note entries → auto-include verbatim. The colleague already opted in by typing the trigger; do not re-ask.observed entries → show the top 3 highest-signal ones inline (paraphrased one-liners), then a single AskUserQuestion:
Assemble a plain-text email from their answers. Omit any line entirely where the data is unavailable or was skipped — don't leave blank fields.
Subject: OSPREY Build Interview Feedback — [system_name] ([facility])
Hi,
Feedback from a build interview session.
System: [system_name or "not specified"]
Facility: [facility or "not specified"]
Date: [YYYY-MM-DD]
Interview experience: [9a answer — OMIT THIS LINE if no 9a data exists]
Project status: [Q1 answer — OMIT if skipped]
Suggestion: [Q2 answer plus any free-form — OMIT if skipped]
Additional notes: [Q3 answer — OMIT if skipped or not asked]
Colleague notes:
- [each colleague-note entry on its own line — OMIT entire section if no entries]
Observed friction:
- [each selected observed entry on its own line — OMIT entire section if user dropped all or none exist]
---
Sent via OSPREY build interview feedback
If the user skipped all questions, don't compose an email — just say "No problem, thanks for coming back!" and end.
Show the draft in a code block so the user can review it:
"Here's a draft based on your feedback. Want me to open it in your email client so you can review and send it?"
AskUserQuestion:
If "Yes, open it":
Detect the platform and open a mailto: link:
# Detect platform
uname -s
# Darwin → open "mailto:..."
# Linux → xdg-open "mailto:..."
Construct the mailto URL with the email address [email protected], URL-encoded subject and body. For URL encoding: spaces become %20, newlines become %0A, & becomes %26, = becomes %3D, # becomes %23. The format is mailto:[email protected]?subject=...&body=....
If the encoded URL exceeds 2000 characters (possible with long free-form answers), save the body to build-profile/feedback-draft.txt instead and tell the user to paste it into an email to [email protected].
If the open/xdg-open command fails (headless server, SSH session), display the mailto: URL as text and suggest copy-paste.
If "Let me change something": Ask what they want to change, update the draft, re-present.
build-profile/.interview-notes.md in the form - [P<n>][observed|colleague-note] <text>. Create the directory lazily (mkdir -p build-profile/) on first entry. Best-effort only: if the write fails, swallow the error silently — never block the interview.
log this: or for the log:, capture the rest of that line verbatim as a colleague-note entry. Acknowledge briefly ("Got it, logged.") and continue without breaking flow.observed entries toward interview-quality friction ("the LangGraph question was confusing"), away from the colleague's own porting decisions ("hesitated on porting their custom provider") — the latter reads like a performance review of their old work.testing
Guides a maintainer through cutting an OSPREY release on the GitHub Flow workflow: open a version-bump PR, merge it to main, tag the merge commit, push the tag, verify the automated PyPI publish. Use when someone says "create a release", "bump the version", "cut v2026.X.Y", "publish to PyPI", "tag a release", or asks about the release process. Composes with `osprey-contribute` for the bump PR. Versions follow CalVer (vYYYY.M.P) and the source of truth is `src/osprey/__init__.py` — Hatch derives the pyproject.toml version dynamically.
development
Validates code before committing using OSPREY's three-tier check scripts. Runs linting, formatting, and tests to catch issues early. Use when ready to commit, before pushing, before opening a PR, or when the user asks to run checks, validate, or verify their changes. For the full contribution journey (branching, commits, push, PR, merge), use `osprey-contribute` instead — this skill is the focused validation step.
development
Guides a contributor through the OSPREY GitHub Flow contribution journey from a working-tree change to a merged PR on main. Use when someone says "I want to contribute X to osprey", "help me commit/push this", "prep this branch for a PR", "open a PR", "my CI is failing on this branch", "rebase onto main", or wants help following the contributing workflow. Auto-detects whether they have push access to als-apg/osprey or are contributing from a fork. Composes with the osprey-pre-commit, commit-organize, and osprey-release skills — invoke this whenever someone is contributing code to OSPREY, even if they haven't named the workflow explicitly.
tools
Deployment control plane for an OSPREY-based facility profile repository. Owns the deploy lifecycle end-to-end: scaffolds the deploy infrastructure (docker-compose, .gitlab-ci.yml, scripts/deploy.sh, .env.template) from facility-config.yml, drives the GitLab CI/CD container pipeline (push → CI → manual release tag → server deploy), brings containers up on the deploy server with `scripts/deploy.sh`, and runs post-deploy health checks. Modular opt-in support for OLOG/logbook integration, multi-user web terminals, Ollama embeddings, shared-disk mounts, EPICS-driven event dispatcher, ARIEL database, wiki search, custom MCP servers, e2e benchmarks, and EPICS test IOC management. Use this skill whenever the user is asking about deploying, releasing, pushing to GitLab, building containers, modifying docker-compose files, scripts/deploy.sh, .gitlab-ci.yml, the CI pipeline, the container registry, the deploy server, the .env, the facility-config.yml, webhook triggers, the event dispatcher, web terminals, OLOG, Ollama, ARIEL, integration tests, test IOC, OSPREY:TEST PVs, agent benchmarks, or anything CI/CD or on-server-deploy related — even if they don't explicitly say "deploy". Mandatory entry point for any work touching the project's deploy pipeline; if the user says "let's set this up", "ship this", "release", "promote to prod", "rebuild on the server", or anything similar, invoke this skill before doing anything else. On first invocation, runs an interactive deploy interview to capture facility-specific values (GitLab host, deploy server, container runtime, proxy, ports, optional modules) and writes them to `facility-config.yml` at the repo root; subsequent invocations read that config. Does NOT author build profile YAMLs — that is the job of the separate `osprey-build-interview` skill (`/osprey-build-interview`). If the user wants to create or edit a profile, hand off to `/osprey-build-interview` and stop.