* chore(agents): simplify contributor instructions and workflows Closes #3980 Signed-off-by: John Myers <johntmyers@users.noreply.github.com> * docs(contributing): scope verification to affected components Signed-off-by: John Myers <johntmyers@users.noreply.github.com> * docs(contributing): standardize issue branch naming Signed-off-by: John Myers <johntmyers@users.noreply.github.com> --------- Signed-off-by: John Myers <johntmyers@users.noreply.github.com> Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
25 KiB
Contributing to OpenShell
OpenShell is built agent-first. We use agents to design and implement systems, while humans manage product decisions and the project roadmap.
The Critical Rule
You must understand your code. Using AI agents to write code is not just acceptable, it's how this project works. But you must be able to explain what your changes do and how they interact with the rest of the system. If you can't, don't submit it.
Submitting agent-generated code without understanding it — regardless of how clean it looks — wastes maintainer time and will result in your PR being closed. Repeat offenders will be blocked from the project.
AI Usage
OpenShell is agent-first, not agent-only. The distinction matters:
- Do use agents to explore the codebase, run diagnostics, generate code, and iterate on implementations.
- Do use the skills in
.agents/skills/— they exist to make your agent effective. - Do interrogate your agent until you understand every edge case and interaction in your changes.
- Don't submit code you can't explain without your agent open.
- Don't use agents as a substitute for understanding the system. Read the RFCs, crate READMEs, and published docs.
First-Time Contributors
We use a vouch system. This exists because AI makes it trivial to generate plausible-looking but low-quality contributions, and we can no longer trust by default.
- Open a Vouch Request discussion.
- Describe what you want to change and why.
- Write in your own words. AI-generated vouch requests will be denied.
- A maintainer will comment
/vouchif approved, and the request discussion will close automatically. - Once vouched, you can submit pull requests.
If you are not vouched, any pull request you open will be automatically closed. Org members and collaborators with push access bypass this check.
Finding Work
Issues labeled good first issue are scoped, well-documented, and friendly to new contributors. Start there. If you need guidance, comment on the issue.
An open issue is not necessarily accepted or ready for implementation. Inspect the repository’s current state:* labels and ask a maintainer when its status is unclear. A direct user request authorizes an agent to perform the requested phase without changing the issue’s disposition.
Before You Open an Issue
Search open and closed issues for the same need. Bug reports and feature requests must include:
- User Story: attest that you personally use OpenShell and describe the specific use case and behavior you directly encountered or need. Agents must ask the human operator for this first-hand context before filing if it is missing.
- Problem Statement: a concise summary of what is broken or missing in the current behavior.
- Impact / Why This Matters: the consequences of the current behavior, the current workaround, and why that workaround is insufficient.
- Acceptance Criteria: specific, observable outcomes that define success.
Feature requests must also propose a user-facing workflow and describe alternatives considered, including relevant OpenShell extension points. When an existing middleware, interceptor, provider, or other extension can satisfy the use case, prefer that path. Running another service alone is not grounds to dismiss it. For changes to configuration, CLI, SDK, or other user experience, include notional examples for human review. Bug reports must include reproduction steps using only an OpenShell deployment, the OpenShell version and relevant environment, and a small, redacted log excerpt when it materially clarifies the behavior. Do not install third-party tools solely to demonstrate reproducibility. Frame every issue entirely in terms of OpenShell.
The project includes optional agent skills for using OpenShell and contributing to the repository. Use them when they help you, but summarize any useful result in your own words rather than pasting a diagnostic transcript.
When to Open an Issue
- A workflow behaves differently from what you need or reasonably expect.
- OpenShell does not support an outcome that matters to your workflow.
- The available documentation or configuration does not explain how to complete a supported workflow.
- Security vulnerabilities must follow SECURITY.md — not GitHub issues.
When NOT to Open an Issue
- General questions or open-ended discussion — use GitHub Discussions.
- Security vulnerabilities — follow SECURITY.md instead.
Before You Submit a Change
Do not start substantial issue-backed work until a maintainer has accepted the issue, unless a maintainer directly asks you to investigate or implement it. Once the work is authorized, use your agent to investigate the current code and behavior. If the issue contains earlier diagnostics, verify them rather than relying on them.
Use agents and the repository skills as needed to understand the affected code, evaluate tradeoffs, implement the smallest coherent change, and verify it. The pull request should explain what changed and how it was tested; it should not substitute an agent transcript for the contributor's understanding.
Agent Skills
OpenShell keeps skills for using the product separate from skills for developing the repository.
Skills for Using OpenShell
Public skills live in skills/ and work without an OpenShell source checkout. Install them with npx skills add NVIDIA/OpenShell.
| Skill | Purpose |
|---|---|
openshell-cli |
CLI usage, sandbox lifecycle, provider management, and BYOC workflows |
debug-openshell-cluster |
Diagnose gateway deployment and health issues |
debug-inference |
Diagnose attached-provider inference, native endpoints, and migration from the retired managed endpoint |
generate-sandbox-policy |
Generate YAML sandbox policies from requirements or API documentation |
Public skills use openshell --help for installed command syntax and published OpenShell documentation for product concepts and configuration. They must not depend on repository-relative source or documentation files.
Agent Skills for Contributors
Contributor and maintainer skills live in .agents/skills/. They are marked internal so the Agent Skills CLI excludes them from ordinary public discovery, but repository-aware agent harnesses can discover and load them natively. Internal metadata is a discovery filter, not an access-control boundary.
| Category | Skill | Purpose |
|---|---|---|
| Contributing | create-spike |
Investigate a problem, produce a structured GitHub issue |
| Contributing | create-rfc |
Create RFC proposals from the repository template |
| Contributing | build-from-issue |
Plan and implement work from a GitHub issue (maintainer workflow) |
| Contributing | create-github-issue |
Create well-structured GitHub issues |
| Contributing | create-github-pr |
Create pull requests with proper conventions |
| Reviewing | review-github-pr |
Summarize PR diffs and key design decisions |
| Reviewing | review-security-issue |
Assess security issues for severity and remediation |
| Reviewing | fix-security-issue |
Implement an approved security remediation plan |
| Reviewing | watch-github-actions |
Monitor CI pipeline status and logs |
| Reviewing | launch-openshell-gator |
Launch and supervise OpenShell gator agents for issue and PR monitoring |
| Reviewing | test-release-canary |
Dispatch and iterate on the Release Canary workflow that smoke-tests published artifacts |
| Triage | triage-issue |
Assess, classify, and route community-filed issues |
| Platform | helm-dev-environment |
Start and manage the local Kubernetes development environment |
| Platform | tui-development |
Development guide for the ratatui-based terminal UI |
| Platform | build-openshell-mxc-windows |
Maintain and validate the build-only x64 and ARM64 Windows MSVC lane |
| Documentation | update-docs-from-commits |
Scan recent commits and draft doc updates for user-facing changes |
| Maintenance | sync-agent-infra |
Detect and fix drift across agent-first infrastructure files |
| Reference | sbom |
Generate SBOMs and resolve dependency licenses |
Issue Workflow
Community issues move through triage, technical validation, and human acceptance. The repository's state:* labels record these stages. Inspect the current GitHub labels and their descriptions before applying or interpreting them; do not assume a fixed label list. An agent may assess evidence and request missing information. A maintainer decides whether to accept valid work and where it belongs on the roadmap.
A direct request to an agent authorizes the requested planning or implementation. A request to plan alone does not authorize implementation. For unattended work, inspect current state descriptions, maintainer assignments, and comments to determine the authorized phase. Technical validation alone does not authorize implementation. Check for an existing owner, branch, or PR before starting.
Do not file suspected vulnerabilities as public issues. Follow SECURITY.md. Use the specialized security skills for authorized review or remediation.
Prerequisites
Install mise. This is used to set up the development environment.
# Install mise (macOS/Linux)
curl https://mise.run | sh
After installing mise, activate it with mise activate or add it to your shell.
Shell setup examples:
# Bash
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
# Fish
echo '~/.local/bin/mise activate fish | source' >> ~/.config/fish/config.fish
# Zsh
echo 'eval "$(~/.local/bin/mise activate zsh)"' >> ~/.zshrc
Project requirements:
- Rust 1.94+
- Python 3.11+
- Docker (running)
Z3 installation
The openshell-prover crate and standalone openshell-prover-cli binary link
directly against Z3. The openshell-server crate depends on the prover, and
the openshell-gateway binary crate depends on openshell-server in turn.
The openshell-cli crate does not depend on Z3. The Nix development shell
supplies Z3. For builds outside that shell on macOS and Linux, install the
system Z3 development package; z3-sys discovers it through pkg-config.
The linker uses the installed static or shared library. The Nix development
shell provides a static Z3 library.
# macOS
brew install z3
# Ubuntu / Debian
sudo apt install libz3-dev
# Fedora
sudo dnf install z3-devel
To build Z3 from source instead, enable vendored-z3 (requires CMake and a C++
compiler):
cargo build -p openshell-prover --features vendored-z3
cargo build -p openshell-prover-cli --features vendored-z3
Local gateway image and E2E builds enable vendored-z3 so their
copied gateway binaries do not need a shared Z3 library in the runtime image.
For x86-64 and ARM64 Windows MSVC builds, use one of these Z3 paths:
- Prebuilt Z3 (the default for
windows:*tasks):z3-sysdownloads the pinned Z3 5.1.0 GitHub release for the target architecture on the first build. Cargo reuses the extracted archive from its target directory. Windows CI authenticates the GitHub API request withREAD_ONLY_GITHUB_TOKENand preserves the archive in the architecture-specific Cargo target cache. For cold local builds, you may setREAD_ONLY_GITHUB_TOKENto avoid anonymous GitHub API rate limits. - System Z3: point
Z3_LIBRARY_PATH_OVERRIDEat the directory containing the target-compatible MSVC Z3 library andZ3_SYS_Z3_HEADERat the full path toz3.h. Thewindows:*tasks use this path automatically whenZ3_LIBRARY_PATH_OVERRIDEis set.
openshell-prover itself has no bindgen/libclang dependency, so building
just this crate does not require LIBCLANG_PATH:
cargo build -p openshell-prover --target x86_64-pc-windows-msvc --features prebuilt-z3
Windows full build
To build the full set of Windows binaries, including openshell-gateway.exe
and openshell.exe, use the windows:build:x64 mise task instead of a
single-crate cargo build. It downloads the pinned prebuilt Z3 release by default. A
full build also compiles crates that use bindgen (e.g. the MXC driver on
Windows), so it requires libclang.dll; if LLVM is not on the default search
path, set LIBCLANG_PATH to the directory containing libclang.dll:
$env:LIBCLANG_PATH='C:\Program Files\Microsoft Visual Studio\2022\<Edition>\VC\Tools\Llvm\x64\bin'
mise run --skip-tools windows:build:x64
To use a local x64 Z3 release instead of the prebuilt download, set
Z3_LIBRARY_PATH_OVERRIDE and Z3_SYS_Z3_HEADER before running the task:
$env:Z3_LIBRARY_PATH_OVERRIDE='C:\path\to\z3-5.1.0-x64-win\bin'
$env:Z3_SYS_Z3_HEADER='C:\path\to\z3-5.1.0-x64-win\include\z3.h'
mise run --skip-tools windows:build:x64
macOS build tools
Install Apple Command Line Tools before building locally:
xcode-select --install
Getting Started
# One-time trust
mise trust
# Run a standalone gateway for local development
mise run gateway
Building the openshell CLI
Inside this repository, openshell is a local shortcut script at scripts/bin/openshell. The script will
- Build
openshell-cliif needed. - Run the local debug CLI binary under
target/debug/openshell.
Because mise adds scripts/bin to PATH for this project, you can run openshell directly from the repo.
openshell --help
openshell sandbox create -- codex
Rust build cache
Mise preserves an existing SCCACHE_DIR so each environment can choose where
to store compiler cache entries. When SCCACHE_DIR is unset, OpenShell uses
the worktree-local .cache/sccache directory. To make cache entries available
to multiple worktrees on a workstation, set the variable to a user-level
directory before activating mise. For example:
export SCCACHE_DIR="$HOME/.cache/openshell/sccache"
CI can select a different directory or configure a remote sccache backend
without changing the workstation setting. Cargo output remains in each
worktree's target/ directory.
OpenShell does not set SCCACHE_BASEDIRS. Sccache loads base directories when
its machine-local daemon starts, but the correct workspace root differs for
each worktree. Cache reuse therefore depends on the compiler inputs: outputs
that embed absolute paths, including Rust dependencies in some builds, can
still miss across worktrees.
Main Tasks
These are the primary mise tasks for day-to-day development:
| Task | Purpose |
|---|---|
mise run gateway |
Run a standalone gateway for local development |
mise run sandbox |
Create or reconnect to the dev sandbox |
mise run test |
Default test suite |
mise run e2e |
Default end-to-end test lane |
mise run ci |
Full local CI checks (lint, compile/type checks, tests) |
mise run docs |
Validate Fern docs locally |
mise run helm:docs |
Regenerate the Helm chart README |
mise run clean |
Clean build artifacts |
Project Structure
| Path | Purpose |
|---|---|
crates/ |
Rust crates |
crates/openshell-policy-schema/ |
Canonical authored policy DTOs and bounded YAML/JSON parser |
crates/openshell-prover-cli/ |
Standalone local policy boundary checker |
python/ |
Python SDK and bindings |
sdk/go/ |
Go SDK (types, gRPC clients, converters) |
sdk/typescript/ |
TypeScript SDK (Connect client and generated protobuf bindings) |
proto/ |
Protocol buffer definitions and public API conventions |
tasks/ |
mise task definitions and build scripts |
deploy/ |
Dockerfiles, Helm chart, Kubernetes manifests |
docs/ |
Published Fern docs source, navigation, and content assets |
fern/ |
Fern site config, components, and theme assets |
plans/ |
Local plans (git-ignored) |
rfc/ |
Request for Comments proposals |
skills/ |
Public skills for using and operating OpenShell |
.agents/ |
Contributor skills and persona definitions |
RFCs
New features always start as GitHub issues using the feature request template. For cross-cutting architectural decisions, API contract changes, or process proposals that need broad consensus, maintainers may ask for an RFC from the issue and assign an RFC number there. RFCs live in rfc/. See rfc/README.md for the full lifecycle and guidelines.
Public API conventions
Follow the protobuf API conventions when adding or changing gRPC contracts. The guide defines entity-reference naming, workspace selectors, field design, and schema-evolution rules.
Documentation
If your change affects user-facing behavior (new flags, changed defaults, new features, bug fixes that contradict existing docs), update the relevant pages under docs/ in the same PR and adjust docs/index.yml if navigation changes. For explicit navigation entries, keep page: aligned with sidebar-title when present and put relative slug: values in docs/index.yml. Reserve frontmatter slug for folder-discovered pages or absolute URL overrides. Keep every page URL equal to its file path under docs/; mise run docs checks this with docs:nav.
To ensure your doc changes follow NVIDIA documentation style, use the update-docs-from-commits skill.
It scans commits, identifies doc pages that need updates, and drafts content that follows the style guide in docs/CONTRIBUTING.mdx.
To preview Fern docs locally:
mise run docs:serve
To run non-interactive validation:
mise run docs
PRs that touch docs/** or fern/** are validated by .github/workflows/branch-docs.yml, and they get a preview when FERN_TOKEN is available to the workflow.
Release Dev publishes the dev docs version from main. Release Tag publishes an immutable stable version and updates latest. See fern/README.md for the source layout, version model, and publishing workflows.
docs/ is the source-of-truth docs tree. fern/ contains the site configuration, components, theme assets, and its README.
See docs/CONTRIBUTING.mdx for the current docs authoring guide.
Pull Requests
- Create a branch from
mainnamed<type>/<issue-id>-<short-description>/<github-username>, using a Conventional Commits type such asfeat,fix,docs, orchore. - Make your changes with tests.
- Run the checks appropriate to the affected code and behavior, as described below.
- Open a PR using the
create-github-prskill or manually following the PR template.
Every PR must close an existing issue. In the PR's Related Issue section, use Closes #NNN for the issue covering that PR's scope. Split multi-PR work into a closable issue for each PR; a tracking issue can link them. Security fixes follow the private disclosure process in SECURITY.md.
Choose Verification for the Change
Choose checks based on the files changed and the behavior they can affect. Run the relevant formatter, linter, type or compile checks, and tests for those areas. Include dependent components when a shared API, schema, dependency, or build change can affect them.
For contributor guidance, skills, Markdown, and issue or PR templates, validate formatting, links, YAML, and cross references as applicable. Run docs validation when published docs or navigation change. These changes do not require full Rust or SDK suites when they cannot affect those components.
For code changes, run tests for the affected crates or SDKs and their dependent behavior. For sandbox, policy, or deployment infrastructure changes, run the relevant E2E lane. Broaden verification when the change spans components, focused checks fail, or a concrete regression risk remains.
mise run ci runs the full repository checks, and mise run pre-commit runs broad formatting and lint checks. Use them when that scope is warranted; they are not blanket prerequisites for every change. Report what actually ran and any relevant limitation in the PR. Stop once the checks needed for the change have passed.
Commit Messages
This project uses Conventional Commits. All commit messages must follow the format:
<type>(<scope>): <description>
[optional body]
[optional footer(s)]
Types:
feat- New featurefix- Bug fixdocs- Documentation onlychore- Maintenance tasks (dependencies, build config)refactor- Code change that neither fixes a bug nor adds a featuretest- Adding or updating testsci- CI/CD changesperf- Performance improvements
Examples:
feat(cli): add --verbose flag to openshell run
fix(sandbox): handle timeout errors gracefully
docs: update installation instructions
chore(deps): bump tokio to 1.40
DCO
All human contributions must include a Signed-off-by line in each commit message. This certifies you have the right to submit the work under the project license. Dependabot-authored dependency update PRs are allowlisted because the bot cannot sign commits.
The project uses version 1.1 of the Developer Certificate of Origin:
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
git commit -s -m "feat(sandbox): add new capability"
DCO sign-off is separate from cryptographic commit signing. CI requires signing for org members so that copy-pr-bot can mirror your PR automatically; see CI.md for setup.
CI
How PR CI runs, the test:e2e, test:e2e-gpu, and test:e2e-kubernetes labels, copy-pr-bot, and commit-signing setup are documented in CI.md.