A complete service
The three files of a working CrabTalk service, a Rust library crate with echo and durable state, and the commands that test, build, deploy and call it.
crab new hello writes these three files. Each compiles and runs as shown; change them from here.
The files
# Cargo.toml
[package]
name = "hello"
version = "0.1.0"
edition = "2024"
# The cdylib is the image `crab build` finishes; the rlib is what `cargo nextest run` links.
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
berm-lang = { git = "https://github.com/crabtalk/crab", tag = "v0.1.3" }# crab.toml
[tools.echo]
access = "public"
[tools.remember]
access = "public"
catalog = "memory.put"
[tools.recall]
access = "public"
catalog = "memory.get"
[database]
size = "64MiB"// src/lib.rs
#![cfg_attr(target_arch = "wasm32", no_std)]
extern crate alloc;
use alloc::string::String;
use berm_lang::{Result, Schema, tool};
/// Answers its argument back.
#[tool]
pub fn echo(
/// The text to echo back.
query: String,
) -> Result<Echo> {
Ok(Echo { query })
}
/// What `echo` answers.
#[derive(Schema)]
pub struct Echo {
pub query: String,
}
const MESSAGE: &str = "message";
/// Store a message that survives calls and restarts, shared by all callers.
#[tool]
pub fn remember(message: String) -> Result<()> {
berm_lang::set_json(MESSAGE, &message)?;
Ok(())
}
/// Read the message saved by remember, or null if none has been saved.
#[tool(query)]
pub fn recall() -> Result<Option<String>> {
Ok(berm_lang::get_json(MESSAGE)?)
}Cargo.tomlsays what the package is. The crate is a library with no bin target and nofn main, andberm-langis its only dependency, pinned to the tag of the crab that wrote it.crab.tomlsays how it runs: the name it deploys as and who may call each tool. Every key: crab.toml.src/lib.rsisno_stdon WebAssembly and an ordinary library off it. Each#[tool]function is a tool; what the macros accept and generate: Macros.
Running it
crab build installs missing Rust tools through the official rustup installer and adds the wasm32-unknown-unknown target before building. It uses the minimal Rust profile, respects CARGO_HOME and RUSTUP_HOME, and makes installed tools available immediately without changing your shell's PATH. An existing rust-toolchain.toml selects the project's toolchain.
$ crab build
$ crab dev -d
$ crab --context default deploy
$ crab --context default call hello echo '{"query":"hi"}'
{"query":"hi"}
$ crab --context default call hello remember '{"message":"kept between calls"}'
$ crab --context default call hello recall '{}'
"kept between calls"crab dev -dstarts the local host at127.0.0.1:7777in the background.crab --context default deploybuilds the crate in its directory and deploys it there; run it again after a change.crab buildprints the image's path:berm/hello.wasmunder cargo's target directory. A barecargo buildwrites an image without thecrab.tomldeclarations, which a host refuses.crab deployuses the selected context. Runcrab loginto select your Cloud account, thencrab deployto deploy as{owner}/hello. See Deploying.
remember writes JSON to the service's keyspace; recall reads it in a later call, including after a host restart. The stored message is shared by all callers. Use caller-scoped keys for private per-user data; see Data.
Adding tests
The scaffold does not generate a tool-specific test. Add tests for the tools you keep, updating their export names and arguments when the tools change. For example, create tests/tools.rs for echo:
// tests/tools.rs
use berm_lang::test;
#[test]
fn echo_answers_its_argument() {
let out = test::call(hello::berm_tool_echo, br#"{"query":"hi"}"#).unwrap();
assert_eq!(out, br#"{"query":"hi"}"#);
}For native tests, put $CARGO_HOME/bin (~/.cargo/bin by default) on your PATH and install nextest with cargo install cargo-nextest.
Run cargo nextest run after adding the test. Native tests do not provide storage syscalls; test remember and recall with the real host as described in Testing.
Next
| To | Read |
|---|---|
| Write tools, arguments, errors and events | Macros |
| Find a function and its signature | API |
| Keep data, fetch over HTTP, call another service, run on a schedule, take settings | The pages under Capabilities |