Update siGit Code Cloud skill
Seto Elkahfi committed
Jun 22, 2026 at 19:44 UTC
29c1fece9d0719dd9ff3f2bc04ac0b785344efc4
3 files changed
+314
-1
.agents/AGENTS.md
+73
index e69de29..9494730 100644
--- a/.agents/AGENTS.md
+++ b/.agents/AGENTS.md
@@ -0,0 +1,73 @@
+# Agent rules for sigit-si
+
+Rules for agents working in this repo and across the siGit / smbCloud codebases.
+Read this before writing code or docs.
+
+## Repositories and the public boundary
+
+| Repo | Visibility | What it is |
+|------|------------|------------|
+| `sigit` (`getsigit/sigit`) | **public** | siGit Code: the Rust CLI / ACP coding agent |
+| `sigit-si` | private | the Rails app, account API, and these agent docs |
+| `sigit-app` | private | the desktop client (Tauri) |
+| `onde-cloud` | private | the OpenAI-compatible inference service |
+| `onde` | open source | the on-device inference crate |
+
+**Cardinal rule: `sigit` is public.** Everything committed there is world-readable:
+code, comments, doc strings, tests, commit messages. Never put any of the
+following in the public repo:
+
+- secrets, API keys, tokens, or credentials;
+- the identity of the upstream model providers behind siGit Code Cloud, or the
+ fact that any specific provider sits behind it;
+- business strategy, pricing, or positioning;
+- internal smbCloud auth mechanics (`app_secret`, validation flows, trust
+ boundaries);
+- customer names or internal infrastructure detail.
+
+That material belongs in `sigit-si` (server and strategy) or `sigit-app`
+(desktop), which are private. When in doubt, put the explanation in a private
+skill and keep the public comment purely about what the code does.
+
+## Writing for the public repo
+
+- Keep comments and docs technical and neutral. Say what the code does, not why
+ it is a good business.
+- Strip AI-writing tells: no em dashes, no forced groups of three, no
+ promotional or significance-inflating language, no "not just X but Y". Plain is
+ correct for reference text.
+- User- and client-facing error messages must not name a provider or echo
+ upstream error bodies. Log the detail server-side; return something neutral.
+
+## Branding
+
+Names are case-sensitive: `siGit Code` (product), `siGit Code Cloud` (hosted
+tier), `sigit` (CLI and crate), `smbCloud` (company), `Onde Cloud` / `Onde
+Inference` (infrastructure), `onde` (crate). The public `sigit` repo has a
+`branding` skill with the full rules.
+
+## Skills in this repo
+
+- `sigit-code`: engineering reference for siGit Code and how it connects to the
+ ecosystem (accounts, the cloud tier, cross-repo work).
+- `sigit-code-cloud`: the hosted inference product: auth, tiers, backend
+ selection, and the `onde-cloud` API behind it.
+- `smbcloud-auth`: the auth service integration.
+- `sigit-app`: the desktop client.
+- `deployment`, `design-system`, `local-environment`: as named.
+
+The public `sigit` repo carries its own skills (`ai-assisted-coding`,
+`agent-client-protocol`, `tool-calling`, `branding`, `sigit-code-release`). Those
+stay public-safe.
+
+## Validation
+
+- Rust (`sigit`, `onde-cloud`): `cargo build`, `cargo test`, `cargo clippy`.
+- Rails (`sigit-si`): `bundle exec rails routes`, `ruby -c` on touched files,
+ `rails db:migrate` when the schema changes.
+
+## Common mistakes
+
+- Putting strategy, a provider name, or a secret into the public `sigit` repo.
+- Leaving AI-writing tells in public prose.
+- Mixing the product, CLI, and company names.
.agents/skills/sigit-code-cloud/SKILL.md
+175
new file mode 100644
index 0000000..84fc06e
--- /dev/null
+++ b/.agents/skills/sigit-code-cloud/SKILL.md
@@ -0,0 +1,175 @@
+---
+name: sigit-code-cloud
+description: Reference for siGit Code Cloud, the hosted inference offering for siGit Code. Use when working on the cloud product surface: the sigit login/logout/whoami account commands, the credential store, provider/backend selection (on-device vs siGit Code Cloud vs BYO endpoint), neutral quality tiers, or the onde-cloud API behind it. Covers the Copilot/Azure layering, the decoupled InferenceBackend engine, auth via sigit.si/api/v1, and what must never leak to the client.
+---
+
+# siGit Code Cloud
+
+**siGit Code Cloud** is the hosted inference offering for **siGit Code**. The
+product framing is deliberate:
+
+- **siGit Code Cloud is the product**, like GitHub Copilot. The user signs in,
+ picks a quality tier, and it works. They never see an API key, a base URL, or
+ the name of any model provider.
+- **Onde Cloud is the infrastructure**, like Azure. It is the OpenAI-compatible
+ inference service siGit Code Cloud runs on, and it is an implementation detail.
+- **Onde Cloud, in turn, routes to upstream providers** (today Anthropic) and
+ hides them too, see the onde-cloud `router`/`anthropic` modules.
+
+Keep the names straight (see the `branding` skill): the product is `siGit Code`,
+the hosted tier is `siGit Code Cloud`, the CLI is `sigit`, the company is
+`smbCloud`, the inference infrastructure is `Onde Cloud` / `Onde Inference`, and
+the on-device Rust crate is `onde`.
+
+## The layering (why it's built this way)
+
+The original instinct was right: abstract the infrastructure away entirely. The
+engine underneath is intentionally generic so that "Onde Cloud = swappable infra"
+is literally true, but that generality is an *internal* seam, not the product.
+
+```
+┌─ Product surface (Copilot) ────────────────────────────────────────┐
+│ sigit login → pick a tier (Fast / Balanced / Large) → just works │
+│ No key, no URL, no provider names. Token is the only credential. │
+└────────────────────────────────────────────────────────────────────┘
+┌─ Engine (generic, swappable) ──────────────────────────────────────┐
+│ InferenceBackend trait │
+│ ├─ LocalBackend → on-device onde::ChatEngine │
+│ └─ OpenAiBackend → any {base_url, api_key, model} over HTTP │
+└────────────────────────────────────────────────────────────────────┘
+┌─ Infrastructure (hidden) ──────────────────────────────────────────┐
+│ Onde Cloud (OpenAI-compatible) → router → Anthropic (never named) │
+└────────────────────────────────────────────────────────────────────┘
+```
+
+The generic engine is also what enables the **BYO-endpoint escape hatch**: an
+advanced user or enterprise can point siGit Code at their own OpenAI/Azure
+endpoint. That is a power-user override, **not** the front door.
+
+## Backend selection (precedence)
+
+Resolved in `sigit/src/provider.rs::active_provider()`, first match wins:
+
+1. **Override (power user / BYO):** `OPENAI_BASE_URL` + `OPENAI_API_KEY` env vars,
+ or the active profile in `~/.config/sigit/providers.toml`.
+2. **siGit Code Cloud (default product):** when logged in (`sigit login` stored a
+ token). Baked-in endpoint, token auth, neutral tier. The user provides nothing
+ but their login.
+3. **On-device:** not logged in, no override → runs locally via `onde::ChatEngine`.
+
+A missing piece in the override path is loud, not silent: `OPENAI_BASE_URL` set
+without `OPENAI_API_KEY` logs a warning and falls back to on-device, rather than
+silently looking like "the cloud didn't work."
+
+## Quality tiers (neutral by design)
+
+The user picks a tier, never a model id or provider. `SIGIT_TIER` selects it
+(default `balanced`); `provider.rs::tier_to_model` maps it:
+
+| Tier | Wire model id (Onde Cloud) |
+|------|----------------------------|
+| `fast` | `onde-fast` |
+| `balanced` | `onde-balanced` |
+| `large` | `onde-large` |
+
+The UI shows `siGit Code Cloud · Balanced`, never the model id or "Anthropic".
+`ProviderConfig.display_name` carries this label; the title bar uses it, and
+`InferenceBackend::is_remote()` ensures a persisted *local* model name can never
+override the cloud label.
+
+## Account / auth (via sigit.si)
+
+`sigit login | logout | whoami` are plain CLI verbs dispatched in
+`sigit/src/main.rs` before the TUI/ACP split, implemented in
+`sigit/src/account.rs`.
+
+- **Trust boundary is `sigit.si`.** It holds the confidential smbCloud
+ `app_secret` server-side and returns the client only a **bearer token**. The
+ client must never hold `app_secret` (it is a public/shipped binary, see the
+ `smbcloud-auth` skill's public-client rule).
+- **Base URL:** `$SIGIT_API_URL`, else `https://sigit.si` (dev:
+ `http://localhost:8088`).
+- **Endpoints (sigit.si `/api/v1`, token-based):** `POST /users/sign_in` →
+ `access_token`; `GET /me`; `DELETE /users/sign_out`. These reuse the planned
+ `/api/v1` JSON surface in sigit-si (see the `smbcloud-auth` skill); confirm the
+ exact routes/response shapes against that app and keep them in sync with the
+ desktop `account/command_*` set.
+- **Credential store:** `sigit/src/credentials.rs` writes
+ `~/.config/sigit/credentials.toml` (`$SIGIT_CONFIG_DIR` override), mode `0600`,
+ holding `access_token` (+ email for display).
+
+## Onde Cloud side (the API the cloud tier calls)
+
+Repo: `onde-cloud` (Rust/axum, OpenAI-compatible).
+
+- **Endpoints:** `POST /v1/chat/completions`, `GET /v1/models`.
+- **Routing:** `router.rs` resolves a request `model` to a backend. Neutral public
+ ids (`onde-fast/balanced/large`) map to upstream models; raw `claude-*` ids are
+ accepted as backward-compatible aliases but never advertised. `/v1/models`
+ reports `owned_by: "onde-inference"`: the upstream provider is never disclosed.
+- **Tool calling:** `anthropic.rs` maps OpenAI function-calling ↔ Anthropic
+ `tool_use`/`tool_result` (assistant `tool_calls` → `tool_use` blocks; coalesced
+ `tool` messages → one `tool_result` user turn; `parameters` → `input_schema`;
+ `stop_reason` → `finish_reason`). This is what makes the cloud tier a real
+ *agent* backend, not just chat.
+- **Error hygiene:** client-facing errors are neutral ("Onde Cloud upstream error
+ (NNN)"); full upstream detail is logged server-side only. Never echo provider
+ names or upstream error bodies to the client.
+- **Auth:** validates `app_id:app_secret` against smbCloud (`DEV_MODE=true`
+ bypasses for local dev and accepts any bearer).
+
+## Local dev / testing
+
+```bash
+# 1. Onde Cloud API (needs ANTHROPIC_API_KEY in onde-cloud/.env for the cloud tier)
+cd ~/Repositories/onde-cloud && set -a && . ./.env && set +a && ./target/debug/onde-cloud
+# → listens on $PORT (e.g. 8090); DEV_MODE=true accepts any bearer
+
+# 2a. Product path: point siGit Code Cloud at the local API and log in
+SIGIT_CLOUD_URL=http://localhost:8090/v1 SIGIT_API_URL=http://localhost:8088 \
+ sigit login # stores a token; then `sigit` defaults to the cloud
+
+# 2b. BYO/override path (no login needed): explicit endpoint
+OPENAI_BASE_URL=http://localhost:8090/v1 OPENAI_API_KEY=dev:dev SIGIT_TIER=fast sigit
+# (or ~/.config/sigit/providers.toml with active = "<profile>")
+```
+
+`SIGIT_CLOUD_URL` overrides the baked-in cloud endpoint for dev. Watch routing in
+the server log: `chat: routing app_id=... to Onde Cloud`. Use the `fast` tier
+while testing to keep upstream spend low.
+
+## Key files
+
+- `sigit/src/account.rs`: `login`/`logout`/`whoami`, sigit.si `/api/v1` client.
+- `sigit/src/credentials.rs`: local token store.
+- `sigit/src/provider.rs`: backend precedence, tiers, cloud default.
+- `sigit/src/backend.rs`: `InferenceBackend` trait, `LocalBackend`, `OpenAiBackend`.
+- `onde-cloud/src/{router,anthropic,chat,types}.rs`: the hosted API + mapping.
+
+## Open items / known gaps
+
+- **Inference token ↔ Onde Cloud auth.** Onde Cloud currently validates
+ `app_id:app_secret`; the product needs it to accept the sigit.si-issued user
+ token (sigit.si fronts/mints inference auth, mirroring the `git_token` exchange
+ in `sigit-app`). Until then, dev relies on `DEV_MODE`.
+- **`sigit.si/api/v1` routes** are assumed from the desktop contract, confirm and
+ keep in sync with the `smbcloud-auth` skill.
+- **Usage/billing:** `onde-cloud` returns zeroed `usage`; wire Anthropic's
+ returned token counts through for metering.
+- **Tool-call id fingerprint:** Onde Cloud passes Anthropic's `toolu_…` tool-call
+ ids straight through (OpenAI uses `call_…`). Reversibly rewrite before any
+ external launch so the id format doesn't reveal the backend.
+- **ACP path:** the Zed/ACP server in `sigit/src/main.rs` still calls `onde`
+ directly; route it through `InferenceBackend` too.
+
+## Common mistakes
+
+- Making BYO-endpoint (env / `providers.toml`) the default instead of the
+ `sigit login` product experience.
+- Exposing a model id, base URL, or provider name in product UI/errors.
+- Treating the account access token as a model API key, or shipping smbCloud
+ `app_secret` in the `sigit` binary (public-client violation).
+- Letting a persisted local model name show in the title while routing to the
+ cloud (guard with `InferenceBackend::is_remote()`).
+- Mixing the names: `siGit Code` (product), `siGit Code Cloud` (hosted tier),
+ `sigit` (CLI), `smbCloud` (company), `Onde Cloud` (infrastructure).
.agents/skills/sigit-code/SKILL.md
+66
-1
index 4b4b301..76327e9 100644
--- a/.agents/skills/sigit-code/SKILL.md
+++ b/.agents/skills/sigit-code/SKILL.md
@@ -1,4 +1,69 @@
---
name: sigit-code
-description: A skill for working with siGit Code
+description: Engineering reference for siGit Code, the public Rust CLI / ACP coding agent (getsigit/sigit), and how it connects to the smbCloud ecosystem (accounts, siGit Code Cloud). Use when working on the sigit codebase, its inference backends, account commands, or coordinating a change across sigit / sigit-si / onde-cloud. The repo is public; see AGENTS.md for what must not go in it.
---
+
+# siGit Code
+
+siGit Code is the coding agent: a Rust CLI (`sigit`, repo `getsigit/sigit`) that
+runs over ACP in editors like Zed and as an interactive terminal TUI. The repo is
+**public**, keep secrets, provider names, and strategy out of it (see
+`AGENTS.md`).
+
+## Codebase map (`sigit/src`)
+
+- `main.rs`: entry point. Routes to the account subcommands
+ (`login`/`logout`/`whoami`), the interactive TUI (when stdin is a tty), or the
+ ACP server (when stdin is piped). Holds the system prompt.
+- `chat.rs`: the terminal TUI and the agent's tool-call loop.
+- `backend.rs`: the `InferenceBackend` trait with two implementations:
+ `LocalBackend` (on-device via the `onde` crate's `ChatEngine`) and
+ `OpenAiBackend` (any OpenAI-compatible HTTP endpoint). Uses neutral
+ `ToolSpec` / `ToolCall` / `ToolResult` / `TurnResult` types so the loop does
+ not depend on a specific backend.
+- `provider.rs`: backend selection and quality tiers. Precedence: an explicit
+ override (`OPENAI_BASE_URL` + `OPENAI_API_KEY`, or `~/.config/sigit/providers.toml`),
+ then siGit Code Cloud when logged in, then on-device.
+- `account.rs`: `login` / `logout` / `whoami` against the account API.
+- `credentials.rs`: the local session-token store.
+- `tools.rs`: tool implementations and their JSON schemas.
+- `models.rs`, `setup.rs`: local model picker and HuggingFace cache setup.
+
+## Inference backends
+
+The agent loop talks to `Arc<dyn InferenceBackend>` and never to a concrete
+engine. `LocalBackend` runs fully on-device. `OpenAiBackend` handles the cloud
+tier and any bring-your-own endpoint. `is_remote()` lets the UI label the active
+backend correctly.
+
+For the hosted product (auth, tiers, and the `onde-cloud` API), see the
+`sigit-code-cloud` skill. For the on-device `ChatEngine` API itself, see the
+`ai-assisted-coding` skill in the public `sigit` repo. For the protocol, see its
+`agent-client-protocol` skill.
+
+## Account and cloud integration
+
+siGit Code authenticates through `sigit.si` and uses the returned session token
+for siGit Code Cloud requests. Keep the account command request/response shapes
+in sync with the desktop client (`sigit-app`) and the `smbcloud-auth` skill;
+those shapes are a shared contract.
+
+## Building and testing
+
+`cargo build`, `cargo test`, `cargo clippy`. Interactive (TUI) mode is Unix-only
+because it redirects file descriptors to keep logs out of the display.
+
+## Public-repo discipline
+
+Anything written into `sigit` is world-readable. Keep comments technical, humanize
+prose (no AI-writing tells), and never name an upstream provider or expose
+secrets or strategy. The reasoning that belongs with a change usually goes in a
+private skill here, not in a public code comment. See `AGENTS.md`.
+
+## Cross-references
+
+- `sigit-code-cloud` (this repo): the hosted inference product.
+- `smbcloud-auth` (this repo): the auth service.
+- `ai-assisted-coding` (sigit repo): the `onde` `ChatEngine` API.
+- `agent-client-protocol` (sigit repo): ACP.
+- `branding` (sigit repo): the case-sensitive names.