Thanks for your interest in contributing! This guide covers development setup, the build/test commands, and the PR flow.
- Rust (stable, via rustup)
- Docker or Podman (the
justfileauto-detects Podman) justcommand runner (cargo install just)
# Start backing infrastructure (Postgres, Redis, MinIO)
just infra
# Configure environment (just run falls back to the example if you skip this)
cp server/.env.example server/.env
# Run the server (single binary — it terminates TLS, validates auth, serves the UI)
just runThe server is the sole ingress: there is no separate gateway process.
cargo build --release -p nasiko
sudo cp target/release/nasiko /usr/local/bin/just run # Server (foreground; sources server/.env)
just infra # Start Postgres, Redis, MinIO
just infra-down # Stop infrastructure
just logs # View infra logs (-f to follow)
just check # cargo check --workspace
just clippy # LintThe authoritative standards live in docs/:
docs/CLEAN_CODE_GUIDE.md— code standards (names, functions, errors, traits, tests)docs/ORGANIZATION.md— where code lives (server/CLI/library layout)docs/API_CONVENTIONS.md— wire format for every HTTP endpoint
The highlights:
The workspace must compile with zero warnings from cargo check and cargo clippy. CI fails
on warnings; run cargo fmt before committing.
All dependencies are declared once in the root Cargo.toml. Crates use dep.workspace = true.
- The server is the single ingress — it validates JWTs itself (the
AuthServicetrait), runs the middleware stack (CORS, tracing, auth, rate limiting), proxies all agent traffic, and serves the embedded UI. Agents are never publicly exposed. - Trait-based extensibility —
AuthService,ContainerRuntime,RoutingEngine,ObservabilityProviderare traits with pluggable implementations, wired once at startup; handlers receiveArc<dyn Trait>. - CLI stays lightweight — the
nasikobinary usesureq(sync HTTP), no tokio, for fast compile times. - UI is vanilla JS — web components, no build step, no framework; embedded in the server binary and served same-origin.
Agents implement the A2A protocol v1.0. Key details:
- Method names:
SendMessage,SendStreamingMessage(gRPC-style) - Role enum:
ROLE_USER,ROLE_AGENT - Header:
A2A-Version: 1.0required - Parts:
[{"text": "..."}](nokindfield in v1.0)
Migrations live in migrations/ and run automatically on server startup via sqlx.
To add a migration:
sqlx migrate add -r <description>cli/ → `nasiko` binary (developer CLI)
server/ → Axum control plane: routes, auth middleware, agent proxy, build worker, UI serving
auth/ → AuthService trait + impls (login, JWT validation, RBAC hooks)
oidc/ → OIDC SSO client
config/ → Config struct (env-driven)
runtime/ → ContainerRuntime trait + DockerRuntime
orchestrator/ → Routing engine: semantic agent selection (shortlist → rerank → select)
react-agent/ → ReAct orchestrator (LLM + tool calls to agents)
mcp-gateway/ → MCP gateway: connectors, per-agent tool permissions, delegation
types/ → A2A protocol types (wraps the a2a crate)
oci/ → Embedded OCI Distribution registry (S3-backed)
flow/ → FlowGuard: anti-DoS cascade limits, flow events
secrets/ → AES-256-GCM encryption for agent secrets
agent-proxy/ → Agent endpoint resolution
observability/ → OpenTelemetry init, Tempo/Loki providers
github/ → GitHub OAuth + source integration
utils/ → Shared helpers
agents/ → Example/seed agents (each a standalone A2A container)
migrations/ → SQL migrations
ui/ → Frontend (vanilla JS web components)
just test-unitServer integration tests need infra up and run serially:
just infra
just test-server # all server integration tests
just test-one auth_flow # a single test file
just test # unit + server integrationcargo fmt, then ensurecargo check --workspaceandcargo clippypass with zero warnings- Add tests for new functionality; keep unit tests hermetic
- Keep PRs focused — one logical change per PR
- Write a clear description of what and why
Open an issue on GitHub with:
- What you expected to happen
- What actually happened
- Steps to reproduce
- Rust version and OS