Open-source project
eastreams/loong avatar
eastreams/loong

Loong tells you to cargo install a crate that is not in its own workspace

Lightweight, clear, and fully extensible AI agent infrastructure — learn easily, customize anything 🐉

640 stars105 forksRustMIT

At a glance

What is it?
A Rust base for vertical agents, split into a kernel and everything outside it, installed by piping a script off a branch that is not the default. The install instructions and the workspace manifest disagree with each other in three separate places.
Who is it for?
Loong is worth reading for its architecture split, since keeping providers, tools, channels, memory and policy outside the kernel is the decision most agent frameworks get wrong, and for a command surface that exposes audit and runtime state rather than hiding them.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.

Editorial analysis

cargo install names crates/daemon, and the workspace has no crates/daemon

The from-source section offers two paths. One runs the project's own install script with a source flag. The other is described as installing via Cargo only, without the onboarding step:

bash
cargo install --path crates/daemon

The workspace manifest lists ten members: `apps/loong`, then `crates/config`, `crates/tool-host`, `crates/tools`, `crates/agent`, `crates/context`, `crates/contracts`, `crates/kernel`, `crates/provider` and `crates/provider-openai`.

There is no `crates/daemon` among them. The binary lives under `apps/loong`, which is consistent with the statement that `loong` is the only supported command-line entrypoint.

So one of the two documented install paths names a directory the repository does not have. Whether that is a stale name from an earlier layout or a package that was moved without updating the README, the effect on a reader is the same: a copy-and-paste fails with a path error and the remaining instructions are the script path.

This is also the third branch name in one repository. The default branch is `rewrite`, the continuous-integration badge points at `dev`, and the install script is fetched from `dev`. The README says outright that the configuration snippets show what the file looks like on `dev` today.

Four branch-like identifiers, then: `rewrite`, `dev`, a release tag, and whatever the Cargo path was called.

The manifest says 0.2.0, the newest tag is an alpha, and update never takes one

Three release tags are visible and all three are prereleases: v0.1.0-alpha.2 on 2026-03-19, v0.1.2-alpha.1 on 2026-04-20 and v0.1.2-alpha.2 on 2026-05-09.

The workspace package version is `0.2.0`.

So the manifest is ahead of every published tag, by a minor version, and no stable release exists among the visible history. Version numbers also step oddly between tags: alpha.2 to alpha.2 with a minor bump in between, which means at least one 0.1.1 line was skipped in the visible list.

Now the update command. The README states that `loong update` always targets the latest stable GitHub release and never installs a pre-release.

Given the tag list, that command has nothing to target. A user on any published version who runs it gets either no change or an error, and neither outcome is documented.

This is a coherent choice rather than an oversight. A project that publishes only alphas and refuses to auto-install them is saying the upgrade path is manual on purpose. The problem is that the sentence reads as a reassurance about safety rather than as a description of a gap.

Around 640 stars, 105 forks and 47 open issues is a busy issue tracker for a project at zero one.

The Linux installer is curl piped to bash from a branch, and Windows downloads first

The recommended install is one line:

bash
curl -fsSL https://raw.githubusercontent.com/eastreams/loong/dev/scripts/install.sh | bash -s -- --onboard

Two properties of that line matter. The script is fetched from the `dev` branch rather than from a tag, so the contents of the recommended install change whenever that branch moves. And nothing is written to disk before execution, so there is no artefact to inspect or pin.

The Windows path is written the other way round. It downloads the script into the temporary directory with `Invoke-WebRequest`, saves it under a name, then runs it with `pwsh` and an `-Onboard` flag.

That is the safer shape, and having both is an odd asymmetry: the two platforms receive different guarantees from the same documentation, with the stricter one on the platform where most readers will not check.

From source, the prerequisites are a C linker, listed per distribution: build-essential on Debian and Ubuntu, a development tools group install on Fedora, and `xcode-select --install` on macOS. The Rust toolchain is installed through the standard rustup shell script and then activated with `source "$HOME/.cargo/env"`, which is the step people forget.

The onboarding flow is what makes the first run work, since it writes a working configuration to `~/.loong/config.toml` so nobody has to hand-edit TOML.

42+ providers, and the two in the example are OpenAI and a sponsor

The feature list claims 42 or more built-in providers and 25 or more channels. The configuration example shows two providers.

One is OpenAI, configured as an active provider with `kind = "openai"`, a key read from an environment variable, and `model = "auto"`. The other is Volcengine, configured with an `ARK_API_KEY`.

Volcengine is BytePlus, and BytePlus is one of two listed sponsors, the other being Feishu. The sponsor link carries campaign parameters naming the project in four separate fields, so the relationship is visible rather than implied, and the same vendor's key format is the second example in the configuration file.

The `active_provider` field selects which lane runs, switchable by editing the field or rerunning onboarding. The `model = "auto"` value uses provider-side discovery, and the guidance is to pin an explicit identifier when discovery is unreliable for a region or an account.

The one genuinely useful warning in the file concerns the key syntax. Written as `api_key = { env = "OPENAI_API_KEY" }` the string names an environment variable to read. Written as `api_key = "OPENAI_API_KEY"` it is the literal key value, and the configuration accepts both.

That is a mistake that produces an authentication error at call time rather than a parse error at load time, and the README calls it a common pitfall for good reason.

Feishu onboarding writes credentials to loong.toml, and the example reads them from the environment

The first-run channel setup is a single command, `loong feishu onboard --domain lark`. It shows an in-terminal QR code, creates the bot application through the official Lark and Feishu registration API, and writes the generated credentials into `loong.toml`.

The documented configuration block then shows the opposite convention. Under a `[feishu]` table, the application identifier and secret are both written as environment references, with a `domain` field set to `lark` and a note that `feishu` selects the China lane. Receive identifiers are typed as `chat_id`, the mode is `websocket`, and `allowed_chat_ids` carries an explicit list.

Two things follow. The filename differs: the onboarding flow writes `loong.toml`, while the earlier section says onboarding writes `~/.loong/config.toml`. Nothing visible says where the first one lives or how the two files relate.

And the credential handling differs. The QR flow writes generated credentials into a file, while the documented table reads them from the environment. Those are different security postures for the same secret, presented in consecutive sections without a note about which applies when.

A manual path exists for people who cannot scan a code, taking an application identifier and secret directly. The smoke test afterwards is three commands: a doctor check, a send to a single identifier, and a serve.

unsafe_code is a warning, and tokio is declared with two features

The workspace uses resolver 3 and edition 2024, both current-generation Rust settings, and declares MIT at the package level.

The one lint in the manifest is a single line: `unsafe_code = "warn"` under the workspace lint table.

That is a warning, not a denial. Unsafe blocks compile, appear in the output, and do not fail a build. For a project whose feature list leads with a secure and controllable base and with explicit runtime boundaries, that is a defensible choice, since the Rust toolchain and the kernel are exactly where a warning you can review is more useful than an error you cannot. But it is a warning, and the number of unsafe blocks in the tree is not visible from the manifest.

The dependency table is short and mostly exact. Nine path dependencies with renamed packages, so `contracts` resolves to a crate published as `loong-contracts` and the same pattern for kernel, tool host, tools, context, agent, provider, provider-openai and config. Then bincode 1.3.3, schemars 1.2.1, serde 1.0.229, serde_json 1.0.151, async-trait, thiserror, tokio at 1.53.1 and uuid at 1.24.0.

Two of those deserve a second look. Tokio is declared with the features `fs` and `macros`, which is not a set that includes the runtime, timers, sockets or synchronisation primitives, in a project whose channels run over websockets and whose providers are HTTP. Those capabilities must be arriving through feature unification from another crate in the tree, which means the effective feature set is not the one the manifest declares.

And one dependency is pinned with an exact version and named `loac`. It appears nowhere in the documentation, and the name does not explain itself.

Every documentation link points at a site/ directory the root does not contain

The navigation row at the top of the README is a list of documentation links, and every one of them is a path under `site/`: an index, a getting-started overview, a configuration-patterns page, a common-setups page called playbooks, a build-on-it overview, and a rationale page explaining the positioning.

The top level of the repository contains fifteen entries and `site/` is not one of them. There is a `docs/` directory.

So the entire documentation surface the README advertises sits in a directory that does not appear in the tree, while a differently named directory does. That is either a submodule, a branch difference, or a stale set of links, and there is nothing in the visible root to tell you which.

The same root does contain two files that do look current: `ARCHITECTURE.md` and `AGENTS.md`, alongside a `rustfmt.toml` and an `.editorconfig`.

What the README does sell in the open is the command surface, and it is unusual in a good way. Audit, tasks, skills, plugins, channels, a runtime snapshot and gateway control are all exposed as directly usable commands rather than hidden behind a configuration file. The architectural claim is the separation: assistant, gateway and channels operate independently, and providers, tools, channels, memory and policy live outside the kernel so they compile and compose as needed.

Compatibility is claimed with existing configurations from OpenClaw, Claude Code, Codex and OpenCode, which is the fastest way to judge whether adopting it means starting fresh.

Editorial conclusion

Loong is worth reading for its architecture split, since keeping providers, tools, channels, memory and policy outside the kernel is the decision most agent frameworks get wrong, and for a command surface that exposes audit and runtime state rather than hiding them. Before you install it, know that the documented cargo path points at a directory that does not exist in the workspace, that the script installer is fetched from a branch rather than a tag, and that loong update is specified never to install a pre-release while every published tag is one. Pick a branch, read the manifest, and install deliberately.

Frequently asked questions

How do I install Loong on Linux or macOS?

The recommended path pipes the install script from the dev branch straight into bash with an --onboard flag, so there is no artefact to inspect first. From source, install a C linker for your distribution, install the Rust toolchain through rustup, then run bash scripts/install.sh --source --onboard. A Cargo-only option is documented as cargo install --path crates/daemon.

What does loong update install?

The documentation states it always targets the latest stable GitHub release and never installs a pre-release. Every visible tag is an alpha, so among the published releases there is no stable version for the command to move to.

How many providers and channels does Loong support?

The feature list claims 42 or more built-in providers and 25 or more channels. The configuration example shows two, one of which is Volcengine, a listed sponsor. One field, active_provider, selects which provider lane runs.

Where does Loong store its configuration?

Onboarding writes a working configuration to ~/.loong/config.toml so nothing has to be edited by hand. The Feishu onboarding flow is described as writing generated credentials into loong.toml, a different filename whose location and relationship to the first file are not explained.

What is the api_key syntax pitfall in Loong config.toml?

Written as api_key = { env = "OPENAI_API_KEY" } the string names an environment variable to read. Written as api_key = "OPENAI_API_KEY" the same text is treated as the literal key value, which fails at call time rather than at load time.

Official sources

  1. eastreams/loong on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/eastreams-loong.svg)](https://hysenlabs.com/projects/eastreams-loong)