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
2 changes: 1 addition & 1 deletion .github/scripts/check_cli_flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def main() -> int:
with open(help_path, encoding="utf-8") as f:
help_text = f.read()
if not flags:
print("::error::found no flags in to_argv; has src/options.rs moved?")
print("::error::found no flags in to_argv; has crates/ccwire/src/options.rs moved?")
return 1
missing = []
for flag in flags:
Expand Down
20 changes: 12 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
features:
- { name: default, flags: "" }
# `runtime` adds the framing's async half and the session tests
# over the fake CLI (tests/fake_claude).
# over the fake CLI (crates/ccwire/tests/fake_claude).
- { name: all-features, flags: "--all-features" }
steps:
- uses: actions/checkout@v7
Expand All @@ -88,7 +88,7 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.features.name }}
# Includes tests/corpus.rs, the golden corpus test.
# Includes crates/ccwire/tests/corpus.rs, the golden corpus test.
- run: cargo test --workspace --all-targets --locked ${{ matrix.features.flags }}
- run: cargo test --workspace --doc --locked ${{ matrix.features.flags }}

Expand All @@ -101,13 +101,17 @@ jobs:
- name: Read rust-version from Cargo.toml
id: msrv
run: |
if grep -Eq '^rust-version\.workspace|^rust-version *= *\{' Cargo.toml; then
echo "::error::Cargo.toml inherits rust-version from a workspace; this repo needs an explicit rust-version = \"x.y\""
exit 1
fi
# One MSRV, the root's [workspace.package] rust-version, which
# every crate inherits.
for manifest in crates/*/Cargo.toml; do
if ! grep -Eq '^rust-version\.workspace *= *true' "$manifest"; then
echo "::error::$manifest doesn't inherit rust-version (rust-version.workspace = true)"
exit 1
fi
done
msrv=$(sed -n 's/^rust-version *= *"\(.*\)"/\1/p' Cargo.toml)
if [ -z "$msrv" ]; then
echo "::error::no rust-version = \"...\" in Cargo.toml"
echo "::error::no rust-version = \"...\" in Cargo.toml's [workspace.package]"
exit 1
fi
echo "MSRV: $msrv"
Expand All @@ -125,7 +129,7 @@ jobs:
with:
toolchain: ${{ steps.msrv.outputs.version }}
- uses: Swatinem/rust-cache@v2
# Every crate in the workspace (they share the root's rust-version).
# Every crate in the workspace (they inherit the root's rust-version).
- run: cargo +${{ steps.msrv.outputs.version }} build --workspace --all-features --locked
- run: cargo +${{ steps.msrv.outputs.version }} build --workspace --locked

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/newest-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ jobs:

- name: Compare the CLI version with TESTED_CLI_VERSION
run: |
tested=$(sed -n 's/^pub const TESTED_CLI_VERSION: &str = "\(.*\)";/\1/p' src/lib.rs)
tested=$(sed -n 's/^pub const TESTED_CLI_VERSION: &str = "\(.*\)";/\1/p' crates/ccwire/src/lib.rs)
newest=$(claude --version | awk '{print $1}')
if [ -z "$tested" ]; then
echo "::error::no TESTED_CLI_VERSION in src/lib.rs"
echo "::error::no TESTED_CLI_VERSION in crates/ccwire/src/lib.rs"
exit 1
fi
{
Expand All @@ -55,13 +55,13 @@ jobs:
echo "- TESTED_CLI_VERSION: \`$tested\`"
} >> "$GITHUB_STEP_SUMMARY"
if [ "$newest" != "$tested" ]; then
echo "::warning::claude $newest differs from TESTED_CLI_VERSION $tested; re-record the corpus (tests/corpus)"
echo "::warning::claude $newest differs from TESTED_CLI_VERSION $tested; re-record the corpus (crates/ccwire/tests/corpus)"
fi

- name: Check that every to_argv flag is in claude --help
run: |
claude --help > "$RUNNER_TEMP/claude-help.txt"
python3 .github/scripts/check_cli_flags.py src/options.rs "$RUNNER_TEMP/claude-help.txt"
python3 .github/scripts/check_cli_flags.py crates/ccwire/src/options.rs "$RUNNER_TEMP/claude-help.txt"

# Only with the secret: a skipped step costs nothing and needs no key.
- name: Live turn (needs ANTHROPIC_API_KEY)
Expand Down
89 changes: 29 additions & 60 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,70 +1,43 @@
[package]
name = "ccwire"
description = "A Rust SDK for Claude Code: the stream-json protocol, typed"
version = "0.1.1"
# ccwire: a Rust SDK for Claude Code. `ccwire` is the stream-json protocol
# and session core, `ccwire-oauth` a client for the Claude account endpoints
# an OAuth login can call. Each crate keeps its own version, README and
# exclude list; the rest is shared here.
[workspace]
resolver = "3"
members = ["crates/*"]

[workspace.package]
edition = "2024"
license = "Apache-2.0"
readme = "README.md"
repository = "https://github.com/talaagent/ccwire"
documentation = "https://docs.rs/ccwire"
authors = ["Ian Macalinao <github@igm.pub>"]
# The MSRV of every crate (CI's `msrv` job reads it from here).
rust-version = "1.85"
keywords = ["claude", "claude-code", "agent", "sdk"]
categories = ["api-bindings"]
# The golden corpus (and scrub.py, its tool) stays in the repo; its test
# goes with it, as it include_str!s the corpus. So do the repo's CI, release
# and Nix files.
exclude = [
"tests/corpus",
"tests/corpus.rs",
".github",
".gitignore",
"clippy.toml",
"deny.toml",
"release-plz.toml",
"flake.nix",
"flake.lock",
]

[features]
default = []
# The async layers over tokio: the framing's async reader and writer, and
# the session core. The `protocol` module and the sync framing never need it.
runtime = ["dep:tokio"]
# Logs every `Other` and `Malformed` frame (debug and warn, with its type),
# besides counting them (`protocol::stats`, always on).
tracing = ["dep:tracing"]

# Each crate turns on the features it uses (`features = [...]` beside
# `workspace = true`); the entries here only pin versions and turn default
# features off where a crate wants them off.
[workspace.dependencies]
httpdate = "1"
# reqwest's default TLS is rustls (aws-lc-rs provider, the platform's
# roots); http2 for the API, no system proxy lookup, no cookies.
reqwest = { version = "0.13", default-features = false, features = [
"rustls",
"http2",
"charset",
] }
serde = { version = "1", features = ["derive"] }
# serde_json without `preserve_order` or `float_roundtrip`: frames compare
# as `Value`s, so key order and the last float digit don't matter.
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
thiserror = "2"
# Only what the session core uses: async I/O traits and buffering (io-util),
# its channels (sync) and its reader/writer tasks (rt).
tokio = { version = "1", default-features = false, features = [
"io-util",
"sync",
"rt",
], optional = true }
tracing = { version = "0.1", default-features = false, features = [
"std",
], optional = true }

[dev-dependencies]
# The tests' runtimes (current-thread and multi-thread) and their hang
# guard.
tokio = { version = "1", default-features = false, features = [
"io-util",
"sync",
"rt",
"rt-multi-thread",
"macros",
"time",
] }
tokio = { version = "1", default-features = false }
tracing = { version = "0.1", default-features = false, features = ["std"] }
url = "2"
wiremock = "0.6"
zeroize = "1"

[lints.clippy]
[workspace.lints.clippy]
pedantic = { level = "warn", priority = -1 }
complexity = { level = "deny", priority = -1 }
must_use_candidate = "allow"
Expand All @@ -83,7 +56,3 @@ await_holding_lock = "deny"
disallowed_methods = "deny"
disallowed_types = "deny"
large_futures = "allow"

# ccwire is the root package; the rest of the repo's crates are members.
[workspace]
members = ["ccwire-oauth"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Until the first crates.io release, use the git repository:
ccwire = { git = "https://github.com/talaagent/ccwire", features = ["runtime"] }
```

The workspace also has [`ccwire-oauth`](https://github.com/talaagent/ccwire/tree/main/ccwire-oauth), a typed client for
The workspace also has [`ccwire-oauth`](https://github.com/talaagent/ccwire/tree/main/crates/ccwire-oauth), a typed client for
the Claude account endpoints an OAuth login can call.

## `ccwire::protocol`
Expand Down
61 changes: 0 additions & 61 deletions ccwire-oauth/Cargo.toml

This file was deleted.

Loading
Loading