@hej / sigit / commits / cd75bec

Add multi-platform release workflows for GitHub, NPM, and PyPI

- Replace single release.yml with platform-specific workflows: - release-github.yml for GitHub Releases and Homebrew tap updates - release-npm.yml for publishing binaries and base package to NPM - release-pypi.yml for building and publishing wheels/sdist to PyPI - Add Homebrew tap update automation - Add NPM packaging scripts, templates, and TypeScript base package - Add PyPI packaging with maturin and metadata - Add .nvmrc and rust-toolchain.toml for consistent builds - Update Cargo.toml with repository, homepage, keywords, categories, and authors

Seto Elkahfi committed Apr 24, 2026 at 00:57 UTC cd75bec906625ae4cac5c441a107846bfb360952
20 files changed +1221 -171
.github/workflows/release-github.yml new
+187
@@ -0,0 +1,187 @@
1 +name: GitHub Release
2 +
3 +on:
4 + push:
5 + tags:
6 + - "v*.*.*"
7 + workflow_dispatch:
8 + inputs:
9 + tag:
10 + description: "Release tag (e.g. v0.1.1)"
11 + required: true
12 +
13 +permissions:
14 + contents: write
15 + actions: write
16 +
17 +env:
18 + PROJECT_NAME: sigit
19 + CARGO_TERM_COLOR: always
20 +
21 +jobs:
22 + build:
23 + name: Build binary (${{ matrix.name }})
24 + runs-on: ${{ matrix.runner }}
25 +
26 + strategy:
27 + fail-fast: false
28 + matrix:
29 + include:
30 + - name: linux-amd64
31 + runner: ubuntu-latest
32 + target: x86_64-unknown-linux-gnu
33 + - name: linux-arm64
34 + runner: ubuntu-24.04-arm
35 + target: aarch64-unknown-linux-gnu
36 + - name: win-amd64
37 + runner: windows-latest
38 + target: x86_64-pc-windows-msvc
39 + - name: win-arm64
40 + runner: windows-latest
41 + target: aarch64-pc-windows-msvc
42 + - name: macos-amd64
43 + runner: macos-15-intel
44 + target: x86_64-apple-darwin
45 + - name: macos-arm64
46 + runner: macos-latest
47 + target: aarch64-apple-darwin
48 +
49 + steps:
50 + - name: Checkout
51 + uses: actions/checkout@v6
52 + with:
53 + ref: ${{ github.event.inputs.tag || github.ref }}
54 +
55 + - name: Set the release version
56 + shell: bash
57 + run: |
58 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
59 + release_version="${GITHUB_REF_NAME#v}"
60 + else
61 + release_version="${{ github.event.inputs.tag }}"
62 + release_version="${release_version#v}"
63 + fi
64 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
65 +
66 + - name: Read Rust toolchain
67 + shell: bash
68 + run: |
69 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
70 + if [ -z "$rust_toolchain" ]; then
71 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
72 + exit 1
73 + fi
74 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
75 +
76 + - name: Install Rust toolchain
77 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
78 + with:
79 + toolchain: ${{ env.RUST_TOOLCHAIN }}
80 + targets: ${{ matrix.target }}
81 +
82 + - name: Setup Rust cache
83 + uses: Swatinem/rust-cache@v2
84 + with:
85 + key: github-${{ matrix.target }}
86 +
87 + - name: Build binary
88 + shell: bash
89 + run: cargo build --locked --release --target ${{ matrix.target }}
90 +
91 + - name: Package binary
92 + shell: bash
93 + run: |
94 + BIN_SUFFIX=""
95 + if [[ "${{ matrix.runner }}" == "windows-latest" ]]; then
96 + BIN_SUFFIX=".exe"
97 + fi
98 +
99 + BIN_OUTPUT="target/${{ matrix.target }}/release/${PROJECT_NAME}${BIN_SUFFIX}"
100 + BIN_RELEASE="${PROJECT_NAME}-${{ matrix.name }}${BIN_SUFFIX}"
101 +
102 + mkdir -p ./release
103 + mv "${BIN_OUTPUT}" "./release/${BIN_RELEASE}"
104 +
105 + - name: Package macOS tarball for Homebrew
106 + if: contains(matrix.target, 'apple-darwin')
107 + shell: bash
108 + run: |
109 + ARCHIVE_NAME="${PROJECT_NAME}-${{ matrix.name }}.tar.gz"
110 +
111 + mkdir -p staging-brew
112 + cp "./release/${PROJECT_NAME}-${{ matrix.name }}" "staging-brew/${PROJECT_NAME}"
113 + strip "staging-brew/${PROJECT_NAME}"
114 +
115 + tar -C staging-brew -czf "${ARCHIVE_NAME}" "${PROJECT_NAME}"
116 +
117 + shasum -a 256 "${ARCHIVE_NAME}" | awk '{print $1}' > "${ARCHIVE_NAME}.sha256"
118 +
119 + echo "Archive: ${ARCHIVE_NAME}"
120 + echo "SHA256: $(cat "${ARCHIVE_NAME}.sha256")"
121 +
122 + - name: Upload binary artifact
123 + uses: actions/upload-artifact@v4
124 + with:
125 + name: binary-${{ matrix.name }}
126 + path: release/*
127 +
128 + - name: Upload macOS Homebrew artifacts
129 + if: contains(matrix.target, 'apple-darwin')
130 + uses: actions/upload-artifact@v4
131 + with:
132 + name: homebrew-${{ matrix.name }}
133 + path: |
134 + ${{ env.PROJECT_NAME }}-${{ matrix.name }}.tar.gz
135 + ${{ env.PROJECT_NAME }}-${{ matrix.name }}.tar.gz.sha256
136 +
137 + release:
138 + name: Create GitHub Release
139 + needs: build
140 + runs-on: ubuntu-latest
141 + if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch'
142 +
143 + steps:
144 + - name: Resolve tag
145 + id: tag
146 + shell: bash
147 + run: |
148 + if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
149 + echo "tag=${{ github.event.inputs.tag }}" >> "$GITHUB_OUTPUT"
150 + else
151 + echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
152 + fi
153 +
154 + - name: Download binary artifacts
155 + uses: actions/download-artifact@v4
156 + with:
157 + pattern: "binary-*"
158 + path: release
159 + merge-multiple: true
160 +
161 + - name: Download Homebrew artifacts
162 + uses: actions/download-artifact@v4
163 + with:
164 + pattern: "homebrew-*"
165 + path: release
166 + merge-multiple: true
167 +
168 + - name: Release
169 + uses: softprops/action-gh-release@v2
170 + with:
171 + tag_name: ${{ steps.tag.outputs.tag }}
172 + files: release/*
173 +
174 + - name: Trigger Homebrew release
175 + uses: actions/github-script@v7
176 + with:
177 + script: |
178 + await github.rest.actions.createWorkflowDispatch({
179 + owner: context.repo.owner,
180 + repo: context.repo.repo,
181 + workflow_id: 'release-homebrew.yml',
182 + ref: 'main',
183 + inputs: {
184 + tag: '${{ steps.tag.outputs.tag }}'
185 + }
186 + })
187 + console.log('Dispatched release-homebrew.yml for tag ${{ steps.tag.outputs.tag }}')
.github/workflows/release-homebrew.yml new
+116
@@ -0,0 +1,116 @@
1 +name: Homebrew CLI Release
2 +
3 +on:
4 + workflow_dispatch:
5 + inputs:
6 + tag:
7 + description: "Release tag (e.g. v0.1.1)"
8 + required: true
9 +
10 +permissions:
11 + contents: read
12 +
13 +env:
14 + REPO: getsigit/sigit
15 +
16 +jobs:
17 + update-homebrew-tap:
18 + name: Update Homebrew tap
19 + runs-on: ubuntu-latest
20 +
21 + steps:
22 + - name: Resolve tag and version
23 + id: release
24 + shell: bash
25 + run: |
26 + TAG="${{ github.event.inputs.tag }}"
27 + VERSION="${TAG#v}"
28 +
29 + echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
30 + echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
31 +
32 + - name: Read SHA256 checksums from release
33 + id: sha
34 + env:
35 + GH_TOKEN: ${{ github.token }}
36 + shell: bash
37 + run: |
38 + mkdir -p artifacts
39 +
40 + gh release download "${{ steps.release.outputs.tag }}" \
41 + --repo "${{ env.REPO }}" \
42 + --pattern "sigit-macos-*.tar.gz.sha256" \
43 + --dir artifacts/
44 +
45 + ARM64_SHA=$(cat artifacts/sigit-macos-arm64.tar.gz.sha256)
46 + AMD64_SHA=$(cat artifacts/sigit-macos-amd64.tar.gz.sha256)
47 +
48 + echo "arm64=${ARM64_SHA}" >> "$GITHUB_OUTPUT"
49 + echo "amd64=${AMD64_SHA}" >> "$GITHUB_OUTPUT"
50 +
51 + echo "ARM64 SHA256: ${ARM64_SHA}"
52 + echo "AMD64 SHA256: ${AMD64_SHA}"
53 +
54 + - name: Checkout Homebrew tap
55 + uses: actions/checkout@v6
56 + with:
57 + repository: getsigit/sigit-homebrew-tap
58 + token: ${{ secrets.HOMEBREW_TAP_TOKEN }}
59 + path: homebrew-tap
60 +
61 + - name: Generate formula
62 + shell: bash
63 + run: |
64 + VERSION="${{ steps.release.outputs.version }}"
65 + TAG="${{ steps.release.outputs.tag }}"
66 + ARM64_SHA="${{ steps.sha.outputs.arm64 }}"
67 + AMD64_SHA="${{ steps.sha.outputs.amd64 }}"
68 +
69 + mkdir -p homebrew-tap/Formula
70 +
71 + cat > homebrew-tap/Formula/sigit.rb <<FORMULA
72 + # frozen_string_literal: true
73 +
74 + # Homebrew formula for siGit Code (\`sigit\` binary).
75 + class Sigit < Formula
76 + desc 'AI coding agent powered by local LLM via Onde Inference'
77 + homepage 'https://github.com/getsigit/sigit'
78 + version '${VERSION}'
79 + license 'Apache-2.0'
80 +
81 + on_macos do
82 + on_arm do
83 + url 'https://github.com/${REPO}/releases/download/${TAG}/sigit-macos-arm64.tar.gz'
84 + sha256 '${ARM64_SHA}'
85 + end
86 + on_intel do
87 + url 'https://github.com/${REPO}/releases/download/${TAG}/sigit-macos-amd64.tar.gz'
88 + sha256 '${AMD64_SHA}'
89 + end
90 + end
91 +
92 + def install
93 + bin.install 'sigit'
94 + end
95 +
96 + test do
97 + assert_match version.to_s, shell_output("#{bin}/sigit --version", 1)
98 + end
99 + end
100 + FORMULA
101 +
102 + echo "Generated formula:"
103 + cat homebrew-tap/Formula/sigit.rb
104 +
105 + - name: Commit and push
106 + shell: bash
107 + run: |
108 + VERSION="${{ steps.release.outputs.version }}"
109 +
110 + cd homebrew-tap
111 + git config user.name "github-actions[bot]"
112 + git config user.email "github-actions[bot]@users.noreply.github.com"
113 + git add Formula/sigit.rb
114 + git diff --cached --quiet && echo "No changes to commit" && exit 0
115 + git commit -m "Update sigit to ${VERSION}"
116 + git push
.github/workflows/release-npm.yml new
+220
@@ -0,0 +1,220 @@
1 +name: NPM Release
2 +
3 +on:
4 + push:
5 + tags:
6 + - "v*.*.*"
7 + workflow_dispatch:
8 + inputs:
9 + tag:
10 + description: "Release tag (e.g. v0.1.1)"
11 + required: true
12 +
13 +permissions:
14 + id-token: write
15 + contents: read
16 +
17 +env:
18 + CARGO_TERM_COLOR: always
19 +
20 +jobs:
21 + publish-npm-binaries:
22 + name: Publish NPM platform packages
23 + runs-on: ${{ matrix.build.OS }}
24 + strategy:
25 + fail-fast: false
26 + matrix:
27 + build:
28 + - {
29 + NAME: linux-x64-glibc,
30 + OS: ubuntu-latest,
31 + TARGET: x86_64-unknown-linux-gnu,
32 + }
33 + - {
34 + NAME: linux-arm64-glibc,
35 + OS: ubuntu-24.04-arm,
36 + TARGET: aarch64-unknown-linux-gnu,
37 + }
38 + - {
39 + NAME: win32-x64-msvc,
40 + OS: windows-2022,
41 + TARGET: x86_64-pc-windows-msvc,
42 + }
43 + - {
44 + NAME: win32-arm64-msvc,
45 + OS: windows-2022,
46 + TARGET: aarch64-pc-windows-msvc,
47 + }
48 + - {
49 + NAME: darwin-x64,
50 + OS: macos-15-intel,
51 + TARGET: x86_64-apple-darwin,
52 + }
53 + - {
54 + NAME: darwin-arm64,
55 + OS: macos-latest,
56 + TARGET: aarch64-apple-darwin,
57 + }
58 +
59 + steps:
60 + - name: Checkout
61 + uses: actions/checkout@v6
62 + with:
63 + ref: ${{ github.event.inputs.tag || github.ref }}
64 +
65 + - name: Set the release version
66 + shell: bash
67 + run: |
68 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
69 + release_version="${GITHUB_REF_NAME#v}"
70 + else
71 + release_version="${{ github.event.inputs.tag }}"
72 + release_version="${release_version#v}"
73 + fi
74 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
75 +
76 + - name: Read Rust toolchain
77 + shell: bash
78 + run: |
79 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
80 + if [ -z "$rust_toolchain" ]; then
81 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
82 + exit 1
83 + fi
84 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
85 +
86 + - name: Install Rust toolchain
87 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
88 + with:
89 + toolchain: ${{ env.RUST_TOOLCHAIN }}
90 +
91 + - name: Install Rust target
92 + shell: bash
93 + run: |
94 + rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
95 + rustup target list --installed
96 +
97 + - name: Setup Rust cache
98 + uses: Swatinem/rust-cache@v2
99 + with:
100 + key: npm-${{ matrix.build.TARGET }}
101 +
102 + - name: Build binary
103 + shell: bash
104 + run: cargo build --locked --release --target ${{ matrix.build.TARGET }}
105 +
106 + - name: Install Node
107 + uses: actions/setup-node@v6
108 + with:
109 + node-version-file: .nvmrc
110 + registry-url: "https://registry.npmjs.org"
111 +
112 + - name: Publish platform package to NPM
113 + env:
114 + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
115 + shell: bash
116 + run: |
117 + cd npm
118 +
119 + # Binary name from Cargo.toml
120 + cargo_bin="sigit"
121 +
122 + # Prefix used for optional dependency package names
123 + node_pkg_prefix="sigit"
124 +
125 + # Derive OS and architecture from the build matrix name
126 + # Matrix name format: <os>-<arch>[-<extra>]
127 + node_os=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f1)
128 + export node_os
129 + node_arch=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f2)
130 + export node_arch
131 +
132 + # Set the version
133 + export node_version="${{ env.RELEASE_VERSION }}"
134 +
135 + # Build the platform package name; normalise win32 → windows
136 + if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
137 + export node_pkg="${node_pkg_prefix}-windows-${node_arch}"
138 + else
139 + export node_pkg="${node_pkg_prefix}-${node_os}-${node_arch}"
140 + fi
141 +
142 + # Create the package directory
143 + mkdir -p "${node_pkg}/bin"
144 +
145 + # Generate package.json + README for this platform slice
146 + node ./scripts/render-platform-package.cjs \
147 + "${node_pkg}" \
148 + "${node_version}" \
149 + "${node_os}" \
150 + "${node_arch}"
151 +
152 + # Windows binaries carry a .exe extension
153 + if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
154 + cargo_bin="${cargo_bin}.exe"
155 + fi
156 +
157 + cp "../target/${{ matrix.build.TARGET }}/release/${cargo_bin}" "${node_pkg}/bin"
158 +
159 + cd "${node_pkg}"
160 +
161 + npm_package_name="@smbcloud/${node_pkg}"
162 + if npm view "${npm_package_name}@${node_version}" version >/dev/null 2>&1; then
163 + echo "${npm_package_name}@${node_version} already exists on npm, skipping publish"
164 + exit 0
165 + fi
166 +
167 + npm publish --access public --provenance
168 +
169 + publish-npm-base:
170 + name: Publish base NPM package (@smbcloud/sigit)
171 + needs: publish-npm-binaries
172 + runs-on: ubuntu-latest
173 +
174 + steps:
175 + - name: Checkout
176 + uses: actions/checkout@v6
177 + with:
178 + ref: ${{ github.event.inputs.tag || github.ref }}
179 +
180 + - name: Set the release version
181 + shell: bash
182 + run: |
183 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
184 + release_version="${GITHUB_REF_NAME#v}"
185 + else
186 + release_version="${{ github.event.inputs.tag }}"
187 + release_version="${release_version#v}"
188 + fi
189 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
190 +
191 + - name: Install Node
192 + uses: actions/setup-node@v6
193 + with:
194 + node-version-file: .nvmrc
195 + registry-url: "https://registry.npmjs.org"
196 +
197 + - name: Publish base package to NPM
198 + env:
199 + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
200 + shell: bash
201 + run: |
202 + cd npm/sigit
203 +
204 + # Rewrite package.json with the correct release version and
205 + # matching optionalDependency versions
206 + node ../scripts/render-main-package.cjs \
207 + "./package.json" \
208 + "${{ env.RELEASE_VERSION }}"
209 +
210 + npm_package_name="@smbcloud/sigit"
211 + npm_package_version="${{ env.RELEASE_VERSION }}"
212 +
213 + if npm view "${npm_package_name}@${npm_package_version}" version >/dev/null 2>&1; then
214 + echo "${npm_package_name}@${npm_package_version} already exists on npm, skipping publish"
215 + exit 0
216 + fi
217 +
218 + npm install
219 + npm run build
220 + npm publish --access public --provenance
.github/workflows/release-pypi.yml new
+191
@@ -0,0 +1,191 @@
1 +name: PyPI Release
2 +
3 +on:
4 + push:
5 + tags:
6 + - "v*.*.*"
7 + workflow_dispatch:
8 + inputs:
9 + tag:
10 + description: "Release tag (e.g. v0.1.1)"
11 + required: true
12 +
13 +permissions:
14 + id-token: write
15 + contents: read
16 +
17 +env:
18 + CARGO_TERM_COLOR: always
19 +
20 +jobs:
21 + build-wheels:
22 + name: Build PyPI wheels
23 + runs-on: ${{ matrix.build.OS }}
24 + strategy:
25 + fail-fast: false
26 + matrix:
27 + build:
28 + - {
29 + NAME: linux-x64-glibc,
30 + OS: ubuntu-latest,
31 + TARGET: x86_64-unknown-linux-gnu,
32 + MANYLINUX: "2014",
33 + }
34 + - {
35 + NAME: linux-arm64-glibc,
36 + OS: ubuntu-24.04-arm,
37 + TARGET: aarch64-unknown-linux-gnu,
38 + MANYLINUX: "2014",
39 + }
40 + - {
41 + NAME: win32-x64-msvc,
42 + OS: windows-2022,
43 + TARGET: x86_64-pc-windows-msvc,
44 + }
45 + - {
46 + NAME: win32-arm64-msvc,
47 + OS: windows-2022,
48 + TARGET: aarch64-pc-windows-msvc,
49 + }
50 + - { NAME: darwin-x64, OS: macos-latest, TARGET: x86_64-apple-darwin }
51 + - {
52 + NAME: darwin-arm64,
53 + OS: macos-latest,
54 + TARGET: aarch64-apple-darwin,
55 + }
56 + steps:
57 + - name: Checkout
58 + uses: actions/checkout@v6
59 + with:
60 + ref: ${{ github.event.inputs.tag || github.ref }}
61 +
62 + - name: Set the release version
63 + shell: bash
64 + run: |
65 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
66 + release_version="${GITHUB_REF_NAME#v}"
67 + else
68 + release_version="${{ github.event.inputs.tag }}"
69 + release_version="${release_version#v}"
70 + fi
71 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
72 +
73 + - name: Read Rust toolchain
74 + shell: bash
75 + run: |
76 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
77 + if [ -z "$rust_toolchain" ]; then
78 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
79 + exit 1
80 + fi
81 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
82 +
83 + - name: Install Rust toolchain
84 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
85 + with:
86 + toolchain: ${{ env.RUST_TOOLCHAIN }}
87 +
88 + - name: Install Rust target
89 + shell: bash
90 + run: |
91 + rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
92 + rustup target list --installed
93 +
94 + - name: Build wheel
95 + uses: PyO3/maturin-action@v1
96 + with:
97 + target: ${{ matrix.build.TARGET }}
98 + manylinux: ${{ matrix.build.MANYLINUX || 'off' }}
99 + working-directory: pypi
100 + args: --release --locked --compatibility pypi --out dist
101 + before-script-linux: yum install -y perl-core
102 +
103 + - name: Upload wheel artifact
104 + uses: actions/upload-artifact@v4
105 + with:
106 + name: wheels-${{ matrix.build.NAME }}
107 + path: pypi/dist/*
108 +
109 + build-sdist:
110 + name: Build source distribution
111 + runs-on: ubuntu-latest
112 + steps:
113 + - name: Checkout
114 + uses: actions/checkout@v6
115 + with:
116 + ref: ${{ github.event.inputs.tag || github.ref }}
117 +
118 + - name: Read Rust toolchain
119 + shell: bash
120 + run: |
121 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
122 + if [ -z "$rust_toolchain" ]; then
123 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
124 + exit 1
125 + fi
126 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
127 +
128 + - name: Install Rust toolchain
129 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
130 + with:
131 + toolchain: ${{ env.RUST_TOOLCHAIN }}
132 +
133 + - name: Build sdist
134 + uses: PyO3/maturin-action@v1
135 + with:
136 + command: sdist
137 + working-directory: pypi
138 + args: --out dist
139 +
140 + - name: Upload sdist artifact
141 + uses: actions/upload-artifact@v4
142 + with:
143 + name: sdist
144 + path: pypi/dist/*
145 +
146 + publish-pypi:
147 + name: Publish to PyPI
148 + runs-on: ubuntu-latest
149 + needs:
150 + - build-wheels
151 + - build-sdist
152 + steps:
153 + - name: Checkout
154 + uses: actions/checkout@v6
155 + with:
156 + ref: ${{ github.event.inputs.tag || github.ref }}
157 +
158 + - name: Set the release version
159 + shell: bash
160 + run: |
161 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
162 + release_version="${GITHUB_REF_NAME#v}"
163 + else
164 + release_version="${{ github.event.inputs.tag }}"
165 + release_version="${release_version#v}"
166 + fi
167 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
168 +
169 + - name: Download distribution artifacts
170 + uses: actions/download-artifact@v4
171 + with:
172 + pattern: "*"
173 + path: dist
174 + merge-multiple: true
175 +
176 + - name: Check whether release already exists on PyPI
177 + id: pypi-check
178 + shell: bash
179 + run: |
180 + if curl -fsS "https://pypi.org/pypi/sigit-code/${RELEASE_VERSION}/json" >/dev/null 2>&1; then
181 + echo "sigit-code ${RELEASE_VERSION} already exists on PyPI, skipping publish"
182 + echo "exists=true" >> "$GITHUB_OUTPUT"
183 + else
184 + echo "exists=false" >> "$GITHUB_OUTPUT"
185 + fi
186 +
187 + - name: Publish distribution
188 + if: steps.pypi-check.outputs.exists != 'true'
189 + uses: pypa/gh-action-pypi-publish@release/v1
190 + with:
191 + skip-existing: true
.github/workflows/release.yml deleted
-171
@@ -1,171 +0,0 @@
1 -name: Release
2 -
3 -on:
4 - push:
5 - tags:
6 - - "v*.*.*"
7 - workflow_dispatch:
8 - inputs:
9 - tag:
10 - description: "Release tag (e.g. v0.1.0)"
11 - required: true
12 -
13 -permissions:
14 - contents: write
15 -
16 -env:
17 - CARGO_TERM_COLOR: always
18 -
19 -jobs:
20 - build:
21 - name: Build ${{ matrix.artifact }}
22 - runs-on: ${{ matrix.os }}
23 - strategy:
24 - fail-fast: false
25 - matrix:
26 - include:
27 - - target: aarch64-apple-darwin
28 - os: macos-26
29 - artifact: sigit-darwin-aarch64
30 - binary: sigit
31 - archive_ext: tar.gz
32 -
33 - - target: x86_64-apple-darwin
34 - os: macos-26-intel
35 - artifact: sigit-darwin-x86_64
36 - binary: sigit
37 - archive_ext: tar.gz
38 -
39 - steps:
40 - - name: Checkout
41 - uses: actions/checkout@v6
42 - with:
43 - ref: ${{ github.event.inputs.tag || github.ref }}
44 -
45 - - name: Set release version
46 - shell: bash
47 - run: |
48 - if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
49 - release_version="${GITHUB_REF_NAME#v}"
50 - else
51 - release_version="${{ github.event.inputs.tag }}"
52 - release_version="${release_version#v}"
53 - fi
54 -
55 - echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
56 -
57 - - name: Verify Cargo.toml version matches tag
58 - shell: bash
59 - run: |
60 - CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 \
61 - | jq -r '.packages[] | select(.name == "sigit") | .version')
62 -
63 - echo "Cargo.toml version : ${CARGO_VERSION}"
64 - echo "Release tag version: ${RELEASE_VERSION}"
65 -
66 - if [[ "${CARGO_VERSION}" != "${RELEASE_VERSION}" ]]; then
67 - echo "::error::Version mismatch — bump Cargo.toml version before tagging."
68 - exit 1
69 - fi
70 -
71 - - name: Install Rust toolchain
72 - uses: dtolnay/rust-toolchain@stable
73 - with:
74 - targets: ${{ matrix.target }}
75 -
76 - - name: Setup Rust cache
77 - uses: Swatinem/rust-cache@v2
78 - with:
79 - key: release-${{ matrix.target }}
80 -
81 - - name: Build
82 - shell: bash
83 - run: cargo build --release --locked --target ${{ matrix.target }}
84 -
85 - - name: Package (tar.gz)
86 - if: matrix.archive_ext == 'tar.gz'
87 - shell: bash
88 - run: |
89 - binary="target/${{ matrix.target }}/release/${{ matrix.binary }}"
90 - archive="${{ matrix.artifact }}.tar.gz"
91 -
92 - tar -czf "${archive}" -C "$(dirname "${binary}")" "${{ matrix.binary }}"
93 -
94 - echo "ARCHIVE=${archive}" >> "$GITHUB_ENV"
95 -
96 - - name: Package (zip)
97 - if: matrix.archive_ext == 'zip'
98 - shell: pwsh
99 - run: |
100 - $binary = "target\${{ matrix.target }}\release\${{ matrix.binary }}"
101 - $archive = "${{ matrix.artifact }}.zip"
102 -
103 - Compress-Archive -Path $binary -DestinationPath $archive
104 -
105 - "ARCHIVE=$archive" | Out-File -FilePath $env:GITHUB_ENV -Append
106 -
107 - - name: Upload archive
108 - uses: actions/upload-artifact@v4
109 - with:
110 - name: ${{ matrix.artifact }}
111 - path: ${{ env.ARCHIVE }}
112 - if-no-files-found: error
113 - retention-days: 1
114 -
115 - release:
116 - name: Publish GitHub Release
117 - needs: build
118 - runs-on: ubuntu-latest
119 - permissions:
120 - contents: write
121 -
122 - steps:
123 - - name: Checkout
124 - uses: actions/checkout@v6
125 - with:
126 - ref: ${{ github.event.inputs.tag || github.ref }}
127 -
128 - - name: Set release version and tag
129 - shell: bash
130 - run: |
131 - if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
132 - release_tag="${GITHUB_REF_NAME}"
133 - release_version="${GITHUB_REF_NAME#v}"
134 - else
135 - release_tag="${{ github.event.inputs.tag }}"
136 - release_version="${{ github.event.inputs.tag }}"
137 - release_version="${release_version#v}"
138 - fi
139 -
140 - echo "RELEASE_TAG=${release_tag}" >> "$GITHUB_ENV"
141 - echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
142 -
143 - - name: Download all archives
144 - uses: actions/download-artifact@v4
145 - with:
146 - path: archives
147 - merge-multiple: true
148 -
149 - - name: Check whether release already exists
150 - id: release-check
151 - shell: bash
152 - run: |
153 - if gh release view "${RELEASE_TAG}" --repo "${{ github.repository }}" >/dev/null 2>&1; then
154 - echo "Release ${RELEASE_TAG} already exists — skipping."
155 - echo "exists=true" >> "$GITHUB_OUTPUT"
156 - else
157 - echo "exists=false" >> "$GITHUB_OUTPUT"
158 - fi
159 - env:
160 - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
161 -
162 - - name: Create release and upload archives
163 - if: steps.release-check.outputs.exists != 'true'
164 - shell: bash
165 - run: |
166 - gh release create "${RELEASE_TAG}" \
167 - --title "siGit ${RELEASE_TAG}" \
168 - --generate-notes \
169 - archives/*
170 - env:
171 - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
.nvmrc new
+1
@@ -0,0 +1 @@
1 +20
Cargo.toml
+6
@@ -5,6 +5,12 @@ edition = "2024"
5 description = "siGit Code — ACP-compatible AI coding agent for smbCloud platform."
6 documentation = "https://github.com/getsigit/sigit"
7 license = "Apache-2.0"
8 +repository = "https://github.com/getsigit/sigit"
9 +homepage = "https://smbcloud.xyz"
10 +readme = "README.md"
11 +keywords = ["sigit", "cli", "ai", "coding-agent", "llm"]
12 +categories = ["command-line-utilities"]
13 +authors = ["Seto Elkahfi <hej@setoelkahfi.se>"]
14
15 [[bin]]
16 name = "sigit"
npm/README.md.tmpl new
+22
@@ -0,0 +1,22 @@
1 +<h1 align="center">siGit Code</h1>
2 +
3 +## `${node_pkg}`
4 +
5 +This is a platform-specific binary for [`@smbcloud/sigit`](https://www.npmjs.com/package/@smbcloud/sigit). You don't need to install it directly.
6 +
7 +Install the main package instead:
8 +
9 +```sh
10 +npm install -g @smbcloud/sigit
11 +```
12 +
13 +npm pulls in the right binary for your OS and architecture.
14 +
15 +## Links
16 +
17 +- [Source code](https://github.com/getsigit/sigit)
18 +- [Issues](https://github.com/getsigit/sigit/issues)
19 +
20 +## License
21 +
22 +[Apache-2.0](https://github.com/getsigit/sigit/blob/main/LICENSE)
npm/package-main.json.tmpl new
+41
@@ -0,0 +1,41 @@
1 +{
2 + "name": "@smbcloud/sigit",
3 + "version": "${release_version}",
4 + "keywords": [
5 + "sigit",
6 + "cli",
7 + "ai",
8 + "coding-agent",
9 + "llm",
10 + "on-device",
11 + "smbcloud",
12 + "acp"
13 + ],
14 + "bin": {
15 + "sigit": "lib/index.js"
16 + },
17 + "files": ["lib", "README.md"],
18 + "description": "AI coding agent powered by local LLM via Onde Inference.",
19 + "license": "Apache-2.0",
20 + "repository": {
21 + "type": "git",
22 + "url": "git+https://github.com/getsigit/sigit.git"
23 + },
24 + "scripts": {
25 + "typecheck": "tsc --noEmit",
26 + "build": "tsc",
27 + "dev": "npm run build && node lib/index.js"
28 + },
29 + "devDependencies": {
30 + "@types/node": "^18.15.11",
31 + "typescript": "^5.0.0"
32 + },
33 + "optionalDependencies": {
34 + "@smbcloud/sigit-darwin-arm64": "${release_version}",
35 + "@smbcloud/sigit-darwin-x64": "${release_version}",
36 + "@smbcloud/sigit-linux-arm64": "${release_version}",
37 + "@smbcloud/sigit-linux-x64": "${release_version}",
38 + "@smbcloud/sigit-windows-arm64": "${release_version}",
39 + "@smbcloud/sigit-windows-x64": "${release_version}"
40 + }
41 +}
npm/package.json.tmpl new
+14
@@ -0,0 +1,14 @@
1 +{
2 + "name": "@smbcloud/${node_pkg}",
3 + "version": "${node_version}",
4 + "description": "Platform binary for siGit Code.",
5 + "license": "Apache-2.0",
6 + "repository": {
7 + "type": "git",
8 + "url": "git+https://github.com/getsigit/sigit.git"
9 + },
10 + "keywords": ["${node_pkg}","cli","binary","sigit","ai","coding-agent"],
11 + "os": ["${node_os}"],
12 + "cpu": ["${node_arch}"],
13 + "files": ["bin"]
14 +}
npm/scripts/render-main-package.cjs new
+34
@@ -0,0 +1,34 @@
1 +#!/usr/bin/env node
2 +
3 +const fs = require("fs");
4 +const path = require("path");
5 +
6 +const [outputPath, version] = process.argv.slice(2);
7 +
8 +if (!outputPath || !version) {
9 + throw new Error("Usage: render-main-package.cjs <output-path> <version>");
10 +}
11 +
12 +const npmRoot = path.resolve(__dirname, "..");
13 +
14 +const vars = {
15 + release_version: version,
16 +};
17 +
18 +/**
19 + * Replace every `${key}` in the template with the corresponding value from vars.
20 + */
21 +function interpolate(template, variables) {
22 + return template.replace(/\$\{(\w+)\}/g, (match, key) => {
23 + if (key in variables) return variables[key];
24 + return match;
25 + });
26 +}
27 +
28 +// Read and interpolate package-main.json.tmpl
29 +const template = fs.readFileSync(
30 + path.join(npmRoot, "package-main.json.tmpl"),
31 + "utf-8",
32 +);
33 +
34 +fs.writeFileSync(path.resolve(outputPath), interpolate(template, vars));
npm/scripts/render-platform-package.cjs new
+56
@@ -0,0 +1,56 @@
1 +#!/usr/bin/env node
2 +
3 +const fs = require("fs");
4 +const path = require("path");
5 +
6 +const [packageName, version, operatingSystem, architecture] =
7 + process.argv.slice(2);
8 +
9 +if (!packageName || !version || !operatingSystem || !architecture) {
10 + throw new Error(
11 + "Usage: render-platform-package.cjs <package-name> <version> <os> <arch>",
12 + );
13 +}
14 +
15 +const npmRoot = path.resolve(__dirname, "..");
16 +const packageDirectory = path.resolve(npmRoot, packageName);
17 +
18 +fs.mkdirSync(packageDirectory, { recursive: true });
19 +
20 +// Variable map for template interpolation
21 +const vars = {
22 + node_pkg: packageName,
23 + node_version: version,
24 + node_os: operatingSystem,
25 + node_arch: architecture,
26 +};
27 +
28 +/**
29 + * Replace every `${key}` in the template with the corresponding value from vars.
30 + */
31 +function interpolate(template, variables) {
32 + return template.replace(/\$\{(\w+)\}/g, (match, key) => {
33 + if (key in variables) return variables[key];
34 + return match;
35 + });
36 +}
37 +
38 +// Read and interpolate package.json.tmpl
39 +const packageTemplate = fs.readFileSync(
40 + path.join(npmRoot, "package.json.tmpl"),
41 + "utf-8",
42 +);
43 +fs.writeFileSync(
44 + path.join(packageDirectory, "package.json"),
45 + interpolate(packageTemplate, vars),
46 +);
47 +
48 +// Read and interpolate README.md.tmpl
49 +const readmeTemplate = fs.readFileSync(
50 + path.join(npmRoot, "README.md.tmpl"),
51 + "utf-8",
52 +);
53 +fs.writeFileSync(
54 + path.join(packageDirectory, "README.md"),
55 + interpolate(readmeTemplate, vars),
56 +);
npm/sigit/.gitignore new
+2
@@ -0,0 +1,2 @@
1 +lib/
2 +node_modules/
npm/sigit/README.md new
+85
@@ -0,0 +1,85 @@
1 +<h1 align="center">siGit Code</h1>
2 +
3 +<p align="center">
4 + AI coding agent powered by local LLM via Onde Inference.
5 +</p>
6 +
7 +<p align="center">
8 + <a href="https://www.npmjs.com/package/@smbcloud/sigit"><img src="https://img.shields.io/npm/v/@smbcloud/sigit?style=flat-square&labelColor=17211D&color=235843" alt="npm"></a>
9 + <a href="https://crates.io/crates/sigit"><img src="https://img.shields.io/crates/v/sigit?style=flat-square&labelColor=17211D&color=235843" alt="crates.io"></a>
10 + <a href="https://pypi.org/project/sigit/"><img src="https://img.shields.io/pypi/v/sigit?style=flat-square&labelColor=17211D&color=235843" alt="PyPI"></a>
11 +</p>
12 +
13 +---
14 +
15 +## Install
16 +
17 +```sh
18 +npm install -g @smbcloud/sigit
19 +```
20 +
21 +The right binary for your platform gets pulled in automatically. Works on macOS (Apple Silicon and Intel), Linux (x64 and arm64), and Windows (x64 and arm64).
22 +
23 +### Other ways to install
24 +
25 +| Method | Command |
26 +|---|---|
27 +| **Homebrew** | `brew install getsigit/homebrew-tap/sigit` |
28 +| **pip** | `pip install sigit` |
29 +| **Cargo** | `cargo install sigit` |
30 +
31 +---
32 +
33 +## Usage
34 +
35 +```sh
36 +sigit
37 +```
38 +
39 +Opens a TUI coding agent that runs entirely on your device using a local LLM.
40 +
41 +### Zed ACP (Agent Control Protocol)
42 +
43 +Add siGit as an agent in Zed by adding this to your settings:
44 +
45 +```json
46 +{
47 + "agent": {
48 + "profiles": {
49 + "sigit": {
50 + "provider": "acp",
51 + "binary": "sigit",
52 + "args": ["--acp"]
53 + }
54 + }
55 + }
56 +}
57 +```
58 +
59 +---
60 +
61 +## Platform support
62 +
63 +| Platform | Architecture | Package |
64 +|---|---|---|
65 +| macOS | Apple Silicon (arm64) | `@smbcloud/sigit-darwin-arm64` |
66 +| macOS | Intel (x64) | `@smbcloud/sigit-darwin-x64` |
67 +| Linux | x64 | `@smbcloud/sigit-linux-x64` |
68 +| Linux | arm64 | `@smbcloud/sigit-linux-arm64` |
69 +| Windows | x64 | `@smbcloud/sigit-windows-x64` |
70 +| Windows | arm64 | `@smbcloud/sigit-windows-arm64` |
71 +
72 +---
73 +
74 +## Links
75 +
76 +- [Source code](https://github.com/getsigit/sigit)
77 +- [Issues](https://github.com/getsigit/sigit/issues)
78 +
79 +## License
80 +
81 +[Apache-2.0](https://github.com/getsigit/sigit/blob/main/LICENSE)
82 +
83 +<p align="center">
84 + <sub>© 2026 <a href="https://www.smbcloud.xyz">smbCloud</a> · <a href="https://apps.apple.com/se/developer/splitfire-ab/id1831430993">Splitfire AB</a></sub>
85 +</p>
\ No newline at end of file
npm/sigit/package.json new
+44
@@ -0,0 +1,44 @@
1 +{
2 + "name": "@smbcloud/sigit",
3 + "version": "0.0.0-dev",
4 + "keywords": [
5 + "sigit",
6 + "cli",
7 + "ai",
8 + "coding-agent",
9 + "llm",
10 + "on-device",
11 + "smbcloud",
12 + "acp"
13 + ],
14 + "bin": {
15 + "sigit": "lib/index.js"
16 + },
17 + "files": [
18 + "lib",
19 + "README.md"
20 + ],
21 + "description": "AI coding agent powered by local LLM via Onde Inference.",
22 + "license": "Apache-2.0",
23 + "repository": {
24 + "type": "git",
25 + "url": "git+https://github.com/getsigit/sigit.git"
26 + },
27 + "scripts": {
28 + "typecheck": "tsc --noEmit",
29 + "build": "tsc",
30 + "dev": "npm run build && node lib/index.js"
31 + },
32 + "devDependencies": {
33 + "@types/node": "^18.15.11",
34 + "typescript": "^5.0.0"
35 + },
36 + "optionalDependencies": {
37 + "@smbcloud/sigit-darwin-arm64": "0.0.0-dev",
38 + "@smbcloud/sigit-darwin-x64": "0.0.0-dev",
39 + "@smbcloud/sigit-linux-arm64": "0.0.0-dev",
40 + "@smbcloud/sigit-linux-x64": "0.0.0-dev",
41 + "@smbcloud/sigit-windows-arm64": "0.0.0-dev",
42 + "@smbcloud/sigit-windows-x64": "0.0.0-dev"
43 + }
44 +}
npm/sigit/src/index.ts new
+43
@@ -0,0 +1,43 @@
1 +#!/usr/bin/env node
2 +
3 +import { spawnSync } from "child_process";
4 +
5 +/**
6 + * Returns the executable path which is located inside node_modules
7 + * The naming convention is cli-OS-ARCH
8 + * If the platform is win32 or cygwin, executable will include a .exe extension.
9 + * @see https://nodejs.org/api/os.html#osarch
10 + * @see https://nodejs.org/api/os.html#osplatform
11 + * @example "x/xx/node_modules/cli-darwin-arm64"
12 + */
13 +function getExePath() {
14 + const arch = process.arch;
15 + let os = process.platform as string;
16 + let extension = "";
17 + if (["win32", "cygwin"].includes(process.platform)) {
18 + os = "windows";
19 + extension = ".exe";
20 + }
21 +
22 + try {
23 + // Since the binary will be located inside node_modules, we can simply call require.resolve
24 + return require.resolve(
25 + `@smbcloud/sigit-${os}-${arch}/bin/sigit${extension}`,
26 + );
27 + } catch (e) {
28 + throw new Error(
29 + `Couldn't find application binary inside node_modules for ${os}-${arch}`,
30 + );
31 + }
32 +}
33 +
34 +/**
35 + * Runs the application with args using nodejs spawn
36 + */
37 +function run() {
38 + const args = process.argv.slice(2);
39 + const processResult = spawnSync(getExePath(), args, { stdio: "inherit" });
40 + process.exit(processResult.status ?? 0);
41 +}
42 +
43 +run();
npm/sigit/tsconfig.json new
+12
@@ -0,0 +1,12 @@
1 +{
2 + "compilerOptions": {
3 + "target": "es2016",
4 + "module": "commonjs",
5 + "esModuleInterop": true,
6 + "baseUrl": "./",
7 + "outDir": "lib",
8 + "forceConsistentCasingInFileNames": true,
9 + "strict": true,
10 + "skipLibCheck": true
11 + }
12 +}
pypi/README.md new
+107
@@ -0,0 +1,107 @@
1 +<p align="center">
2 + <strong>siGit Code</strong>
3 +</p>
4 +
5 +<h1 align="center">sigit</h1>
6 +
7 +<p align="center">
8 + <strong>AI coding agent powered by local LLM via <a href="https://ondeinference.com">Onde Inference</a>.</strong><br>
9 + ACP-compatible agent that runs entirely on your machine — no API keys, no cloud.
10 +</p>
11 +
12 +<p align="center">
13 + <a href="https://smbcloud.xyz"><img src="https://img.shields.io/badge/smbcloud.xyz-235843?style=flat-square&labelColor=17211D" alt="Website"></a>
14 + <a href="https://pypi.org/project/sigit-code/"><img src="https://img.shields.io/pypi/v/sigit-code?style=flat-square&labelColor=17211D&color=235843" alt="PyPI"></a>
15 + <a href="https://www.npmjs.com/package/@smbcloud/sigit"><img src="https://img.shields.io/npm/v/@smbcloud/sigit?style=flat-square&labelColor=17211D&color=235843" alt="npm"></a>
16 + <a href="https://crates.io/crates/sigit"><img src="https://img.shields.io/crates/v/sigit?style=flat-square&labelColor=17211D&color=235843" alt="Crates.io"></a>
17 + <a href="https://github.com/getsigit/sigit/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Apache--2.0-235843?style=flat-square&labelColor=17211D" alt="License"></a>
18 +</p>
19 +
20 +<br>
21 +
22 +---
23 +
24 +## Install
25 +
26 +```sh
27 +pip install sigit-code
28 +```
29 +
30 +Installs the native `sigit` binary for your platform — no compiler, no Node.js, no runtime dependencies.
31 +
32 +## Quick start
33 +
34 +### Interactive TUI
35 +
36 +```sh
37 +sigit
38 +```
39 +
40 +A terminal UI opens where you can chat with a local LLM coding agent directly.
41 +
42 +### Zed editor (ACP agent)
43 +
44 +siGit works as an [ACP-compatible](https://github.com/nicobailon/agent-client-protocol) agent in [Zed](https://zed.dev). Add this to your Zed settings:
45 +
46 +```json
47 +{
48 + "agent": {
49 + "profiles": {
50 + "sigit": {
51 + "provider": "acp",
52 + "binary": {
53 + "path": "sigit",
54 + "args": ["--acp"]
55 + }
56 + }
57 + }
58 + }
59 +}
60 +```
61 +
62 +Then select **sigit** as your agent profile in the Zed assistant panel.
63 +
64 +## Other installation methods
65 +
66 +| Method | Command |
67 +|--------|---------|
68 +| npm | `npm install -g @smbcloud/sigit` |
69 +| Homebrew | `brew install getsigit/sigit/sigit` |
70 +| Cargo | `cargo install sigit` |
71 +
72 +### From source
73 +
74 +```sh
75 +git clone https://github.com/getsigit/sigit
76 +cd sigit
77 +cargo build --release
78 +./target/release/sigit
79 +```
80 +
81 +## Platform support
82 +
83 +Pre-built native binaries ship for every major platform:
84 +
85 +| Platform | Architecture |
86 +|---------------|--------------|
87 +| macOS | arm64, x64 |
88 +| Linux (glibc) | arm64, x64 |
89 +| Windows | arm64, x64 |
90 +
91 +## Source & issues
92 +
93 +This package ships a pre-built native binary. Source lives at
94 +[github.com/getsigit/sigit](https://github.com/getsigit/sigit) —
95 +file bugs and feature requests there.
96 +
97 +## License
98 +
99 +Licensed under **Apache 2.0**.
100 +
101 +- [Apache License 2.0](https://github.com/getsigit/sigit/blob/main/LICENSE)
102 +
103 +---
104 +
105 +<p align="center">
106 + <sub>Built by <a href="https://smbcloud.xyz">smbCloud</a> (Splitfire AB) · © 2026</sub>
107 +</p>
\ No newline at end of file
pypi/pyproject.toml new
+38
@@ -0,0 +1,38 @@
1 +[build-system]
2 +requires = ["maturin>=1.7,<2.0"]
3 +build-backend = "maturin"
4 +
5 +[project]
6 +name = "sigit-code"
7 +description = "AI coding agent powered by local LLM via Onde Inference."
8 +readme = "README.md"
9 +requires-python = ">=3.8"
10 +dynamic = ["version"]
11 +license = { text = "Apache-2.0" }
12 +authors = [{ name = "Seto Elkahfi", email = "hej@setoelkahfi.se" }]
13 +keywords = ["sigit", "cli", "ai", "coding-agent", "llm", "on-device"]
14 +classifiers = [
15 + "Development Status :: 4 - Beta",
16 + "Environment :: Console",
17 + "Intended Audience :: Developers",
18 + "License :: OSI Approved :: Apache Software License",
19 + "Operating System :: MacOS",
20 + "Operating System :: Microsoft :: Windows",
21 + "Operating System :: POSIX :: Linux",
22 + "Programming Language :: Python :: 3",
23 + "Programming Language :: Rust",
24 + "Topic :: Scientific/Engineering :: Artificial Intelligence",
25 + "Topic :: Software Development",
26 + "Topic :: Utilities",
27 +]
28 +
29 +[project.urls]
30 +Homepage = "https://smbcloud.xyz"
31 +Documentation = "https://github.com/getsigit/sigit"
32 +Repository = "https://github.com/getsigit/sigit"
33 +Issues = "https://github.com/getsigit/sigit/issues"
34 +
35 +[tool.maturin]
36 +manifest-path = "../Cargo.toml"
37 +bindings = "bin"
38 +strip = true
rust-toolchain.toml new
+2
@@ -0,0 +1,2 @@
1 +[toolchain]
2 +channel = "stable"