sigit-code 1.3.2__tar.gz → 1.4.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.
- sigit_code-1.4.0/.agents/AGENTS.md +202 -0
- sigit_code-1.4.0/.claude/skills/agent-client-protocol/SKILL.md +576 -0
- sigit_code-1.4.0/.claude/skills/ai-assisted-coding/SKILL.md +390 -0
- sigit_code-1.4.0/.claude/skills/branding/SKILL.md +203 -0
- sigit_code-1.4.0/.claude/skills/run-sigit/SKILL.md +134 -0
- sigit_code-1.4.0/.claude/skills/run-sigit/driver.mjs +126 -0
- sigit_code-1.4.0/.claude/skills/run-sigit/tui-smoke.sh +41 -0
- sigit_code-1.4.0/.claude/skills/sigit-code-release/SKILL.md +71 -0
- sigit_code-1.4.0/.claude/skills/tool-calling/SKILL.md +351 -0
- sigit_code-1.4.0/AGENTS.md +202 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/CHANGELOG.md +17 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/CLAUDE.md +40 -13
- {sigit_code-1.3.2 → sigit_code-1.4.0}/Cargo.lock +1 -1
- {sigit_code-1.3.2 → sigit_code-1.4.0}/Cargo.toml +7 -2
- {sigit_code-1.3.2 → sigit_code-1.4.0}/PKG-INFO +1 -1
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/chat.rs +1147 -44
- sigit_code-1.4.0/src/headless.rs +473 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/instructions.rs +34 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/main.rs +75 -5
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/mcp.rs +625 -93
- sigit_code-1.4.0/src/permissions.rs +652 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/session_store.rs +94 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/settings.rs +54 -1
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/tools.rs +4 -3
- sigit_code-1.4.0/tests/headless_mode.rs +312 -0
- sigit_code-1.3.2/.agents/AGENTS.md +0 -0
- sigit_code-1.3.2/src/permissions.rs +0 -337
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.agents/skills/agent-client-protocol/SKILL.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.agents/skills/ai-assisted-coding/SKILL.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.agents/skills/branding/SKILL.md +0 -0
- {sigit_code-1.3.2/.claude → sigit_code-1.4.0/.agents}/skills/run-sigit/SKILL.md +0 -0
- {sigit_code-1.3.2/.claude → sigit_code-1.4.0/.agents}/skills/run-sigit/driver.mjs +0 -0
- {sigit_code-1.3.2/.claude → sigit_code-1.4.0/.agents}/skills/run-sigit/tui-smoke.sh +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.agents/skills/sigit-code-release/SKILL.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.agents/skills/tool-calling/SKILL.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.github/workflows/ci.yml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.github/workflows/release-crates.yml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.github/workflows/release-github.yml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.github/workflows/release-homebrew.yml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.github/workflows/release-npm.yml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.github/workflows/release-pypi.yml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.gitignore +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/.nvmrc +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/LICENSE +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/README.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/examples/skills/README.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/examples/skills/commit-message/SKILL.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/README.md.tmpl +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/package-main.json.tmpl +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/package.json.tmpl +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/scripts/render-main-package.cjs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/scripts/render-platform-package.cjs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/sigit/.gitignore +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/sigit/README.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/sigit/package.json +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/sigit/src/index.ts +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/npm/sigit/tsconfig.json +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/pypi/README.md +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/pypi/pyproject.toml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/pyproject.toml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/rust-toolchain.toml +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/account.rs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/backend.rs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/credentials.rs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/models.rs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/provider.rs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/setup.rs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/src/skills.rs +0 -0
- {sigit_code-1.3.2 → sigit_code-1.4.0}/tests/acp_permissions.rs +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to AI coding agents when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What this is
|
|
6
|
+
|
|
7
|
+
`sigit` ("siGit Code") is a single Rust binary: a local-first AI coding agent that runs LLM
|
|
8
|
+
inference on-device (via the `onde` crate / GGUF models) or against a hosted/OpenAI-compatible
|
|
9
|
+
endpoint. It exposes itself two ways from the *same* binary, chosen at startup by whether stdin
|
|
10
|
+
is a TTY:
|
|
11
|
+
|
|
12
|
+
- **ACP mode** (stdin not a TTY): speaks the Agent Client Protocol over stdio for editor
|
|
13
|
+
integration (Zed, VS Code ACP Client). Cross-platform.
|
|
14
|
+
- **Interactive terminal mode** (stdin is a TTY): a full-screen ratatui chat UI. **Unix-only** —
|
|
15
|
+
it relies on fd redirection to keep logs out of the TUI, so Windows gets ACP mode only.
|
|
16
|
+
|
|
17
|
+
Before the TTY/ACP split, `main` also dispatches the account subcommands `sigit login`,
|
|
18
|
+
`sigit logout`, `sigit whoami` (see `src/main.rs` `main()`).
|
|
19
|
+
|
|
20
|
+
## Working in this repo
|
|
21
|
+
|
|
22
|
+
**IMPORTANT — branch naming:** Prefix every working branch with `feature/` (new functionality)
|
|
23
|
+
or `fix/` (bug fixes) — never a tool- or agent-name prefix like `claude/`. Name the branch after
|
|
24
|
+
the *changes it contains*, as a short, descriptive, kebab-case slug that is self-explanatory
|
|
25
|
+
from the name alone (e.g. `feature/tool-permission-system`, `fix/glob-mtime-sort`), never after
|
|
26
|
+
a task, ticket, or session id (not `feature/task-q003hm`).
|
|
27
|
+
|
|
28
|
+
**IMPORTANT — pull request target:** Always open pull requests against the `development` branch,
|
|
29
|
+
never `main`. `main` is release-only; `development` is where day-to-day work integrates.
|
|
30
|
+
|
|
31
|
+
**IMPORTANT — branch off `development`:** Start every working branch from the latest
|
|
32
|
+
`origin/development`. Exception: when new work *depends on* a feature branch that has not merged
|
|
33
|
+
yet (e.g. it builds on tools or APIs that branch introduces), it may be stacked on top of that
|
|
34
|
+
branch instead. When stacking: merge the base PR into `development` first, then rebase the
|
|
35
|
+
stacked branch onto `development` before opening its pull request, so each PR shows only its own
|
|
36
|
+
commits.
|
|
37
|
+
|
|
38
|
+
**IMPORTANT — run CI before pushing:** Run the full CI gate locally and confirm it is green
|
|
39
|
+
*before* pushing a branch or opening a pull request — never push work that fails these:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
cargo fmt -- --check # formatting
|
|
43
|
+
cargo clippy --tests -- -D warnings # lint (warnings are errors)
|
|
44
|
+
cargo test --locked # tests
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Agent assets layout
|
|
48
|
+
|
|
49
|
+
`.agents/` is the canonical home for agent assets; every other agent path in
|
|
50
|
+
the repo is a symlink into it, never a copy:
|
|
51
|
+
|
|
52
|
+
- `.agents/AGENTS.md` — this file, the project instructions. The root
|
|
53
|
+
`AGENTS.md` and `CLAUDE.md` are symlinks to it, so agents.md-standard tools,
|
|
54
|
+
Claude Code, and sigit itself (via `src/instructions.rs`, which prefers
|
|
55
|
+
`AGENTS.md` over `CLAUDE.md` in the same directory and therefore reads it
|
|
56
|
+
once) all load the same content. Edit this file; never replace the root
|
|
57
|
+
symlinks with real files.
|
|
58
|
+
- `.agents/skills/` — all project skills. `.claude/skills` is a symlink to it,
|
|
59
|
+
which is how both Claude Code and sigit itself (via `src/skills.rs`) discover
|
|
60
|
+
them. Add new skills under `.agents/skills/<name>/SKILL.md`, never as real
|
|
61
|
+
files under `.claude/`.
|
|
62
|
+
|
|
63
|
+
## Build / test / lint
|
|
64
|
+
|
|
65
|
+
```sh
|
|
66
|
+
cargo build # debug build
|
|
67
|
+
cargo build --release # release binary at target/release/sigit
|
|
68
|
+
cargo run # launches interactive TUI (stdin is a TTY)
|
|
69
|
+
cargo test # CI runs: cargo test --locked --target <target>
|
|
70
|
+
cargo clippy --tests -- -D warnings # CI gate: clippy is -D warnings on all 4 targets
|
|
71
|
+
cargo fmt -- --check # CI gate (edition 2024)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
CI (`.github/workflows/ci.yml`) runs fmt + clippy + test across four targets:
|
|
75
|
+
`aarch64-apple-darwin`, `x86_64-apple-darwin`, `x86_64-unknown-linux-gnu`,
|
|
76
|
+
`x86_64-pc-windows-msvc`. Clippy is `-D warnings`, so warnings fail the build.
|
|
77
|
+
|
|
78
|
+
Run a single test: `cargo test <test_name>`.
|
|
79
|
+
|
|
80
|
+
## Critical platform constraint: `#[cfg(unix)]` dead code
|
|
81
|
+
|
|
82
|
+
The interactive client is `#[cfg(unix)]`-only. The `InferenceBackend` seam (`backend.rs`) and
|
|
83
|
+
provider resolution (`provider.rs`) are consumed by both the interactive client and the ACP
|
|
84
|
+
server, but several of their items are reached only through the Unix-only interactive paths, so
|
|
85
|
+
the dead-code lint is suppressed *on non-Unix targets only*.
|
|
86
|
+
|
|
87
|
+
Consequence: code can pass clippy on macOS/Linux but fail on the Windows target (or vice versa).
|
|
88
|
+
When touching `backend.rs`, `provider.rs`, or the interactive path, keep the `cfg` gates intact —
|
|
89
|
+
don't "fix" an unused-warning by deleting code that's live on Unix.
|
|
90
|
+
|
|
91
|
+
## Architecture
|
|
92
|
+
|
|
93
|
+
The agent loop is backend-agnostic. The flow: a turn (messages + tool specs) goes to an
|
|
94
|
+
`InferenceBackend`, which returns assistant text and/or tool calls; the loop executes tools and
|
|
95
|
+
feeds results back. Neither the loop nor ACP/TUI surfaces depend on a concrete backend.
|
|
96
|
+
|
|
97
|
+
- **`src/main.rs`** — entry point, mode dispatch, the full ACP `Agent` impl (session lifecycle:
|
|
98
|
+
new/load/fork/prompt/cancel, config options, slash-command advertisement), and the `SYSTEM_PROMPT`
|
|
99
|
+
(note: it bakes in smbCloud-specific context the agent should use when the repo is clearly
|
|
100
|
+
smbCloud, and stay general otherwise).
|
|
101
|
+
- **`src/backend.rs`** — the `InferenceBackend` trait and neutral types (`ToolSpec`, `ToolCall`,
|
|
102
|
+
`ToolResult`, `TurnResult`). Two impls: `LocalBackend` (on-device via `onde::ChatEngine`) and
|
|
103
|
+
`OpenAiBackend` (any OpenAI-compatible HTTP endpoint).
|
|
104
|
+
- **`src/provider.rs`** — decides *which* backend serves inference. Resolution order, first match
|
|
105
|
+
wins: (1) override via `OPENAI_BASE_URL`+`OPENAI_API_KEY` or active profile in
|
|
106
|
+
`~/.config/sigit/providers.toml`; (2) siGit Code Cloud when logged in; (3) on-device.
|
|
107
|
+
- **`src/tools.rs`** — agent tool schemas + execution: `read_file`, `create_directory`,
|
|
108
|
+
`list_directory`, `search_files`, `glob`, `read_website`, `create_file`, `edit_file`,
|
|
109
|
+
`multi_edit`, `delete_file`, `run_command`, `write_todos`, `remember`. Add a tool in both the
|
|
110
|
+
spec list (`all_tools`) and the execute `match` (`execute_tool`). `run_command` also enforces
|
|
111
|
+
commit attribution: when a command creates a new commit that lacks the
|
|
112
|
+
`Co-Authored-By: siGit Code` trailer (`COMMIT_CO_AUTHOR_TRAILER`), it amends the trailer in —
|
|
113
|
+
unless the commit already exists on a remote, which is never rewritten.
|
|
114
|
+
- **`src/skills.rs`** — [Agent Skills](https://agentskills.io) support. Discovers skill
|
|
115
|
+
folders (each with a `SKILL.md`: YAML frontmatter `name` + `description`, then Markdown
|
|
116
|
+
instructions) from `.sigit/skills/` and `.claude/skills/` in the cwd, `$SIGIT_CONFIG_DIR/skills/`,
|
|
117
|
+
and `~/.claude/skills/`. Progressive disclosure: the discovery list (name + description) is
|
|
118
|
+
baked into the dynamically-built `skill` tool's description, and activating a skill (the model
|
|
119
|
+
calls `skill` with a name) loads the full `SKILL.md` body. The `skill` tool is appended in the
|
|
120
|
+
`*_as_specs`/`build_tool_specs` layer (not in `all_tools()`) so its description can be dynamic,
|
|
121
|
+
and only when at least one skill exists.
|
|
122
|
+
- **`src/mcp.rs`** — [Model Context Protocol](https://modelcontextprotocol.io) *client*. Two
|
|
123
|
+
transports: **Streamable HTTP** (one JSON-RPC POST endpoint, `url` in `mcp.toml`; replies are
|
|
124
|
+
`application/json` or SSE) and **stdio** (`command` + optional `args`/`[server.env]` in
|
|
125
|
+
`mcp.toml`; sigit spawns the server and speaks newline-delimited JSON-RPC over its
|
|
126
|
+
stdin/stdout, stderr inherited into sigit's log). `url` and `command` are mutually exclusive —
|
|
127
|
+
both or neither is a config error, logged and skipped. Both transports run the same
|
|
128
|
+
`initialize`/`tools/list` handshake and forward `tools/call`. Discovery is best-effort at
|
|
129
|
+
startup (`mcp::init`, called from both branches of `main()`) and cached in a process-global so
|
|
130
|
+
the synchronous spec builders (`mcp::tool_specs`) and the async dispatch (`mcp::call_tool`) can
|
|
131
|
+
both read it; `/reload` does *not* re-run it, so config changes need a restart. stdio children
|
|
132
|
+
live for the process; a dead child fails calls with an in-band error string (no auto-restart).
|
|
133
|
+
Tools are namespaced `mcp__<server>__<tool>`, appended in the `*_as_specs`/`build_tool_specs`
|
|
134
|
+
layer and routed in `tools::execute_tool` via `mcp::is_mcp_tool`. The official server
|
|
135
|
+
(`<cloud>/mcp`, default `https://sigit.si/api/v1/mcp`) is baked in (always HTTP) and authed
|
|
136
|
+
with the cloud session token; extra servers live in `mcp.toml` (global
|
|
137
|
+
`$SIGIT_CONFIG_DIR/mcp.toml` and project-local `.sigit/mcp.toml`). The stdio path is covered by
|
|
138
|
+
`tests/mcp_stdio.rs`, driven by the test-only `src/bin/mcp_stdio_stub.rs` helper binary
|
|
139
|
+
(excluded from the published crate via `exclude` in `Cargo.toml`).
|
|
140
|
+
- **`src/permissions.rs`** — tool permission policy. Every tool call passes through
|
|
141
|
+
`decision_for` before executing: read-only tools always run; mutating tools (and all
|
|
142
|
+
`mcp__*`/unknown tools) are governed by, in order: per-session plan mode (`/plan` — deny all
|
|
143
|
+
mutating tools with a present-a-plan message), session "always allow" grants, per-tool
|
|
144
|
+
overrides and the default mode from `[permissions]` in `settings.toml` (`allow`/`ask`/`deny`,
|
|
145
|
+
default `ask`; `SIGIT_PERMISSIONS` env overrides the default). On `ask`, the ACP path sends
|
|
146
|
+
`session/request_permission` (allow once / allow for session / deny) and the TUI pauses the
|
|
147
|
+
inference task on a y/a/n prompt. Note: ACP turn-affecting handlers run in `cx.spawn`ed tasks
|
|
148
|
+
serialized by `SiGitAgent::turn_lock` so the dispatch loop can route the client's permission
|
|
149
|
+
answer mid-turn — don't move them back inline, and don't await client requests from inline
|
|
150
|
+
handlers (deadlock).
|
|
151
|
+
- **`src/instructions.rs`** — project instruction files, the always-on counterpart to skills.
|
|
152
|
+
Reads `AGENTS.md` (the cross-tool [agents.md](https://agents.md) standard) and `CLAUDE.md`,
|
|
153
|
+
walking from the session cwd up to the repo root (nearest ancestor with `.git`, never above it),
|
|
154
|
+
plus a global file under `$SIGIT_CONFIG_DIR`. Files are ordered outermost-first so the deepest
|
|
155
|
+
(most specific) wins. The combined block is injected via `session_context_message` in `main.rs`
|
|
156
|
+
— pushed as a system message at every ACP session entry point (new/load/fork + model switch)
|
|
157
|
+
and appended to the system prompt on the cloud and TUI-startup paths.
|
|
158
|
+
- **`src/chat.rs`** — the Unix-only ratatui TUI. Loading-spinner phase then chat; uses
|
|
159
|
+
`tokio::select!` to multiplex terminal events with streaming tokens.
|
|
160
|
+
- **`src/setup.rs`** — model cache location, local model discovery, selected-model persistence.
|
|
161
|
+
Must run (`setup_shared_model_cache`) *before* anything touches `ChatEngine`/`hf-hub`, since
|
|
162
|
+
those read env vars once at init.
|
|
163
|
+
- **`src/account.rs`** — siGit Code Cloud auth (`/login`, `/logout`, `/whoami`); authenticates
|
|
164
|
+
against the account API and stores a session token. Performs no console I/O.
|
|
165
|
+
- **`src/credentials.rs`** — local session-token store (TOML, `0600` on Unix).
|
|
166
|
+
- **`src/models.rs`** — model-picker types shared across platforms.
|
|
167
|
+
|
|
168
|
+
Slash commands (`/help`, `/models`, `/skills`, `/mcp`, `/login`, `/logout`, `/whoami`, `/reload`,
|
|
169
|
+
`/plan`, `/permissions`, `/init`, `/clear`, `/status`) are advertised via `advertise_commands` in
|
|
170
|
+
`main.rs` and handled in both the TUI and ACP sessions. `/init` is special: instead of replying
|
|
171
|
+
directly it substitutes `instructions::INIT_PROMPT` for the user text and runs a normal agent
|
|
172
|
+
turn that explores the repo and writes (or improves) `AGENTS.md` through the ordinary tools and
|
|
173
|
+
permission checks.
|
|
174
|
+
|
|
175
|
+
## Model cache (macOS)
|
|
176
|
+
|
|
177
|
+
On macOS the HF model cache lives in an App Group container shared with the siGit desktop app:
|
|
178
|
+
`~/Library/Group Containers/group.com.ondeinference.apps/models/`. Other platforms fall back to
|
|
179
|
+
`~/.cache/huggingface/`. The CLI reuses a model the desktop app already downloaded. First run
|
|
180
|
+
downloads a GGUF model (~1–2 GB) from Hugging Face.
|
|
181
|
+
|
|
182
|
+
## Logging
|
|
183
|
+
|
|
184
|
+
In TTY (interactive) mode, *all* output — `log`, `tracing`, stray `println!` — is redirected to
|
|
185
|
+
`$TMPDIR/sigit.log` so the ratatui surface stays clean; the TUI holds a separate fd to the real
|
|
186
|
+
terminal. In ACP mode, stdout is reserved for protocol JSON and logs go to stderr. Control
|
|
187
|
+
verbosity with `RUST_LOG`.
|
|
188
|
+
|
|
189
|
+
## Relevant env vars
|
|
190
|
+
|
|
191
|
+
`OPENAI_BASE_URL` / `OPENAI_API_KEY` (provider override), `SIGIT_API_URL` (account API base,
|
|
192
|
+
default `https://sigit.si`), `SIGIT_CLOUD_URL`, `SIGIT_CONFIG_DIR` (default `~/.config/sigit`),
|
|
193
|
+
`SIGIT_MODEL`, `SIGIT_MCP` (`off` disables MCP), `SIGIT_MCP_OFFICIAL` (`off` drops the baked-in
|
|
194
|
+
server), `SIGIT_PERMISSIONS` (`allow`/`ask`/`deny` — overrides the default permission mode for
|
|
195
|
+
mutating tools; the escape hatch for clients without permission-request support),
|
|
196
|
+
`HF_HOME` / `HF_HUB_CACHE`, `RUST_LOG`.
|
|
197
|
+
|
|
198
|
+
## Releasing
|
|
199
|
+
|
|
200
|
+
Version lives in `Cargo.toml`. The binary is published to five registries via separate workflows
|
|
201
|
+
(`release-crates`, `release-github`, `release-homebrew`, `release-npm`, `release-pypi`); the
|
|
202
|
+
`npm/` and `pypi/` dirs hold the wrapper-package templates. Update `CHANGELOG.md` for releases.
|