Developer experience bundle
Use this bundle when creating or improving local developer workflows, Dev Containers, Codespaces, VS Code setup, inner-loop debugging, or contributor onboarding for Drasi projects.
Principle
A new developer should be able to clone the repository, open the documented environment, run the sample, make a source change, see the query result, and verify the reaction without guessing hidden setup steps.
Recommended new-project defaults
Include, where appropriate:
.devcontainer/for repeatable local or Codespaces onboarding.- Pinned Drasi CLI, Docker image, Rust toolchain, Node/Python helpers, and database images.
- A single documented entry point such as
make test,make dev,just test, or./scripts/validate.sh. - Example
.env.examplewith safe placeholders and no real secrets. - Scripts for start, validate, test data, watch/query results, and cleanup.
- A README section that shows expected output, not only commands.
VS Code extension guidance
The Drasi VS Code extension can help developers manage resources, watch live ContinuousQuery results, and debug ContinuousQueries before applying them to a Drasi environment.
Use it as an accelerator, not as the only path:
- Keep CLI/script equivalents for every critical VS Code action.
- Document which runtime the extension is connected to.
- Do not rely on screenshots alone for acceptance; provide commands and expected outputs.
- Pin or document the extension version used when screenshots or CodeLens behavior matter.
- Use the extension for quick query iteration, then keep the validated query in source control.
VS Code action → CLI mapping
Every critical action a developer takes in the Drasi VS Code extension needs a CLI or REST equivalent so CI, scripts, and headless contributors can reproduce it. K8s commands are grounded in the Drasi CLI reference linked from references/current-sources.md; REST paths are grounded in the management endpoints already named in that file (sources, queries, reactions, health, OpenAPI, docs). When a specific path is not already documented in the skill, the table says "see Drasi Server OpenAPI" rather than inventing one.
| VS Code action | CLI / REST equivalent | Notes |
|---|---|---|
| Apply resource | drasi apply -f <file> (K8s) or POST /api/v1/sources / POST /api/v1/queries / POST /api/v1/reactions (Server) |
required for CI; pick the endpoint that matches the resource kind |
| Watch query results | drasi watch <query> (K8s) or GET /api/v1/queries/<id>/stream (Server, see Drasi Server OpenAPI for exact path) |
SSE; expect long-lived response |
| Debug ContinuousQuery | extension-only; export the input event set to JSON for replay in tests | no Drasi CLI debug subcommand is documented; treat as VS Code accelerator |
| Delete resource | drasi delete <kind> <name> (K8s) or DELETE /api/v1/<kind>/<name> (Server) |
dependency order matters: reactions → queries → sources |
| View resource status | drasi list <kind> (K8s) or GET /api/v1/<kind> (Server) |
use for CI smoke check; also GET /health to confirm Server is up |
If a REST path above does not match what your Drasi Server build exposes, resolve it against /api/v1/openapi.json or /api/v1/docs/ on the running Server before pinning it in scripts.
CLI command surface (verified 2026-08-23, installed CLI)
Full installed command set: apply, completion, delete, describe, env, ingress, init, list, namespace, secret, tunnel, uninstall, version, wait, watch. The commands below are the ones this skill historically under-documents ; prefer them over hand-rolled equivalents when generating runbooks or scripts:
drasi secret set <name>/drasi secret delete <name>— CLI-side secrets management. Use for credentials a Source/Reaction references by name instead of embedding values in YAML; never echo secret values into logs or transcripts.drasi tunnel <source|reaction> <name> <port>— secure local tunnel to a Source or Reaction (kinds are case-insensitive), e.g.drasi tunnel reaction my-reaction 8080. Default to this for local client connectivity in development; connect directly to the service endpoint only in production.drasi uninstall— removes a Drasi environment from a namespace. NOT equivalent to a version downgrade: cross-minor reinstalls wipe all state (see recovery bundle). Use only for deliberate teardown.drasi delete <kind> <name>— single-resource removal; always respect dependency order reactions → queries → sources, and preferdrasi waitafter each step before deleting dependents.drasi env all|current|delete|kube|use— multi-environment configuration: register contexts (kube), list (all), select default (use); commands then target that environment unless-n/--namespaceoverrides per invocation. Prefer explicit-nin CI scripts so output never depends on ambient selection state.drasi completion <bash|zsh|fish|powershell>— shell autocompletion; include in devcontainer setup docs for contributor onboarding.
Inner-loop workflow
A strong Drasi inner loop should support:
- Start dependencies.
- Apply or start Drasi runtime resources.
- Wait for source/query/reaction readiness.
- Send one insert/update/delete change.
- Watch query results.
- Verify reaction side effect.
- Reset to a clean state.
Example script names:
scripts/dev-start.sh
scripts/apply-drasi.sh
scripts/seed-data.sh
scripts/send-test-change.sh
scripts/watch-results.sh
scripts/validate-e2e.sh
scripts/cleanup.shConcrete .devcontainer skeleton
The bundle references .devcontainer/ and a set of scripts but does not show the contents. The following is a minimal starter that wires Drasi inner-loop development to VS Code and Codespaces. Treat it as a starter - adjust per project (toolchain versions, exposed ports, postCreateCommand) and pin to digests for production-bound work.
.devcontainer/devcontainer.json (starter - adjust per project):
{
"name": "drasi-dev",
"build": { "dockerfile": "Dockerfile" },
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "27",
"moby": true
},
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {
"version": "1.30",
"helm": "3.15",
"minikube": "1.33"
}
},
"postCreateCommand": "./scripts/dev-start.sh",
"forwardPorts": [8080, 5432],
"portsAttributes": {
"8080": { "label": "Drasi Server", "onAutoForward": "notify" },
"5432": { "label": "PostgreSQL", "onAutoForward": "silent" }
},
"customizations": {
"vscode": {
"extensions": ["DrasiProject.drasi"]
}
},
"remoteUser": "vscode"
}.devcontainer/Dockerfile (starter - adjust per project; pin tags to known versions; do not use the floating latest tag in production-bound images):
# Pinned base. Replace tag with a known-good version for your tenant.
FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04
ARG RUST_VERSION=1.82.0
ARG NODE_VERSION=20.17.0
# Rust toolchain (pinned)
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
| bash -s -- -y --default-toolchain ${RUST_VERSION} --profile minimal
ENV PATH="/root/.cargo/bin:${PATH}"
# Node toolchain (pinned via nvm-installed binary)
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs=${NODE_VERSION}-1nodesource1 \
&& rm -rf /var/lib/apt/lists/*
# Drasi CLI — replace with a release tag once one is published upstream;
# see references/current-sources.md for the current state of releases.
# Do not bake :latest into images destined for production.Docker-in-Docker is supplied by the dev container feature pinned above rather than installed in the Dockerfile, to keep the image small and the host privilege story explicit. Re-check references/current-sources.md before bumping any of these versions.
Inner-loop latency targets
These are engineering targets the team should measure on its own hardware and record in versions.md or the project README. They are not Drasi-published SLAs and not guarantees from any upstream component.
| Inner-loop edit | Target latency | Notes |
|---|---|---|
| Edit a Cypher ContinuousQuery, see new result for an already-streamed event | under 5 seconds | developer expectation only; tune locally and re-measure after Drasi upgrades |
| Add a new Source, observe its first event end-to-end | under 30 seconds | provider-dependent - first-time Postgres replication slot creation alone can add minutes |
| Replace a reaction config, see next firing match the new config | under 10 seconds | depends on reaction restart strategy and dependent query recompute |
Treat these as numbers to measure, not numbers to assume. Capture the actual observed value during synthetic-user runs and record it alongside the rest of the evidence in templates/drasi-acceptance-evidence.md. Cross-link bundles/observability/guide.md for the metrics and traces that make these latencies measurable in the first place.
Fresh-machine validation
Before claiming the developer setup works, run this procedure on a clean clone (a fresh Codespace or a host that has never built the dev container). This mirrors the synthetic-user pattern in bundles/synthetic-user-testing/guide.md and should be runnable by a contributor who has never touched the repository.
- Clone the repository fresh into a directory that does not already contain build artefacts or cached state.
- Open the project in VS Code with Dev Containers (or open as a GitHub Codespace) and let
postCreateCommandcomplete without manual intervention. - Run the starter example end-to-end via the documented one-command path (for example
make devor./scripts/validate-e2e.sh). - Observe a query result on the watch stream (CLI
drasi watch <query>or VS Code extension) for a seeded change event, and record the observed latency against the targets in the section above. - Trigger the reaction side effect (or assert on the reaction's observable output) and capture proof - log line, written row, or HTTP call - that the reaction fired exactly once for the change.
- Run the documented cleanup (
./scripts/cleanup.shor equivalent) and confirm no Drasi resources, databases, or containers remain. Re-running step 3 from this state must still succeed.
If any step requires undocumented manual fixes, treat that as a developer-experience bug and update this bundle and the project README before signing off.
Dev Container and Codespaces guardrails
- Avoid relying on host-installed tools unless they are documented as prerequisites.
- Ensure Docker-in-Docker or Kubernetes-in-Docker requirements are explicit.
- Prefer local test databases for tutorials; use cloud dependencies only when the scenario requires them.
- Keep cloud credentials out of the container image.
- Validate both a clean first run and a repeated second run.
Documentation quality bar
Developer-facing docs should include:
- Prerequisites with versions.
- Commands in the correct working directory.
- Expected outputs or status indicators.
- Troubleshooting for common readiness and port issues.
- Cleanup steps.
- A link to the synthetic-user test evidence for reusable examples.
Completion evidence
### Developer experience evidence
- Environment: <local/devcontainer/codespaces>
- Pinned tools: <list>
- One-command path: <command>
- Query debug path: <CLI/VS Code extension/both>
- E2E validation: <command and summary>
- Cleanup verified: <yes/no>Exit criteria
Developer-experience work is complete only when:
- A fresh developer can start from a clean checkout, Codespace, Dev Container, or documented local setup.
- Required tools and versions are pinned or explicitly checked.
- VS Code extension steps have equivalent CLI/script paths for automation.
- Seed data, validation commands, and expected outputs are documented.
- Cleanup works without hidden local state.
- The path has been run by a synthetic user or equivalent clean-environment test for reusable scaffolds.