Skip to content

Commit fd72f26

Browse files
authored
Refactor database stats to return raw byte counts and CLI command grouping and support OpenClaw Plugins (#57)
<!-- AI-PR-DESCRIPTION-START --> ## PR Auto Describe ## Summary This PR adds official support for the OpenClaw agent framework, renames the deprecated `omni learn --status` flag to `--discover` across the codebase, improves command savings tracking, and updates release tooling to sync plugin versions. --- ## Key Changes - Official OpenClaw integration plugin suite - Breaking flag rename: `--status` → `--discover` for `omni learn` - Enhanced stats tracking with command grouping - Updated release scripts and documentation --- ## Detailed Breakdown - **OpenClaw Integration**: Added `integrations/openclaw/` with a full plugin setup: README guide, Node.js tool handlers for `omni_shell` (wraps `omni exec`) and `omni_rewind` (retrieves full archived logs), and a plugin manifest with configurable options. Updated `scripts/bump_version.sh` and `scripts/omni-release.sh` to sync the plugin's version with the core OMNI binary. - **Flag Rename**: Replaced all instances of `omni learn --status` with `--discover` across CLI code (`src/cli/learn.rs`), all documentation examples, checklists, and help text. - **Stats & Tracking Improvements**: - Updated SQLite store methods to track raw input/output bytes instead of precomputed reduction percentages for accurate command grouping - Added command grouping logic in `src/cli/stats.rs` to aggregate similar commands (e.g., `npm install` variants) - Fixed `src/hooks/post_tool.rs` to use cleaned command strings when recording distillation data - Updated test assertions in `tests/savings_assertions.rs` to match the new stats API schema - **Documentation Updates**: Added an OpenClaw integration link to the root README's user resources, updated the agent flowchart to include OpenClaw, and revised all `omni learn` examples in `docs/HOW_TO_USE.md`. --- ## Notes (Optional) The OpenClaw integration reduces terminal output token usage by up to 90% by filtering out noise, while preserving full access to raw logs via the `omni_rewind` tool when needed. --- ## Breaking Changes (If any) - The `omni learn --status` flag has been fully removed and replaced with `--discover`; existing scripts or automation using the old flag will fail until updated. _Last updated: 2026-04-12 14:21:53_ <!-- AI-PR-DESCRIPTION-END -->
2 parents cbe8398 + c479103 commit fd72f26

12 files changed

Lines changed: 267 additions & 45 deletions

File tree

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ AI agents like Claude are only as smart as the context you feed them. When you f
6666

6767
```mermaid
6868
flowchart TB
69-
Agent["Claude Code / MCP Agent"]
69+
Agent["Claude Code / OpenClaw / MCP Agent"]
7070
7171
subgraph Hooks["Native Hook Layer (Transparent)"]
7272
Pre["Pre-Hook\n(Rewriter)"]
@@ -151,6 +151,7 @@ You can easily create your own rules using simple TOML files.
151151

152152
**For Users:**
153153
- [The Ultimate Guide (HOW_TO_USE.md)](docs/HOW_TO_USE.md) — Everything you need: Installation, `omni learn`, Custom TOML Filters, and CLI Commands.
154+
- [OpenClaw Integration](integrations/openclaw/README.md) — How to use OMNI with the OpenClaw agent framework.
154155

155156
**For Developers & System Integrators:**
156157
- [Development Guide](docs/DEVELOPMENT.md) — How to build and contribute to the OMNI codebase.

docs/HOW_TO_USE.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ flowchart TD
7171
Work --> Learn
7272
7373
subgraph Learn [When Output Isn't Filtered Well]
74-
LearnStatus["omni learn --status"] --> DryRun["omni learn --dry-run"]
74+
LearnDiscover["omni learn --discover"] --> DryRun["omni learn --dry-run"]
7575
DryRun --> Apply["omni learn --apply"]
7676
end
7777
@@ -396,7 +396,7 @@ Whenever OMNI runs as a hook (e.g., inside Claude Code), it silently monitors fo
396396

397397
You can process this queue by discovering patterns first:
398398
```bash
399-
omni learn --status
399+
omni learn --discover
400400
```
401401

402402
Then preview or apply:
@@ -409,7 +409,7 @@ omni learn --dry-run
409409
If you have a log file or a command output that is very noisy, you can pipe it directly into OMNI to generate a filter:
410410

411411
```bash
412-
cat build.log | omni learn --status
412+
cat build.log | omni learn --discover
413413
```
414414

415415
### 3. Applying Learned Filters
@@ -710,7 +710,7 @@ expected = "2024-01-15 10:30:03 ERROR Connection timeout to redis-primary"
710710
omni learn --verify
711711

712712
# Discovery: search for patterns in a log file
713-
omni learn --status < output.log
713+
omni learn --discover < output.log
714714

715715
# Preview: show generated TOML
716716
omni learn --dry-run < output.log
@@ -953,7 +953,7 @@ omni session --transcript # View transcript of recent session
953953
Auto-generate TOML filters from passthrough output.
954954

955955
```bash
956-
omni learn --status # Discovery: Search for new noise patterns
956+
omni learn --discovery # Discovery: Search for new noise patterns
957957
omni learn --dry-run # Preview: Show suggested TOML
958958
omni learn --apply # Action: Commit to learned.toml
959959
omni learn --verify # Test: Run inline tests on all filters
@@ -1116,7 +1116,7 @@ omni doctor --fix # Self-repair
11161116

11171117
### Weekly / Ongoing
11181118
- [ ] Run `omni stats` to review savings
1119-
- [ ] Run `omni learn --status` to check for new noise patterns to filter
1119+
- [ ] Run `omni learn --discovery` to check for new noise patterns to filter
11201120
- [ ] Run `omni learn --dry-run` if there are patterns
11211121
- [ ] Run `omni learn --apply` if the dry-run looks good
11221122
- [ ] Run `omni learn --verify` after applying any filters

integrations/openclaw/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# OMNI Integration for OpenClaw
2+
3+
This plugin integrates **OMNI** into the **OpenClaw** agent framework, allowing OpenClaw agents to intelligently filter terminal output, reducing token consumption by up to 90% while improving context quality.
4+
5+
## Prerequisites
6+
7+
- **OMNI** must be installed and available in your PATH.
8+
- **OpenClaw** (Gateway) must be installed.
9+
10+
## Installation
11+
12+
1. Clone or copy the OMNI repository.
13+
2. Navigate to the OMNI directory.
14+
3. Install the plugin into OpenClaw:
15+
16+
```bash
17+
openclaw plugins install ./integrations/openclaw
18+
```
19+
20+
## Configuration (Optional)
21+
22+
**OMNI for OpenClaw is designed to be "Zero Config".** If `omni` is already in your `PATH`, it will work immediately after installation without any additional settings.
23+
24+
If you have a custom setup, you can modify your OpenClaw settings (`~/.openclaw/config.yaml`):
25+
26+
```yaml
27+
plugins:
28+
omni-signal-engine:
29+
omniPath: "/usr/local/bin/omni" # Optional: path to omni binary
30+
forceDistill: false # Optional: experimental override
31+
```
32+
33+
## Usage
34+
35+
Once installed, your OpenClaw agent will have access to two new tools:
36+
37+
### `omni_shell`
38+
Use this exactly like the standard `shell` or `bash` tool.
39+
- **Input**: `{ "command": "npm install" }`
40+
- **Behavior**: Runs the command via `omni exec`, filtering out noise and keeping only the signal (errors, summaries).
41+
42+
### `omni_rewind`
43+
If OMNI omits a large block of text and provides a hash (e.g., `[OMNI: 847 lines omitted — hash: a3f8c2d1]`), the agent can call `omni_rewind` with that hash to see the full output.
44+
- **Input**: `{ "hash": "a3f8c2d1" }`
45+
46+
## Monitoring Savings
47+
48+
You can track how many tokens and how much money the OpenClaw plugin is saving you by running the following command in your terminal:
49+
50+
```bash
51+
omni stats --today
52+
```
53+
54+
This will show a detailed breakdown of all commands processed for your OpenClaw session, including the signal reduction percentage.
55+
56+
## Benefits
57+
- **Cheaper Tasks**: Massive savings on API bills for long-running autonomous tasks.
58+
- **Higher Accuracy**: Agents focus on the real errors instead of being distracted by 10,000 lines of build logs.
59+
- **Zero Information Loss**: The agent can always "rewind" to see the full raw logs if needed.

integrations/openclaw/index.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
const { exec } = require('child_process');
2+
const util = require('util');
3+
const execPromise = util.promisify(exec);
4+
5+
/**
6+
* OMNI Plugin for OpenClaw
7+
*
8+
* Provides a highly-efficient shell tool that uses OMNI's
9+
* distillation engine to reduce token usage.
10+
*/
11+
module.exports = function(sdk) {
12+
if (!sdk) return;
13+
14+
const config = (typeof sdk.getConfig === 'function') ? sdk.getConfig() : {};
15+
const omniPath = config.omniPath || 'omni';
16+
17+
sdk.registerTool({
18+
id: "omni_shell",
19+
description: "Run a shell command with intelligent OMNI filtering. Use this for noisy commands (git, npm, cargo, docker) to save 80-90% of token costs.",
20+
schema: {
21+
type: "object",
22+
properties: {
23+
command: {
24+
type: "string",
25+
description: "The shell command to execute"
26+
}
27+
},
28+
required: ["command"]
29+
},
30+
handler: async ({ command }) => {
31+
try {
32+
// We wrap the command in `omni exec`
33+
// The -- ensures that omni doesn't parse command flags as its own
34+
const fullCommand = `${omniPath} exec -- ${command}`;
35+
36+
const { stdout, stderr } = await execPromise(fullCommand);
37+
38+
let result = stdout || "";
39+
if (stderr && stderr.trim()) {
40+
result += `\n[stderr]\n${stderr}`;
41+
}
42+
43+
return {
44+
content: result || "(No output from OMNI)",
45+
role: "tool"
46+
};
47+
} catch (error) {
48+
sdk.log(`OMNI Error: ${error.message}`, "error");
49+
return {
50+
content: `Error running OMNI: ${error.message}\n${error.stderr || ""}`,
51+
isError: true
52+
};
53+
}
54+
}
55+
});
56+
57+
// Optional: Provide a direct rewind tool
58+
sdk.registerTool({
59+
id: "omni_rewind",
60+
description: "Retrieve full archived output from OMNI if the distilled summary was insufficient.",
61+
schema: {
62+
type: "object",
63+
properties: {
64+
hash: {
65+
type: "string",
66+
description: "The 8-character hash provided in the OMNI summary"
67+
}
68+
},
69+
required: ["hash"]
70+
},
71+
handler: async ({ hash }) => {
72+
try {
73+
const { stdout } = await execPromise(`${omniPath} rewind ${hash}`);
74+
return {
75+
content: stdout || "No archive found for this hash.",
76+
role: "tool"
77+
};
78+
} catch (error) {
79+
return {
80+
content: `Failed to retrieve OMNI archive: ${error.message}`,
81+
isError: true
82+
};
83+
}
84+
}
85+
});
86+
87+
sdk.log("OMNI Signal Engine plugin loaded successfully.");
88+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"id": "omni-signal-engine",
3+
"name": "OMNI Signal Engine",
4+
"version": "0.5.6-rc1",
5+
"description": "Intelligent context filtering for OpenClaw using OMNI. Saves tokens by distilling shell output.",
6+
"author": "OMNI Team",
7+
"configSchema": {
8+
"type": "object",
9+
"properties": {
10+
"omniPath": {
11+
"type": "string",
12+
"description": "Path to the omni binary (defaults to 'omni' in PATH)",
13+
"default": "omni"
14+
},
15+
"forceDistill": {
16+
"type": "boolean",
17+
"description": "If true, overrides the default shell tool (experimental)",
18+
"default": false
19+
}
20+
}
21+
}
22+
}

scripts/bump_version.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,15 @@ rm -f Cargo.toml.bak
3131
# 3. Update Cargo.lock
3232
cargo check --quiet 2>/dev/null || true
3333

34-
# 4. Verify build
34+
# 4. Update openclaw plugin version
35+
sed -i.bak "s/^version = \".*\"/version = \"$NEW\"/" integrations/openclaw/openclaw.plugin.json
36+
rm -f integrations/openclaw/openclaw.plugin.json.bak
37+
38+
# 5. Verify build
3539
echo "Verifying build..."
3640
cargo build --quiet
3741

38-
# 5. Verify version output
42+
# 6. Verify version output
3943
ACTUAL=$(./target/debug/omni version 2>&1)
4044
if echo "$ACTUAL" | grep -q "$NEW"; then
4145
echo "✓ Version output: $ACTUAL"
@@ -45,7 +49,7 @@ else
4549
fi
4650

4751
# 6. Stage and commit
48-
git add Cargo.toml Cargo.lock
52+
git add Cargo.toml Cargo.lock integrations/openclaw/openclaw.plugin.json
4953
git commit -m "chore: bump version to $NEW"
5054

5155
echo ""

scripts/omni-release.sh

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,20 @@ if [ "$CARGO_VERSION" != "$VERSION" ]; then
3434
fi
3535
ok "Cargo.toml version: $CARGO_VERSION"
3636

37-
# 2. Git status check
37+
# 2. Verify version in openclaw.plugin.json
38+
OPENCLAW_VERSION=$(grep '^version' integrations/openclaw/openclaw.plugin.json | head -1 | sed 's/version = "\(.*\)"/\1/')
39+
if [ "$OPENCLAW_VERSION" != "$VERSION" ]; then
40+
fail "openclaw.plugin.json version ($OPENCLAW_VERSION) ≠ release version ($VERSION)\n Fix: edit openclaw.plugin.json version field, or run: ./scripts/bump_version.sh $VERSION"
41+
fi
42+
ok "openclaw.plugin.json version: $OPENCLAW_VERSION"
43+
44+
# 3. Git status check
3845
if ! git diff --quiet HEAD; then
3946
fail "Working directory is not clean. Commit or stash changes first."
4047
fi
4148
ok "Git working directory: clean"
4249

43-
# 3. Branch check
50+
# 4. Branch check
4451
BRANCH=$(git branch --show-current)
4552
if [ "$BRANCH" != "main" ] && [ "$BRANCH" != "homebrew_fix" ]; then
4653
warn "Not on main branch (on: $BRANCH). Continue? [y/N]"
@@ -49,7 +56,7 @@ if [ "$BRANCH" != "main" ] && [ "$BRANCH" != "homebrew_fix" ]; then
4956
fi
5057
ok "Branch: $BRANCH"
5158

52-
# 4. Tag check
59+
# 5. Tag check
5360
if git tag --list | grep -q "^${TAG}$"; then
5461
fail "Tag ${TAG} already exists"
5562
fi
@@ -60,21 +67,21 @@ ok "Tag ${TAG}: not yet created"
6067
echo ""
6168
info "Build validation"
6269

63-
# 5. cargo fmt check
70+
# 6. cargo fmt check
6471
cargo fmt --check || fail "cargo fmt check failed. Run: cargo fmt"
6572
ok "cargo fmt: clean"
6673

67-
# 6. cargo clippy
74+
# 7. cargo clippy
6875
echo " Running clippy..."
6976
cargo clippy --all-targets -- -D warnings > /tmp/omni-clippy 2>&1 || { cat /tmp/omni-clippy && fail "clippy warnings found"; }
7077
ok "cargo clippy: no warnings"
7178

72-
# 7. cargo test
79+
# 8. cargo test
7380
echo " Running tests..."
7481
cargo test --all > /tmp/omni-test 2>&1 || { tail -n 20 /tmp/omni-test && fail "tests failed"; }
7582
ok "cargo test: all pass"
7683

77-
# 8. Release build
84+
# 9. Release build
7885
echo " Building release..."
7986
cargo build --release > /tmp/omni-build 2>&1 || { tail -n 20 /tmp/omni-build && fail "release build failed"; }
8087
BINARY_SIZE=$(du -k target/release/omni | cut -f1)
@@ -83,7 +90,7 @@ if [ "$BINARY_SIZE" -gt 5120 ]; then
8390
warn "Binary size ${BINARY_SIZE}KB exceeds 5MB target"
8491
fi
8592

86-
# 9. Smoke test
93+
# 10. Smoke test
8794
if [ -x tests/smoke_test.sh ]; then
8895
echo " Running smoke tests..."
8996
bash tests/smoke_test.sh ./target/release/omni > /tmp/omni-smoke 2>&1 || { cat /tmp/omni-smoke && fail "smoke test failed"; }

src/cli/learn.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn print_help() {
1818
println!("\n{}", "FLAGS:".bold().bright_white());
1919
println!(
2020
" {: <12} Discover and view candidate patterns",
21-
"--status".cyan()
21+
"--discover".cyan()
2222
);
2323
println!(
2424
" {: <12} Automatically append new filters to config",
@@ -40,7 +40,7 @@ fn print_help() {
4040

4141
println!("\n{}", "EXAMPLES:".bold().bright_white());
4242
println!(
43-
" omni learn --status {}",
43+
" omni learn --discover {}",
4444
"# Search for new noise patterns".bright_black()
4545
);
4646
println!(
@@ -75,10 +75,10 @@ pub fn run_learn(args: &[String]) -> Result<()> {
7575
let dry_run = args.iter().any(|a| a == "--dry-run");
7676
let from_queue = args.iter().any(|a| a == "--from-queue");
7777
let verify = args.iter().any(|a| a == "--verify");
78-
let is_status = args.iter().any(|a| a == "--status");
78+
let is_discover = args.iter().any(|a| a == "--discover");
7979

8080
// If no flags, show help
81-
if !apply && !dry_run && !from_queue && !verify && !is_status {
81+
if !apply && !dry_run && !from_queue && !verify && !is_discover {
8282
print_help();
8383
return Ok(());
8484
}
@@ -117,7 +117,7 @@ pub fn run_learn(args: &[String]) -> Result<()> {
117117

118118
// In terminal mode, if an action is used without --from-queue, default to queue
119119
let mut use_queue = from_queue;
120-
let is_action = is_status || dry_run || apply;
120+
let is_action = is_discover || dry_run || apply;
121121
if is_action && !from_queue && io::stdin().is_terminal() {
122122
use_queue = true;
123123
}

0 commit comments

Comments
 (0)