sigit-code 1.2.1__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {sigit_code-1.2.1 → sigit_code-1.3.0}/.agents/skills/sigit-code-release/SKILL.md +13 -0
  2. sigit_code-1.3.0/.claude/skills/run-sigit/SKILL.md +134 -0
  3. sigit_code-1.3.0/.claude/skills/run-sigit/driver.mjs +126 -0
  4. sigit_code-1.3.0/.claude/skills/run-sigit/tui-smoke.sh +41 -0
  5. {sigit_code-1.2.1 → sigit_code-1.3.0}/CHANGELOG.md +28 -0
  6. {sigit_code-1.2.1 → sigit_code-1.3.0}/CLAUDE.md +18 -3
  7. {sigit_code-1.2.1 → sigit_code-1.3.0}/Cargo.lock +8 -18
  8. {sigit_code-1.2.1 → sigit_code-1.3.0}/Cargo.toml +7 -4
  9. {sigit_code-1.2.1 → sigit_code-1.3.0}/PKG-INFO +1 -1
  10. {sigit_code-1.2.1 → sigit_code-1.3.0}/README.md +24 -13
  11. sigit_code-1.3.0/examples/skills/README.md +36 -0
  12. sigit_code-1.3.0/examples/skills/commit-message/SKILL.md +44 -0
  13. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/backend.rs +311 -6
  14. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/chat.rs +395 -183
  15. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/credentials.rs +3 -0
  16. sigit_code-1.3.0/src/instructions.rs +241 -0
  17. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/main.rs +491 -141
  18. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/models.rs +35 -2
  19. sigit_code-1.3.0/src/settings.rs +153 -0
  20. sigit_code-1.3.0/src/skills.rs +613 -0
  21. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/tools.rs +1 -0
  22. {sigit_code-1.2.1 → sigit_code-1.3.0}/.agents/AGENTS.md +0 -0
  23. {sigit_code-1.2.1 → sigit_code-1.3.0}/.agents/skills/agent-client-protocol/SKILL.md +0 -0
  24. {sigit_code-1.2.1 → sigit_code-1.3.0}/.agents/skills/ai-assisted-coding/SKILL.md +0 -0
  25. {sigit_code-1.2.1 → sigit_code-1.3.0}/.agents/skills/branding/SKILL.md +0 -0
  26. {sigit_code-1.2.1 → sigit_code-1.3.0}/.agents/skills/tool-calling/SKILL.md +0 -0
  27. {sigit_code-1.2.1 → sigit_code-1.3.0}/.github/workflows/ci.yml +0 -0
  28. {sigit_code-1.2.1 → sigit_code-1.3.0}/.github/workflows/release-crates.yml +0 -0
  29. {sigit_code-1.2.1 → sigit_code-1.3.0}/.github/workflows/release-github.yml +0 -0
  30. {sigit_code-1.2.1 → sigit_code-1.3.0}/.github/workflows/release-homebrew.yml +0 -0
  31. {sigit_code-1.2.1 → sigit_code-1.3.0}/.github/workflows/release-npm.yml +0 -0
  32. {sigit_code-1.2.1 → sigit_code-1.3.0}/.github/workflows/release-pypi.yml +0 -0
  33. {sigit_code-1.2.1 → sigit_code-1.3.0}/.gitignore +0 -0
  34. {sigit_code-1.2.1 → sigit_code-1.3.0}/.nvmrc +0 -0
  35. {sigit_code-1.2.1 → sigit_code-1.3.0}/LICENSE +0 -0
  36. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/README.md.tmpl +0 -0
  37. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/package-main.json.tmpl +0 -0
  38. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/package.json.tmpl +0 -0
  39. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/scripts/render-main-package.cjs +0 -0
  40. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/scripts/render-platform-package.cjs +0 -0
  41. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/sigit/.gitignore +0 -0
  42. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/sigit/README.md +0 -0
  43. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/sigit/package.json +0 -0
  44. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/sigit/src/index.ts +0 -0
  45. {sigit_code-1.2.1 → sigit_code-1.3.0}/npm/sigit/tsconfig.json +0 -0
  46. {sigit_code-1.2.1 → sigit_code-1.3.0}/pypi/README.md +0 -0
  47. {sigit_code-1.2.1 → sigit_code-1.3.0}/pypi/pyproject.toml +0 -0
  48. {sigit_code-1.2.1 → sigit_code-1.3.0}/pyproject.toml +0 -0
  49. {sigit_code-1.2.1 → sigit_code-1.3.0}/rust-toolchain.toml +0 -0
  50. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/account.rs +0 -0
  51. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/provider.rs +0 -0
  52. {sigit_code-1.2.1 → sigit_code-1.3.0}/src/setup.rs +0 -0
@@ -32,6 +32,18 @@ Use this skill when preparing a release for this repository.
32
32
  - Release workflows are tag-driven. `release-github.yml`, `release-npm.yml`, `release-pypi.yml`, `release-crates.yml`, and `release-homebrew.yml` all derive `RELEASE_VERSION` from a `v*.*.*` tag or a manually supplied tag input.
33
33
  - The crate is published to crates.io (`release-crates.yml`) and the Homebrew tap is updated (`release-homebrew.yml`) as part of the tag-driven flow. Per the siGit release flow, Homebrew is auto-triggered — do not dispatch it manually.
34
34
 
35
+ ## Git release flow
36
+
37
+ Releases are cut from `development` and shipped on `main`. The published tags (`v1.2.0`, `v1.2.1`) point at the `main`-side merge commit, never at a release branch or at `development`. Follow this order:
38
+
39
+ 1. Branch `release/v<version>` off `development`.
40
+ 2. Apply the version bump and changelog edits, then commit (e.g. `Release v<version>`).
41
+ 3. Merge `release/v<version>` back into `development`.
42
+ 4. Merge `development` into `main` (commit message: `Merge development into main for v<version> release`).
43
+ 5. Tag `v<version>` on that `main` merge commit, then push `main` and the tag.
44
+
45
+ Pushing the `v*.*.*` tag is what fires every release workflow, so create and push it only after the merge into `main` has landed. Do not commit, tag, or push until the user explicitly asks — confirm the version and that they want the release to go out first.
46
+
35
47
  ## Typical files to inspect
36
48
 
37
49
  - `Cargo.toml`
@@ -52,6 +64,7 @@ Use this skill when preparing a release for this repository.
52
64
  - `npm/sigit/package.json` is left at `0.0.0-dev` unless the packaging flow itself changed.
53
65
  - `pypi/pyproject.toml` still uses dynamic versioning unless there is a deliberate packaging change.
54
66
  - Release workflows still derive their version from the tag as expected.
67
+ - Git flow followed: bump committed on `release/v<version>`, merged back to `development`, then `development` merged into `main`, with `v<version>` tagged on the `main` merge commit.
55
68
  - Release notes or changelog entries match the actual changes.
56
69
  - CI-equivalent local checks pass for the relevant platform or target.
57
70
  - Package names, install commands, and branding stay consistent.
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: run-sigit
3
+ description: Build, launch, and drive the sigit AI coding agent — run the ACP server, screenshot the interactive TUI, smoke-test the CLI. Use when asked to run sigit, start the agent, screenshot the chat UI, or verify a change to the binary.
4
+ ---
5
+
6
+ # Run sigit
7
+
8
+ `sigit` is a single Rust binary that picks its mode at startup from whether stdin
9
+ is a TTY:
10
+
11
+ - **ACP mode** (stdin not a TTY): newline-delimited JSON-RPC 2.0 over stdio — the
12
+ Agent Client Protocol surface that Zed / VS Code drive. This is the primary
13
+ programmatic handle. Drive it with **`.claude/skills/run-sigit/driver.mjs`**.
14
+ - **Interactive TUI** (stdin is a TTY): a full-screen ratatui chat, Unix-only.
15
+ Drive it under tmux with **`.claude/skills/run-sigit/tui-smoke.sh`**.
16
+ - **CLI subcommands**: `sigit login | logout | whoami`, handled before the split.
17
+
18
+ Both drivers avoid on-device inference: `initialize`, `session/new`, and slash
19
+ commands (`/whoami`, `/help`, `/status`) answer **without** loading a multi-GB
20
+ GGUF model, so they work on a clean machine with nothing cached and no network.
21
+
22
+ Paths below are relative to the repo root (`<unit>/`).
23
+
24
+ ## Prerequisites
25
+
26
+ - Rust toolchain (pinned in `rust-toolchain.toml`); `cargo` on PATH.
27
+ - Node ≥ 18 for the ACP driver (`driver.mjs`).
28
+ - `tmux` for the TUI smoke test only: `brew install tmux` (macOS) /
29
+ `apt-get install -y tmux` (Linux).
30
+
31
+ ## Build
32
+
33
+ ```bash
34
+ cargo build # debug binary at target/debug/sigit
35
+ ```
36
+
37
+ First build is slow (it compiles `onde` / mistralrs); incremental rebuilds are
38
+ sub-second. Use `cargo build --release` for `target/release/sigit` if you want
39
+ realistic inference speed — the drivers default to the debug binary.
40
+
41
+ ## Run (agent path)
42
+
43
+ ### ACP server — `driver.mjs`
44
+
45
+ Spawns the binary in ACP mode, runs `initialize` → `session/new` →
46
+ `session/prompt /whoami`, prints every frame, exits 0 on success:
47
+
48
+ ```bash
49
+ node .claude/skills/run-sigit/driver.mjs
50
+ # SIGIT_BIN=target/release/sigit node .claude/skills/run-sigit/driver.mjs
51
+ ```
52
+
53
+ Expected tail:
54
+
55
+ ```
56
+ <-- notify session/update "Signed in to siGit Code Cloud as demo@sigit.si."
57
+ "stopReason": "end_turn"
58
+ OK — ACP handshake, session, and /whoami round-tripped.
59
+ ```
60
+
61
+ The `/whoami` reply arrives as an `agent_message_chunk` notification — the same
62
+ streaming surface a real prompt fans out across many chunks. To drive real
63
+ streamed inference, send a `session/prompt` with ordinary text instead of a
64
+ slash command (needs a cached local model or a signed-in cloud tier).
65
+
66
+ ### Interactive TUI — `tui-smoke.sh`
67
+
68
+ Launches the TUI under tmux, types `/help`, writes the rendered screen to
69
+ `$TMPDIR/sigit-tui.txt` (the "screenshot" for a terminal app), then quits:
70
+
71
+ ```bash
72
+ .claude/skills/run-sigit/tui-smoke.sh
73
+ cat "${TMPDIR:-/tmp}/sigit-tui.txt" # view the captured screen
74
+ ```
75
+
76
+ To poke it by hand, the same tmux moves the script automates:
77
+
78
+ ```bash
79
+ tmux new-session -d -s sigit -x 120 -y 35
80
+ tmux send-keys -t sigit './target/debug/sigit' Enter
81
+ sleep 6
82
+ tmux capture-pane -t sigit -p # read the screen
83
+ tmux send-keys -t sigit '/help' Enter
84
+ tmux send-keys -t sigit C-c # Ctrl+C quits
85
+ tmux kill-session -t sigit
86
+ ```
87
+
88
+ ### CLI smoke
89
+
90
+ ```bash
91
+ ./target/debug/sigit whoami # prints the signed-in account, exit 0
92
+ ```
93
+
94
+ ## Run (human path)
95
+
96
+ ```bash
97
+ cargo run # stdin is your TTY → launches the TUI
98
+ ```
99
+
100
+ A full-screen chat opens; type a message or `/help`, Ctrl+C to quit. Useless
101
+ headless or with stdin piped — that path falls through to ACP mode instead.
102
+
103
+ ## Gotchas
104
+
105
+ - **The ACP server never exits on stdin EOF.** `printf '…' | sigit | head` hangs:
106
+ the process stays alive holding stdout open, so `head` blocks waiting for bytes
107
+ that only stop when you kill it. You must read the response frame and then
108
+ `kill` the child — that's the whole reason `driver.mjs` exists instead of a
109
+ one-line pipe.
110
+ - **Piping stdin forces ACP mode.** Any non-TTY stdin (a pipe, `</dev/null`)
111
+ routes to the JSON-RPC server, not the TUI. The TUI needs a real PTY, hence
112
+ tmux.
113
+ - **Handshake is intentionally model-free.** `initialize` / `session/new` defer
114
+ GGUF loading to the first real prompt, so they're fast and need no network. A
115
+ text `session/prompt` to an on-device model triggers a ~1–2 GB download on
116
+ first use.
117
+ - **The default model depends on sign-in state.** On a signed-in machine the
118
+ picker shows a cloud tier (e.g. `onde-cloud (onde-fast)`); logged out it
119
+ defaults to an on-device model. `sigit whoami` shows which.
120
+ - **Logs go to different places per mode.** ACP mode → stderr (the driver prefixes
121
+ them `[sigit]`). TUI mode redirects all stdout/stderr to `$TMPDIR/sigit.log` so
122
+ the ratatui surface stays clean — tail that file to debug the TUI.
123
+ - **macOS model cache is shared with the desktop app**, under
124
+ `~/Library/Group Containers/group.com.ondeinference.apps/models/`; other
125
+ platforms use `~/.cache/huggingface/`.
126
+
127
+ ## Troubleshooting
128
+
129
+ - `binary not found: target/debug/sigit` → run `cargo build` first.
130
+ - Driver hangs / times out on `initialize` → you're likely running a stale binary
131
+ or one that crashed at startup; check the `[sigit]` stderr lines it echoes.
132
+ - `tmux not installed` from `tui-smoke.sh` → `brew install tmux`.
133
+ - TUI capture is blank → increase the `sleep` before `capture-pane`; the banner
134
+ and (lazy) model selection take a few seconds on a cold start.
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ // ACP driver for the `sigit` binary.
3
+ //
4
+ // `sigit` runs as an Agent Client Protocol server when stdin is NOT a TTY
5
+ // (newline-delimited JSON-RPC 2.0 over stdio — the same surface Zed / VS Code
6
+ // drive). This script spawns the binary in that mode, runs a scripted handshake,
7
+ // prints every request/response/notification, and exits non-zero on failure.
8
+ //
9
+ // It deliberately avoids triggering on-device inference: `initialize`,
10
+ // `session/new`, and slash commands like `/whoami` and `/status` answer without
11
+ // loading a multi-GB GGUF model, so the driver works on a clean machine with no
12
+ // model cached and no network.
13
+ //
14
+ // Usage:
15
+ // node driver.mjs [path-to-binary] # default: target/debug/sigit
16
+ // SIGIT_BIN=target/release/sigit node driver.mjs
17
+ //
18
+ // Exit code 0 = every step got a well-formed JSON-RPC result.
19
+
20
+ import { spawn } from "node:child_process";
21
+ import { createInterface } from "node:readline";
22
+ import { existsSync } from "node:fs";
23
+
24
+ const bin = process.argv[2] || process.env.SIGIT_BIN || "target/debug/sigit";
25
+ if (!existsSync(bin)) {
26
+ console.error(`binary not found: ${bin} — run \`cargo build\` first`);
27
+ process.exit(2);
28
+ }
29
+
30
+ // Force ACP mode regardless of how the driver itself was launched: pipe stdin so
31
+ // the child's stdin is not a TTY.
32
+ const child = spawn(bin, [], { stdio: ["pipe", "pipe", "pipe"] });
33
+
34
+ // Surface the agent's own logs (it writes them to stderr in ACP mode).
35
+ createInterface({ input: child.stderr }).on("line", (l) =>
36
+ console.error(`[sigit] ${l}`),
37
+ );
38
+
39
+ const pending = new Map(); // id -> {resolve, method}
40
+ const notifications = [];
41
+ let nextId = 1;
42
+ let failed = false;
43
+
44
+ createInterface({ input: child.stdout }).on("line", (line) => {
45
+ line = line.trim();
46
+ if (!line) return;
47
+ let msg;
48
+ try {
49
+ msg = JSON.parse(line);
50
+ } catch {
51
+ console.error(`<-- (non-JSON) ${line}`);
52
+ return;
53
+ }
54
+ if (msg.id !== undefined && (msg.result !== undefined || msg.error)) {
55
+ const waiter = pending.get(msg.id);
56
+ console.log(`<-- response #${msg.id} (${waiter?.method ?? "?"})`);
57
+ console.log(JSON.stringify(msg.result ?? msg.error, null, 2));
58
+ if (msg.error) failed = true;
59
+ waiter?.resolve(msg);
60
+ pending.delete(msg.id);
61
+ } else if (msg.method) {
62
+ // A notification or a server->client request. We only observe these.
63
+ notifications.push(msg);
64
+ const update = msg.params?.update;
65
+ let detail = "";
66
+ if (update?.sessionUpdate === "agent_message_chunk") {
67
+ // The streamed assistant text — one chunk per AgentMessageChunk. With the
68
+ // streaming backend a real prompt produces many of these.
69
+ detail = ` ${JSON.stringify(update.content?.text ?? update.content)}`;
70
+ } else if (update?.sessionUpdate) {
71
+ detail = ` (${update.sessionUpdate})`;
72
+ }
73
+ console.log(`<-- notify ${msg.method}${detail}`);
74
+ }
75
+ });
76
+
77
+ function send(method, params) {
78
+ const id = nextId++;
79
+ const req = { jsonrpc: "2.0", id, method, params };
80
+ console.log(`--> request #${id} ${method}`);
81
+ child.stdin.write(JSON.stringify(req) + "\n");
82
+ return new Promise((resolve, reject) => {
83
+ pending.set(id, { resolve, method });
84
+ setTimeout(() => {
85
+ if (pending.has(id)) {
86
+ pending.delete(id);
87
+ reject(new Error(`timeout waiting for ${method} (#${id})`));
88
+ }
89
+ }, 20_000);
90
+ });
91
+ }
92
+
93
+ async function main() {
94
+ // 1. Handshake.
95
+ await send("initialize", {
96
+ protocolVersion: 1,
97
+ clientCapabilities: {},
98
+ });
99
+
100
+ // 2. Open a session rooted at the repo. `cwd` must be absolute.
101
+ const sessionRes = await send("session/new", {
102
+ cwd: process.cwd(),
103
+ mcpServers: [],
104
+ });
105
+ const sessionId = sessionRes.result?.sessionId;
106
+ if (!sessionId) throw new Error("session/new returned no sessionId");
107
+
108
+ // 3. Drive a no-inference slash command through the prompt surface. `/whoami`
109
+ // reports the signed-in account; it never touches the model.
110
+ await send("session/prompt", {
111
+ sessionId,
112
+ prompt: [{ type: "text", text: "/whoami" }],
113
+ });
114
+
115
+ console.log("\nOK — ACP handshake, session, and /whoami round-tripped.");
116
+ }
117
+
118
+ main()
119
+ .catch((err) => {
120
+ console.error(`FAILED: ${err.message}`);
121
+ failed = true;
122
+ })
123
+ .finally(() => {
124
+ child.kill("SIGTERM");
125
+ setTimeout(() => process.exit(failed ? 1 : 0), 150);
126
+ });
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env bash
2
+ # Drive the interactive ratatui TUI under tmux: launch it, type /help, dump the
3
+ # rendered screen to a file ("screenshot" for a terminal app), then quit cleanly.
4
+ #
5
+ # The TUI only starts when stdin is a real TTY, so it must run inside a terminal
6
+ # multiplexer — tmux gives us one plus `capture-pane` to read what it drew.
7
+ # Requires tmux (`brew install tmux`). Unix only (the TUI is #[cfg(unix)]).
8
+ #
9
+ # Usage: .claude/skills/run-sigit/tui-smoke.sh [path-to-binary]
10
+ set -euo pipefail
11
+
12
+ BIN="${1:-${SIGIT_BIN:-target/debug/sigit}}"
13
+ SESSION="sigit-smoke-$$"
14
+ OUT="${TMPDIR:-/tmp}/sigit-tui.txt"
15
+
16
+ if [[ ! -x "$BIN" ]]; then
17
+ echo "binary not found/executable: $BIN — run \`cargo build\` first" >&2
18
+ exit 2
19
+ fi
20
+ command -v tmux >/dev/null || { echo "tmux not installed (brew install tmux)" >&2; exit 2; }
21
+
22
+ cleanup() { tmux kill-session -t "$SESSION" 2>/dev/null || true; }
23
+ trap cleanup EXIT
24
+
25
+ tmux new-session -d -s "$SESSION" -x 120 -y 35
26
+ tmux send-keys -t "$SESSION" "$BIN" Enter
27
+ sleep 6 # banner + (lazy) model selection
28
+ tmux send-keys -t "$SESSION" '/help' Enter
29
+ sleep 2
30
+ tmux capture-pane -t "$SESSION" -p > "$OUT"
31
+ tmux send-keys -t "$SESSION" C-c # Ctrl+C quits
32
+ sleep 1
33
+
34
+ echo "Captured TUI screen -> $OUT"
35
+ if grep -q '/whoami' "$OUT"; then
36
+ echo "OK — TUI launched and /help rendered."
37
+ else
38
+ echo "FAILED — /help output not found in capture:" >&2
39
+ sed '/^$/d' "$OUT" | head -40 >&2
40
+ exit 1
41
+ fi
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.3.0
4
+
5
+ Adds a Local Inference on/off toggle, the open [Agent Skills](https://agentskills.io)
6
+ format, and support for project instruction files (`AGENTS.md` and the like).
7
+
8
+ ### What changed
9
+
10
+ - Added a Local Inference on/off setting that is the explicit local-vs-cloud mode switch. It is persisted in `~/.config/sigit/settings.toml` (default on, local-first) and can be overridden with `SIGIT_LOCAL_INFERENCE`
11
+ - Toggle it with the `/local [on|off]` command (TUI and ACP); ACP clients without slash-command support get an equivalent "Local Inference" On/Off control in the session config panel
12
+ - `/models` now groups models by nature — Local vs siGit Code Cloud — and highlights the active mode's group while still showing the other, so the cloud tiers stay discoverable
13
+ - Discovers Agent Skills (folders with a `SKILL.md`) from `.sigit/skills/` and `.claude/skills/` in the project, `~/.config/sigit/skills/`, and `~/.claude/skills/`
14
+ - Follows the spec's progressive disclosure: each skill's name and description are advertised up front via a new `skill` tool, and the full instructions load only when the agent activates one
15
+ - Added a `/skills` slash command (TUI and ACP) that lists the discovered skills
16
+ - Reads project instruction files at session start: `AGENTS.md` (the cross-tool standard) and `CLAUDE.md`, walking from the working directory up to the repository root, plus a global file under `~/.config/sigit/`, and injects them into the session's system context so their guidance is always in force
17
+ - Nested instruction files are ordered outermost-first so the closest, most specific file takes precedence; the scan never reads above the repository root
18
+ - On-device models are no longer loaded implicitly. The chat UI and ACP sessions come up immediately, and the local model is brought into memory only when you run the `/load` command (or pick one in `/models`). Prompts sent before a model is loaded now return a hint instead of blocking on a multi-minute download.
19
+
20
+ ## 1.2.2
21
+
22
+ Streams assistant tokens as they arrive, on-device and over the cloud.
23
+
24
+ ### What changed
25
+
26
+ - Streamed assistant tokens live in the TUI and ACP sessions, both on-device and through siGit Code Cloud
27
+ - On-device inference streams only when a turn offers no tools, since `onde` can't stream and detect tool calls in the same pass; tool-capable turns still resolve in one shot
28
+ - Fixed the TUI so the latest message stays visible in long chats
29
+ - Put the cloud model-switch confirmation on its own line in ACP
30
+
3
31
  ## 1.2.1
4
32
 
5
33
  Stabilizes the Zed/ACP integration and finishes the cloud-tier wiring on top of 1.2.0.
@@ -64,6 +64,21 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
64
64
  - **`src/tools.rs`** — agent tool schemas + execution: `read_file`, `create_directory`,
65
65
  `list_directory`, `search_files`, `read_website`, `create_file`, `edit_file`, `delete_file`,
66
66
  `run_command`. Add a tool in both the spec list and the execute `match`.
67
+ - **`src/skills.rs`** — [Agent Skills](https://agentskills.io) support. Discovers skill
68
+ folders (each with a `SKILL.md`: YAML frontmatter `name` + `description`, then Markdown
69
+ instructions) from `.sigit/skills/` and `.claude/skills/` in the cwd, `$SIGIT_CONFIG_DIR/skills/`,
70
+ and `~/.claude/skills/`. Progressive disclosure: the discovery list (name + description) is
71
+ baked into the dynamically-built `skill` tool's description, and activating a skill (the model
72
+ calls `skill` with a name) loads the full `SKILL.md` body. The `skill` tool is appended in the
73
+ `*_as_specs`/`build_tool_specs` layer (not in `all_tools()`) so its description can be dynamic,
74
+ and only when at least one skill exists.
75
+ - **`src/instructions.rs`** — project instruction files, the always-on counterpart to skills.
76
+ Reads `AGENTS.md` (the cross-tool [agents.md](https://agents.md) standard) and `CLAUDE.md`,
77
+ walking from the session cwd up to the repo root (nearest ancestor with `.git`, never above it),
78
+ plus a global file under `$SIGIT_CONFIG_DIR`. Files are ordered outermost-first so the deepest
79
+ (most specific) wins. The combined block is injected via `session_context_message` in `main.rs`
80
+ — pushed as a system message at every ACP session entry point (new/load/fork + model switch)
81
+ and appended to the system prompt on the cloud and TUI-startup paths.
67
82
  - **`src/chat.rs`** — the Unix-only ratatui TUI. Loading-spinner phase then chat; uses
68
83
  `tokio::select!` to multiplex terminal events with streaming tokens.
69
84
  - **`src/setup.rs`** — model cache location, local model discovery, selected-model persistence.
@@ -74,9 +89,9 @@ feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete b
74
89
  - **`src/credentials.rs`** — local session-token store (TOML, `0600` on Unix).
75
90
  - **`src/models.rs`** — model-picker types shared across platforms.
76
91
 
77
- Slash commands (`/help`, `/models`, `/login`, `/logout`, `/whoami`, `/reload`, `/clear`,
78
- `/status`) are advertised via `advertise_commands` in `main.rs` and handled in both the TUI and
79
- ACP sessions.
92
+ Slash commands (`/help`, `/models`, `/skills`, `/login`, `/logout`, `/whoami`, `/reload`,
93
+ `/clear`, `/status`) are advertised via `advertise_commands` in `main.rs` and handled in both the
94
+ TUI and ACP sessions.
80
95
 
81
96
  ## Model cache (macOS)
82
97
 
@@ -20,9 +20,9 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
20
20
 
21
21
  [[package]]
22
22
  name = "agent-client-protocol"
23
- version = "0.13.0"
23
+ version = "1.0.1"
24
24
  source = "registry+https://github.com/rust-lang/crates.io-index"
25
- checksum = "e037424fa2da7aea1363b42e0c792d117b4d0ceb9d6d6f58719ce7520c22eabf"
25
+ checksum = "16302d16c7531355db16593d99c38c8297db0c4653aa7dd80c3556bb17f4cd8c"
26
26
  dependencies = [
27
27
  "agent-client-protocol-derive",
28
28
  "agent-client-protocol-schema",
@@ -30,7 +30,6 @@ dependencies = [
30
30
  "blocking",
31
31
  "futures",
32
32
  "futures-concurrency",
33
- "jsonrpcmsg",
34
33
  "rustc-hash 2.1.2",
35
34
  "schemars 1.2.1",
36
35
  "serde",
@@ -38,13 +37,14 @@ dependencies = [
38
37
  "shell-words",
39
38
  "tracing",
40
39
  "uuid 1.23.3",
40
+ "windows-sys 0.61.2",
41
41
  ]
42
42
 
43
43
  [[package]]
44
44
  name = "agent-client-protocol-derive"
45
- version = "0.11.1"
45
+ version = "1.0.1"
46
46
  source = "registry+https://github.com/rust-lang/crates.io-index"
47
- checksum = "cabdc9d845d08ec7ed2d0c9de1ae4a1b198301407d55855261572761be90ec9f"
47
+ checksum = "88b37d552feb6981a0109febda6b71fc723678cd065974c2d76279c19c407095"
48
48
  dependencies = [
49
49
  "quote",
50
50
  "syn 2.0.117",
@@ -52,9 +52,9 @@ dependencies = [
52
52
 
53
53
  [[package]]
54
54
  name = "agent-client-protocol-schema"
55
- version = "0.13.4"
55
+ version = "1.1.0"
56
56
  source = "registry+https://github.com/rust-lang/crates.io-index"
57
- checksum = "8dd79d476e25d8562d46b368eb5fc629edd3dd6be75e6b036606e6f4f867e7e7"
57
+ checksum = "ac542aba230234b1591ace7286a47c0514fe3efc3037d43296bde31ba7ee5728"
58
58
  dependencies = [
59
59
  "anyhow",
60
60
  "derive_more",
@@ -2879,16 +2879,6 @@ dependencies = [
2879
2879
  "wasm-bindgen",
2880
2880
  ]
2881
2881
 
2882
- [[package]]
2883
- name = "jsonrpcmsg"
2884
- version = "0.1.2"
2885
- source = "registry+https://github.com/rust-lang/crates.io-index"
2886
- checksum = "6d833a15225c779251e13929203518c2ff26e2fe0f322d584b213f4f4dad37bd"
2887
- dependencies = [
2888
- "serde",
2889
- "serde_json",
2890
- ]
2891
-
2892
2882
  [[package]]
2893
2883
  name = "lazy_static"
2894
2884
  version = "1.5.0"
@@ -5210,7 +5200,7 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
5210
5200
 
5211
5201
  [[package]]
5212
5202
  name = "sigit"
5213
- version = "1.2.1"
5203
+ version = "1.3.0"
5214
5204
  dependencies = [
5215
5205
  "agent-client-protocol",
5216
5206
  "anyhow",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sigit"
3
- version = "1.2.1"
3
+ version = "1.3.0"
4
4
  edition = "2024"
5
5
  description = "siGit Code — ACP-compatible AI coding agent. Sí, git."
6
6
  documentation = "https://github.com/getsigit/sigit"
@@ -18,7 +18,7 @@ path = "src/main.rs"
18
18
 
19
19
  [dependencies]
20
20
  # ACP protocol SDK
21
- agent-client-protocol = { version = "0.13", features = ["unstable_session_fork", "unstable_session_additional_directories", "unstable_auth_methods"] }
21
+ agent-client-protocol = { version = "1.0", features = ["unstable_session_fork", "unstable_auth_methods"] }
22
22
 
23
23
  # Onde Inference engine (local LLM)
24
24
  # onde = { path = "../onde" }
@@ -30,7 +30,10 @@ tokio-util = { version = "0.7", features = ["compat"] }
30
30
  futures = "0.3"
31
31
 
32
32
  # TUI (interactive chat mode)
33
- ratatui = "0.29"
33
+ # `unstable-rendered-line-info` exposes `Paragraph::line_count`, which we use to
34
+ # pin the message view to the bottom using the exact wrapped-row count (the same
35
+ # WordWrapper that rendering uses) rather than a hand-rolled estimate.
36
+ ratatui = { version = "0.29", features = ["unstable-rendered-line-info"] }
34
37
  crossterm = { version = "0.29", features = ["event-stream"] }
35
38
 
36
39
  # Utilities
@@ -43,6 +46,6 @@ serde_json = "1"
43
46
  toml = "0.8"
44
47
  async-trait = "0.1"
45
48
  regex = "1"
46
- reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] }
49
+ reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls", "stream"] }
47
50
  uuid = { version = "1", features = ["v4"] }
48
51
  rpassword = "7"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sigit-code
3
- Version: 1.2.1
3
+ Version: 1.3.0
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -10,6 +10,8 @@
10
10
 
11
11
  siGit Code is a local coding agent. It runs on your machine, not someone else's. No API keys, no cloud round-trips, no subscription.
12
12
 
13
+ Its home is [code.sigit.si](https://code.sigit.si). You can run it yourself, as below, or use the hosted version (siGit Code Cloud) there if you would rather not run a model locally. [sigit.si](https://sigit.si) is Git hosting built for AI workflows.
14
+
13
15
  It works in any codebase. In smbCloud repos it is more useful out of the box because it already understands the Rust workspace layout, deploy flows, auth boundaries, and GresIQ.
14
16
 
15
17
  You can use it in two ways:
@@ -23,17 +25,6 @@ You can use it in two ways:
23
25
  | Linux | ✓ | ✓ |
24
26
  | Windows | ✓ | not yet |
25
27
 
26
- ## smbCloud context
27
-
28
- In an smbCloud repo, siGit Code already knows a few important things:
29
-
30
- - platform-user flows and tenant-app auth flows are different systems
31
- - `Project` is the umbrella workspace, while `FrontendApp`, `AuthApp`, and GresIQ are separate deployable units
32
- - Next.js SSR deploys are not the same thing as the generic git-push path
33
- - existing crate boundaries and workspace patterns are usually the right place to start
34
-
35
- In other repos it stays general and does not pretend everything is about smbCloud.
36
-
37
28
  ## Install
38
29
 
39
30
  ```sh
@@ -70,7 +61,27 @@ Add this to `~/.config/zed/settings.json`:
70
61
 
71
62
  Use the full absolute path. `~` does not expand here.
72
63
 
73
- ## VS Code with ACP Client
64
+ ## VS Code
65
+
66
+ ### With siGit Code Extension
67
+
68
+ Install from the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=getsigit.sigit-code).
69
+
70
+ ```jsonc
71
+ {
72
+ "sigit.agents": {
73
+ "sigit": {
74
+ "name": "siGit (on-device)",
75
+ "command": "sigit",
76
+ "args": [],
77
+ "env": {}
78
+ },
79
+ },
80
+ "sigit.agent.default": "sigit"
81
+ }
82
+ ```
83
+
84
+ ### With ACP Client
74
85
 
75
86
  Install [ACP Client](https://marketplace.visualstudio.com/items?itemName=formulahendry.acp-client), then add:
76
87
 
@@ -106,4 +117,4 @@ Terminal mode currently needs Unix terminal behavior, so it works on macOS and L
106
117
 
107
118
  ## Copyright
108
119
 
109
- © 2026 [smbCloud](https://smbcloud.xyz/) (Splitfire AB).
120
+ © 2026 [smbCloud Platform](https://smbcloud.xyz/) (Splitfire AB).
@@ -0,0 +1,36 @@
1
+ # Example Agent Skills
2
+
3
+ siGit Code supports the open [Agent Skills](https://agentskills.io) format. A
4
+ skill is a folder containing a `SKILL.md` file — YAML frontmatter (`name` and
5
+ `description`, at minimum) followed by Markdown instructions. Skills can bundle
6
+ `scripts/`, `references/`, and `assets/` that the agent reads on demand.
7
+
8
+ ## Installing a skill
9
+
10
+ Copy a skill folder into one of the directories siGit scans (in priority order):
11
+
12
+ - `.sigit/skills/` or `.claude/skills/` in your project (project-local)
13
+ - `~/.config/sigit/skills/` (honours `$SIGIT_CONFIG_DIR`)
14
+ - `~/.claude/skills/` (shared with the broader ecosystem)
15
+
16
+ For example, to install the `commit-message` skill here for the current project:
17
+
18
+ ```sh
19
+ mkdir -p .sigit/skills
20
+ cp -R examples/skills/commit-message .sigit/skills/
21
+ ```
22
+
23
+ The folder name must match the skill's `name` field.
24
+
25
+ ## How siGit uses them
26
+
27
+ siGit follows the spec's *progressive disclosure*:
28
+
29
+ 1. **Discovery** — at the start of each turn, siGit loads only each skill's
30
+ `name` and `description` into the `skill` tool's description.
31
+ 2. **Activation** — when your task matches a skill, the agent calls the `skill`
32
+ tool with that name, which loads the full `SKILL.md` into context.
33
+ 3. **Execution** — the agent follows the instructions, reading any bundled files
34
+ from the skill's directory with its normal file and command tools.
35
+
36
+ Run `/skills` to list the skills siGit can see.
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: commit-message
3
+ description: Write a clear git commit message from staged changes. Use when the user asks to commit, write a commit message, or describe staged changes.
4
+ license: Apache-2.0
5
+ metadata:
6
+ author: sigit
7
+ version: "1.0"
8
+ ---
9
+
10
+ # Commit message
11
+
12
+ Write a concise, conventional commit message that describes *why* a change was
13
+ made, not just what changed.
14
+
15
+ ## Steps
16
+
17
+ 1. Inspect what is staged: run `git diff --cached` (and `git status` for context).
18
+ 2. Group the changes into a single logical intent. If they span unrelated
19
+ concerns, say so and suggest splitting the commit.
20
+ 3. Write the message:
21
+ - **Subject line**: imperative mood, lowercase after the type, no trailing
22
+ period, ≤ 50 characters. Prefix with a type when it fits the repo's
23
+ convention (`feat:`, `fix:`, `refactor:`, `docs:`, `test:`, `chore:`).
24
+ - **Body** (optional): wrap at 72 columns. Explain the motivation and any
25
+ non-obvious tradeoffs. Reference issues if relevant.
26
+ 4. Show the message to the user before committing. Only run `git commit` if they
27
+ confirm.
28
+
29
+ ## Examples
30
+
31
+ Good subject lines:
32
+
33
+ ```
34
+ fix: stop the picker from reloading a working model on /reload
35
+ refactor: extract skill discovery into its own module
36
+ ```
37
+
38
+ Avoid:
39
+
40
+ ```
41
+ Update files
42
+ fixed bug
43
+ WIP
44
+ ```