Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Release

on:
push:
tags: ["v*"]

permissions:
contents: write # create the GitHub Release + upload assets

env:
CARGO_TERM_COLOR: always

jobs:
crates:
name: Publish to crates.io
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Verify workspace version matches the tag
run: |
VER="$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/')"
TAG="${GITHUB_REF_NAME#v}"
if [ "$VER" != "$TAG" ]; then
echo "::error::workspace version ($VER) does not match tag ($TAG)"
exit 1
fi

# Dependency order; modern cargo waits for each crate to index before returning.
- name: Publish crates
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
cargo publish -p codeoid-protocol
cargo publish -p codeoid-client
cargo publish -p codeoid-tui

binaries:
name: Binary (${{ matrix.target }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { os: ubuntu-latest, target: x86_64-unknown-linux-gnu }
- { os: macos-latest, target: aarch64-apple-darwin }
- { os: macos-13, target: x86_64-apple-darwin }
steps:
- uses: actions/checkout@v4

- name: Setup Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}

- name: Cache cargo build
uses: Swatinem/rust-cache@v2

- name: Build codeoid-tui
run: cargo build --release -p codeoid-tui --target ${{ matrix.target }}

- name: Package tarball
shell: bash
run: |
DIR="codeoid-tui-${GITHUB_REF_NAME}-${{ matrix.target }}"
mkdir "$DIR"
cp "target/${{ matrix.target }}/release/codeoid-tui" "$DIR/"
cp README.md LICENSE "$DIR/" 2>/dev/null || true
tar -czf "${DIR}.tar.gz" "$DIR"
echo "ASSET=${DIR}.tar.gz" >> "$GITHUB_ENV"

- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
files: ${{ env.ASSET }}
generate_release_notes: true
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Changelog

All notable changes to **codeoid-ui** (the native Rust client for Codeoid) are
documented here. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
versioning: [SemVer](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.0] - 2026-06-23

Initial public release.

### Added

- **`codeoid-tui`** — a native [Ratatui](https://ratatui.rs) terminal cockpit for
the Codeoid daemon: a true cell-matrix framebuffer, so it stays jitter-free
under high-frequency streaming deltas.
- **`codeoid-client`** — async WebSocket client (auth handshake, request/response
correlation, and the unsolicited event stream).
- **`codeoid-protocol`** — serde-compatible Rust port of the daemon's wire
protocol; `PROTOCOL_VERSION` is negotiated on connect so client and daemon
versions can move independently.

[Unreleased]: https://github.com/saucam/codeoid-ui/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/saucam/codeoid-ui/releases/tag/v0.1.0
8 changes: 5 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ edition = "2021"
rust-version = "1.85"
license = "MIT"
authors = ["Codeoid <dev@codeoid.ai>"]
repository = "https://github.com/codeoid/codeoid-ui"
repository = "https://github.com/saucam/codeoid-ui"
homepage = "https://github.com/saucam/codeoid-ui"
keywords = ["codeoid", "claude", "tui", "ai-agents", "ratatui"]

[workspace.dependencies]
# Workspace-internal
codeoid-protocol = { path = "crates/codeoid-protocol" }
codeoid-client = { path = "crates/codeoid-client" }
codeoid-protocol = { path = "crates/codeoid-protocol", version = "0.1.0" }
codeoid-client = { path = "crates/codeoid-client", version = "0.1.0" }

# Async runtime
tokio = { version = "1.41", features = ["macros", "rt-multi-thread", "sync", "time", "signal", "io-std", "io-util"] }
Expand Down
47 changes: 47 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Releasing codeoid-ui

Pushing a `vX.Y.Z` tag publishes the three crates to crates.io and attaches
prebuilt `codeoid-tui` binaries to a GitHub Release — see
[`.github/workflows/release.yml`](.github/workflows/release.yml).

## One-time setup

Add a **`CARGO_REGISTRY_TOKEN`** repository secret (Settings → Secrets and
variables → Actions): crates.io → Account Settings → **API Tokens** → new token
scoped to publish.

(Binary uploads need no extra secret — they use the built-in `GITHUB_TOKEN`.)

## Cutting a release

1. Bump the version in [`Cargo.toml`](Cargo.toml): `[workspace.package].version`
**and** the `version = "X.Y.Z"` on the internal path-deps in
`[workspace.dependencies]` (they must match for crates.io).
2. Move the `## [Unreleased]` notes into a new `## [X.Y.Z]` section in
[`CHANGELOG.md`](CHANGELOG.md).
3. Open a PR, get CI green, merge to `main`.
4. Tag from `main` and push (tags are not branch-protected):

```bash
git checkout main && git pull
git tag vX.Y.Z && git push origin vX.Y.Z
```

The workflow publishes `codeoid-protocol` → `codeoid-client` → `codeoid-tui`
(in dependency order; cargo waits for each to index) and uploads macOS
(arm64 / x64) and Linux (x64) binaries. Install with:

```bash
cargo install codeoid-tui # from crates.io
# or download a prebuilt binary from the GitHub Release
```

## Notes

- The **wire protocol** version (`PROTOCOL_VERSION` in `codeoid-protocol`) is
independent of the crate version — bump it only on wire-breaking changes, and
keep it in lockstep with the daemon's `src/protocol/types.ts` in
[codeoid](https://github.com/saucam/codeoid). The handshake negotiates
compatibility, so app versions and the protocol version move independently.
- Both internal crates must be published before `codeoid-tui`; the workflow
handles the ordering.
2 changes: 2 additions & 0 deletions crates/codeoid-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
keywords.workspace = true
description = "Async WebSocket client for the Codeoid daemon. Handles auth handshake, request/response correlation, and the unsolicited event stream."

[dependencies]
Expand Down
2 changes: 2 additions & 0 deletions crates/codeoid-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
keywords.workspace = true
description = "Wire protocol types for the Codeoid daemon — serde-compatible Rust port of src/protocol/types.ts."

[dependencies]
Expand Down
2 changes: 2 additions & 0 deletions crates/codeoid-tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ rust-version.workspace = true
license.workspace = true
authors.workspace = true
repository.workspace = true
homepage.workspace = true
keywords.workspace = true
description = "Ratatui-based terminal cockpit for the Codeoid daemon."

[[bin]]
Expand Down
Loading