build: the claw stands alone

The claw product (the daemon, the feed integrations, the client
tools, and the web and android trees) extracted from the framework
repository, keeping its history. The framework crates the product
pulls are all on crates.io at 0.2.3, so the in-tree path
dependencies became versions and the workspace resolves without the
framework checkout.
This commit is contained in:
vhaudiquet committed 2026-11-12 17:43:08 +01:00
1 parent 36a79ced0e
commit 552a76ba99
8 files changed
+3516 -17

No files matched your search

+1
View File
@@ -0,0 +1 @@
/target/
Generated
+3432
View File
File diff suppressed because it is too large. Load diff
+34
View File
@@ -0,0 +1,34 @@
[workspace]
resolver = "2"
members = ["crates/*", "integrations/*"]
[workspace.package]
version = "0.2.3"
edition = "2024"
rust-version = "1.89"
license = "MIT"
repository = "https://git.vhaudiquet.fr/vhaudiquet/rhema-claw"
authors = ["Valentin Haudiquet"]
[workspace.lints.rust]
missing_docs = "deny"
[workspace.dependencies]
# Serialization: session and message types must round-trip for checkpointing
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
# Typed library errors
thiserror = "2"
# Async traits must stay object-safe (dyn ModelProvider, dyn ToolResolver)
async-trait = "0.1"
# Config file format (flat scalar fields; see the rhema-config crate)
serde_yaml = "0.9"
# Test runtime
tokio = { version = "1", features = ["macros", "rt"] }
# The claw's HTTP surface: native routes plus SSE, and the OpenAI shim
axum = { version = "0.8", features = ["json"] }
tokio-stream = { version = "0.1", features = ["sync"] }
[profile.release]
strip = "symbols"
codegen-units = 1
+32
View File
@@ -0,0 +1,32 @@
<div align="center">
<b>ῥῆμα, "the spoken word": words that do things.</b>
</div>
<h1 align="center">Rhema Claw</h1>
Rhema Claw is the resident tier of the Rhema agent framework: a
claw-shaped daemon that watches forges (GitHub, Gitea, GitLab) and
calendar feeds, dispatches work to its agents, and serves a chat
surface over HTTP — native routes plus an OpenAI-compatible shim,
with a web UI and an Android client talking to it.
The framework it embeds (the crates under `crates/` it pulls from
crates.io: `rhema-autonomous-agent`, `rhema-coding-agent`,
`rhema-rsd`, and friends) lives in the
[rhema repository](https://git.vhaudiquet.fr/vhaudiquet/rhema).
## Layout
- [`crates/rhema-claw/`](./crates/rhema-claw) — the daemon: forge
watches, session dispatch, the chat surface, MCP wiring, and the
vision helper. See its
[README](./crates/rhema-claw/README.md).
- [`integrations/`](./integrations) — the feed adapters that
normalize forge and calendar activity into `rhema-rsd` dispatch.
- [`tools/`](./tools) — what runs on the *user's machine*: the
`rhema-claw-tools-contract` (the scoped agent-token allowlist the
auth middleware enforces), the shared thin-client code, and
`rhema-claw-tools-notify`.
- [`web/claw/`](./web/claw) — the Nuxt web UI.
- [`android/`](./android) — the Compose Android client.
- [`deploy/`](./deploy) — the Docker images and the Helm chart.
+13 -13
View File
@@ -27,28 +27,28 @@ mock = ["rhema-core/mock"]
[dependencies] [dependencies]
# The shared toolkit: the resident agent assembles its agent from the # The shared toolkit: the resident agent assembles its agent from the
# shell, the approval seam, paste expansion, and revive-on-resume # shell, the approval seam, paste expansion, and revive-on-resume
rhema-agent-tools = { path = "../rhema-agent-tools" } rhema-agent-tools = "0.2.3"
rhema-autonomous-agent = { path = "../rhema-autonomous-agent" } rhema-autonomous-agent = "0.2.3"
rhema-coding-agent = { path = "../rhema-coding-agent" } rhema-coding-agent = "0.2.3"
rhema-config = { path = "../rhema-config" } rhema-config = "0.2.3"
rhema-core = { path = "../rhema-core" } rhema-core = "0.2.3"
# The bounded request view over the claw sessions, on by default here # The bounded request view over the claw sessions, on by default here
rhema-transcript = { path = "../rhema-transcript" } rhema-transcript = "0.2.3"
rhema-calendar-integration = { path = "../../integrations/rhema-calendar-integration" } rhema-calendar-integration = { path = "../../integrations/rhema-calendar-integration" }
rhema-forge-integration = { path = "../../integrations/rhema-forge-integration" } rhema-forge-integration = { path = "../../integrations/rhema-forge-integration" }
# The accounts layer: identities hold the forge tokens the watches poll # The accounts layer: identities hold the forge tokens the watches poll
# with, and the identity tools manage them over chat # with, and the identity tools manage them over chat
rhema-identity = { path = "../rhema-identity" } rhema-identity = "0.2.3"
rhema-rsd = { path = "../rhema-rsd" } rhema-rsd = "0.2.3"
# The tool contract: the agent-token allowlist and version the auth # The tool contract: the agent-token allowlist and version the auth
# middleware enforces (rhema-tools spec). The arrow runs claw -> # middleware enforces (rhema-tools spec). The arrow runs claw ->
# contract only — never the reverse. # contract only — never the reverse.
rhema-claw-tools-contract = { path = "../../tools/contract" } rhema-claw-tools-contract = { path = "../../tools/contract" }
# The resident tier's durable memory: its tools join the resolver chain # The resident tier's durable memory: its tools join the resolver chain
rhema-memory = { path = "../rhema-memory" } rhema-memory = "0.2.3"
# The shared ModelCard the backend registry's listings return # The shared ModelCard the backend registry's listings return
rhema-provider = { path = "../rhema-provider" } rhema-provider = "0.2.3"
rhema-provider-registry = { path = "../rhema-provider-registry", version = "0.2.3" } rhema-provider-registry = "0.2.3"
# Args for the two-flag binary surface # Args for the two-flag binary surface
clap = { version = "4.5", features = ["derive"] } clap = { version = "4.5", features = ["derive"] }
serde = { workspace = true } serde = { workspace = true }
@@ -71,7 +71,7 @@ time = { version = "0.3", default-features = false, features = ["parsing"] }
# Inbound chat images ride base64; the dispatch decodes them into the # Inbound chat images ride base64; the dispatch decodes them into the
# attachment store # attachment store
base64 = "0.22" base64 = "0.22"
rhema-mcp = { version = "0.2.3", path = "../rhema-mcp" } rhema-mcp = "0.2.3"
[dev-dependencies] [dev-dependencies]
tempfile = "3" tempfile = "3"
@@ -83,7 +83,7 @@ reqwest = { version = "0.12", features = ["json", "stream"] }
bytes = "1" bytes = "1"
# The scripted provider for turn-level tests; mirrors rhema-code's mock # The scripted provider for turn-level tests; mirrors rhema-code's mock
# feature without a feature of our own — tests are the only consumer # feature without a feature of our own — tests are the only consumer
rhema-core = { path = "../rhema-core", features = ["mock"] } rhema-core = { version = "0.2.3", features = ["mock"] }
tokio = { workspace = true, features = ["rt-multi-thread", "macros", "sync", "time"] } tokio = { workspace = true, features = ["rt-multi-thread", "macros", "sync", "time"] }
[lints] [lints]
@@ -15,10 +15,10 @@ publish = false
rusqlite = { version = "0.40", features = ["bundled"] } rusqlite = { version = "0.40", features = ["bundled"] }
# The reminder source: one `Source` over the feeds, detect-pass shaped # The reminder source: one `Source` over the feeds, detect-pass shaped
# like the task scheduler's # like the task scheduler's
rhema-autonomous-agent = { path = "../../crates/rhema-autonomous-agent", version = "0.2.3" } rhema-autonomous-agent = "0.2.3"
# The reminder source ingests its slots into a `Dispatcher`; the event # The reminder source ingests its slots into a `Dispatcher`; the event
# and key-function shapes are the dispatcher's # and key-function shapes are the dispatcher's
rhema-rsd = { path = "../../crates/rhema-rsd", version = "0.2.3" } rhema-rsd = "0.2.3"
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
@@ -13,7 +13,7 @@ publish = false
[dependencies] [dependencies]
# The dispatch seam: watches ingest into a Dispatcher # The dispatch seam: watches ingest into a Dispatcher
rhema-rsd = { path = "../../crates/rhema-rsd", version = "0.2.3" } rhema-rsd = "0.2.3"
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
thiserror = { workspace = true } thiserror = { workspace = true }
+1 -1
View File
@@ -7,7 +7,7 @@ version = "0.1.0"
edition = "2024" edition = "2024"
rust-version = "1.85" rust-version = "1.85"
license = "MIT" license = "MIT"
repository = "https://github.com/vhaudiquet/rhema" repository = "https://git.vhaudiquet.fr/vhaudiquet/rhema-claw"
authors = ["Valentin Haudiquet"] authors = ["Valentin Haudiquet"]
[workspace.dependencies] [workspace.dependencies]