Skip to content

Commit 70b674c

Browse files
committed
Merge branch 'feat/clawxtool'
2 parents 51d8912 + f6abb71 commit 70b674c

41 files changed

Lines changed: 4217 additions & 9 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export interface SkillDiscoveryConfig {
3030
logLevel?: "debug" | "info" | "warn" | "error" | "silent";
3131
}
3232

33-
const CONFIG_PATH = path.join(os.homedir(), ".openclaw", "skill-discovery.json");
33+
const CONFIG_PATH = path.join(os.homedir(), ".openclaw", "clawxskill.json");
3434

3535
const CONFIG_TEMPLATE = `{
3636
// Master switch — set to false to disable the entire extension
@@ -100,7 +100,7 @@ function createLogger(tag: string) {
100100
let logStream: fs.WriteStream | null = null;
101101
try {
102102
fs.mkdirSync(logDir, { recursive: true });
103-
logStream = fs.createWriteStream(path.join(logDir, "skill-discovery.log"), { flags: "a" });
103+
logStream = fs.createWriteStream(path.join(logDir, "clawxskill.log"), { flags: "a" });
104104
} catch {
105105
// Filesystem error — console only
106106
}
@@ -127,7 +127,7 @@ function createLogger(tag: string) {
127127
};
128128
}
129129

130-
const log = createLogger("skill-discovery");
130+
const log = createLogger("clawxskill");
131131

132132
// ---- Name normalization ----
133133
// pi.getCommands() returns "skill:think-base", watcher returns "think-base".
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
2-
* Standalone test for skill-discovery extension core logic.
2+
* Standalone test for clawxskill extension core logic.
33
*
4-
* Run: npx tsx .pi/extensions/skill-discovery/test.ts
4+
* Run: npx tsx .pi/extensions/clawxskill/test.ts
55
*/
66
import { InvertedIndex, tokenize } from "./engines/inverted-index.js";
77
import { SkillBackup } from "./skill-backup.js";

README.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Edge-Cloud Collaborative AI Agent
1919

2020
**What's New** 🔥
2121

22+
- **[2026.04.03]** 🚀 Three Claude Code-liked features released: 🔧 [ClawXTool](./extensions/clawxtool/) launches an 8-in-1 tool suite (including security analysis, secret scanning, git worktrees, etc.), 🔍 [ClawXSkill](./extensions/clawxskill/) releases an intelligent discovery engine (supporting skill search and model judge), and 🧠 [ClawXMemory](./extensions/openbmb-clawxmemory/) v0.1.5 refactors the retrieval loop and improves the dream-review mechanism.
2223
- **[2026.04.02]** 🚀 Released three Claude Code-liked features optimized for OpenClaw — 🤖 [ClawXKairos](./extensions/clawxkairos/) (Self-Driven Agent Loop), 🛡️ [ClawXGovernor](./extensions/clawxgovernor/) (Tool Governance), and 📦 [ClawXSandbox](./extensions/ClawXSandbox/) (Claude Code-Style Sandbox)
2324
- **[2026.04.01]** 🎉 EdgeClaw 2.0 is officially open-sourced, featuring a brand-new memory engine and cost-saving router — bringing the Claude Code experience to OpenClaw!
2425
- **[2026.04.01]** 🎉 [ClawXMemory](https://github.com/OpenBMB/ClawXMemory) released — inspired by Claude Code's memory mechanism, it delivers a smoother experience for OpenClaw scenarios with multi-layered structured long-term memory and proactive reasoning!
@@ -47,6 +48,9 @@ EdgeClaw is an **Edge-Cloud Collaborative AI Agent** jointly developed by [THUNL
4748
| Tool risk governance & audit ||| **** |
4849
| Self-driven agent loop ||| **** |
4950
| Sandboxed execution ||| **** |
51+
| Intelligent skill discovery ||| **** |
52+
| Built-in security tool suite ||| **** |
53+
| Virtual pet companion ||| **** |
5054
| Visual Dashboard ||| **** |
5155

5256
### ✨ Highlights at a Glance
@@ -56,10 +60,13 @@ EdgeClaw is an **Edge-Cloud Collaborative AI Agent** jointly developed by [THUNL
5660
- **🤖 Self-Driven Loop**[ClawXKairos](./extensions/clawxkairos/): Tick scheduling + Sleep tool + background command automation + async sub-agents, enabling the agent to work autonomously and continuously
5761
- **🛡️ Tool Governance**[ClawXGovernor](./extensions/clawxgovernor/): Three hook middlewares — context tail-window trimming, tool call risk interception & audit, session note incremental append. Deeply optimized for OpenClaw scenarios, **saving 85% tokens over 30 rounds of calls**
5862
- **📦 Sandbox Execution**[ClawXSandbox](./extensions/ClawXSandbox/): Fully isolated local execution environment based on system-level sandboxing (bwrap / sandbox-exec). Focused on being **lightweight, fast, and zero-dependency**, completely eliminating all Docker overhead.
63+
- **🔧 Unified Tool Suite**[ClawXTool](./extensions/clawxtool/): 8-in-1 plugin providing 13 tools, covering **security audit** (bash security analysis, secret scanning), **workflow** (git worktree management, structured task tracking), **development assistance** (cron parsing, notebook editing), and **agent interaction** (memory age annotations, interactive user questions).
64+
- **🔍 Skill Discovery**[ClawXSkill](./extensions/clawxskill/): Automatically discovers and indexes agent skills across the workspace using BM25 keyword search, optional embedding-based semantic search, and LLM model judge for intelligent skill matching.
65+
- **🧠 Memory Engine**[ClawXMemory](./extensions/openbmb-clawxmemory/): A structured long-term memory engine built for OpenClaw. Building on the ideas behind Claude Code's memory mechanism, it further introduces multi-layered structured memory and model-driven memory retrieval. *(v0.1.5)*
66+
- **🐾 Virtual Pet Companion**[ClawXBuddy](./extensions/clawxbuddy/): An adorable ASCII virtual pet companion with idle animations, rarity traits, and interactive commands to keep you company.
5967

6068
**🔥 Other Core Features**
6169

62-
- **🧠 Memory Engine**[ClawXMemory](https://github.com/OpenBMB/ClawXMemory): A structured long-term memory engine built for OpenClaw. Building on the ideas behind Claude Code's memory mechanism, it further introduces multi-layered structured memory and model-driven memory retrieval.
6370
- **💰 Cost-Saving Router**[ClawXRouter](https://github.com/openbmb/clawxrouter): LLM-as-Judge automatically determines complexity, routing 60–80% of requests to cheaper models. Real-world PinchBench testing shows **58% cost savings** with scores **6.3% higher**.
6471
- **🔒 Three-Tier Privacy** — S1 direct cloud / S2 desensitized forwarding / S3 fully local processing — sensitive data never leaves the device.
6572
- **🚀 Zero Configuration**`pnpm build && node openclaw.mjs gateway run`, auto-generates config on first launch, just fill in your API Key.
@@ -423,6 +430,30 @@ EdgeClaw/
423430
│ │ ├── fs-bridge.ts # File system bridge
424431
│ │ └── config.ts # Sandbox configuration
425432
│ │
433+
│ ├── clawxtool/ # [Built-in] ClawXTool unified tool suite (8-in-1)
434+
│ │ ├── index.ts # Unified entry (13 tools + hooks)
435+
│ │ └── src/ # Tool logic modules
436+
│ │ ├── cron-parser.ts # Cron expression parsing
437+
│ │ ├── classifier.ts # Bash command security classification
438+
│ │ ├── secret-patterns.ts # Secret/key detection patterns
439+
│ │ ├── notebook.ts # Jupyter notebook read/edit
440+
│ │ ├── worktree.ts # Git worktree management
441+
│ │ ├── store.ts # Task persistence store
442+
│ │ ├── annotate.ts # Memory age freshness labels
443+
│ │ └── question-tool.ts # Structured multi-choice questions
444+
│ │
445+
│ ├── clawxskill/ # [Built-in] ClawXSkill intelligent skill discovery
446+
│ │ ├── index.ts # Plugin entry point
447+
│ │ ├── engines/
448+
│ │ │ ├── inverted-index.ts # BM25 keyword search engine
449+
│ │ │ ├── embedding-search.ts # Semantic embedding search
450+
│ │ │ └── model-judge.ts # LLM-based skill relevance judge
451+
│ │ ├── watcher.ts # File system skill watcher
452+
│ │ └── skill-backup.ts # Skill index backup/restore
453+
│ │
454+
│ ├── clawxbuddy/ # [Built-in] ClawXBuddy virtual pet companion
455+
│ │ └── index.ts # Plugin entry point (ASCII sprites, idle animations)
456+
│ │
426457
│ ├── guardclaw/ # [Optional] Privacy guard (excluded from build by default)
427458
│ │
428459
│ └── clawxgovernor/ # [Built-in] ClawXGovernor tool governance
@@ -483,6 +514,9 @@ If this project is helpful to your research or work, please give us a ⭐!
483514
- [ClawXGovernor](./extensions/clawxgovernor/) — Tool governance (context trimming + tool call interception & audit + session notes), EdgeClaw built-in extension
484515
- [ClawXKairos](./extensions/clawxkairos/) — Self-driven agent loop (tick scheduling + sleep + background commands + async sub-agents)
485516
- [ClawXSandbox](./extensions/ClawXSandbox/) — Lightweight, zero-dependency isolated execution environment based on system-level sandboxing (bwrap / sandbox-exec)
517+
- [ClawXTool](./extensions/clawxtool/) — Unified 8-in-1 tool suite (cron, bash security, secret scanning, notebooks, git worktrees, tasks, memory age, user questions)
518+
- [ClawXSkill](./extensions/clawxskill/) — Intelligent skill discovery with BM25 keyword search, embedding-based semantic search, and LLM model judge
519+
- [ClawXBuddy](./extensions/clawxbuddy/) — Virtual pet companion with ASCII sprites, idle animations, and rarity traits
486520

487521
### License
488522

extensions/clawxbuddy/api.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export {
2+
definePluginEntry,
3+
type OpenClawPluginApi,
4+
type PluginCommandContext,
5+
type OpenClawPluginCommandDefinition,
6+
} from "openclaw/plugin-sdk/plugin-entry";
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env npx tsx
2+
/**
3+
* Gallery: shows companions for multiple seeds.
4+
* Run: npx tsx extensions/clawxbuddy/demo-gallery.ts
5+
*/
6+
import { roll } from "./src/core/companion.js";
7+
import { renderFace, renderSprite } from "./src/core/sprites.js";
8+
import { RARITY_STARS } from "./src/core/types.js";
9+
10+
const seeds = [
11+
"alice",
12+
"bob",
13+
"miwi",
14+
"dragon-fan",
15+
"lucky7",
16+
"edgeclaw",
17+
"test123",
18+
"hello-world",
19+
];
20+
21+
for (const seed of seeds) {
22+
const { bones } = roll(seed);
23+
const sprite = renderSprite(bones, 0);
24+
const face = renderFace(bones);
25+
const stars = RARITY_STARS[bones.rarity];
26+
const hatInfo = bones.hat !== "none" ? ` hat:${bones.hat}` : "";
27+
const shinyInfo = bones.shiny ? " ✨SHINY✨" : "";
28+
29+
console.log(` ┌─ ${seed} ${"─".repeat(Math.max(0, 30 - seed.length))}┐`);
30+
for (const line of sprite) {
31+
console.log(` │ ${line} │`);
32+
}
33+
console.log(` │ ${face} ${bones.species} ${bones.rarity} ${stars}${hatInfo}${shinyInfo}`);
34+
console.log(` └${"─".repeat(34)}┘`);
35+
console.log();
36+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env npx tsx
2+
/**
3+
* Quick demo: renders a random buddy companion in the terminal.
4+
* Run: npx tsx extensions/clawxbuddy/demo.ts
5+
* or: npx tsx extensions/clawxbuddy/demo.ts <seed>
6+
*/
7+
import { roll, rollWithSeed } from "./src/core/companion.js";
8+
import { renderFace, renderSprite, spriteFrameCount } from "./src/core/sprites.js";
9+
import { RARITY_STARS, STAT_NAMES } from "./src/core/types.js";
10+
11+
const seed = process.argv[2] || `demo-${Date.now()}`;
12+
const { bones, inspirationSeed } = seed.startsWith("demo-") ? rollWithSeed(seed) : roll(seed);
13+
14+
const DEFAULT_NAMES = [
15+
"Pip",
16+
"Mochi",
17+
"Bloop",
18+
"Nyx",
19+
"Quill",
20+
"Dusk",
21+
"Sprout",
22+
"Fern",
23+
"Zap",
24+
"Twig",
25+
];
26+
const name = DEFAULT_NAMES[inspirationSeed % DEFAULT_NAMES.length]!;
27+
28+
console.log();
29+
console.log(" 🥚 *crack* ... *crack crack* ...");
30+
console.log();
31+
32+
// Show all 3 animation frames
33+
const frameCount = spriteFrameCount(bones.species);
34+
for (let f = 0; f < frameCount; f++) {
35+
const sprite = renderSprite(bones, f);
36+
if (f === 0) {
37+
console.log(" Frame 0 (idle):");
38+
} else {
39+
console.log(` Frame ${f} (fidget):`);
40+
}
41+
for (const line of sprite) {
42+
console.log(` ${line}`);
43+
}
44+
console.log();
45+
}
46+
47+
console.log(` Name: ${name}`);
48+
console.log(` Species: ${bones.species}`);
49+
console.log(` Rarity: ${bones.rarity} ${RARITY_STARS[bones.rarity]}`);
50+
console.log(` Eyes: ${bones.eye}`);
51+
console.log(` Hat: ${bones.hat}`);
52+
console.log(` Shiny: ${bones.shiny ? "✨ YES ✨" : "no"}`);
53+
console.log(` Face: ${renderFace(bones)}`);
54+
console.log();
55+
console.log(" Stats:");
56+
for (const s of STAT_NAMES) {
57+
const val = bones.stats[s];
58+
const bar = "█".repeat(Math.floor(val / 10)) + "░".repeat(10 - Math.floor(val / 10));
59+
console.log(` ${s.padEnd(10)} ${bar} ${val}`);
60+
}
61+
console.log();
62+
63+
// Animated idle demo
64+
console.log(" --- Idle animation (press Ctrl+C to stop) ---");
65+
console.log();
66+
67+
const IDLE_SEQUENCE = [
68+
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
69+
0, 0, 1, 0, 0, 0, 0,
70+
];
71+
72+
let idx = 0;
73+
const spriteHeight = renderSprite(bones, 0).length + 2; // +2 for name line + blank
74+
75+
function renderFrame() {
76+
const frame = IDLE_SEQUENCE[idx % IDLE_SEQUENCE.length]!;
77+
const sprite = renderSprite(bones, frame);
78+
79+
// Move cursor up to overwrite previous frame
80+
if (idx > 0) {
81+
process.stdout.write(`\x1b[${spriteHeight}A`);
82+
}
83+
84+
for (const line of sprite) {
85+
process.stdout.write(` ${line}\n`);
86+
}
87+
const label = bones.shiny
88+
? ` ✨ ${name} ${RARITY_STARS[bones.rarity]} ✨`
89+
: ` ${name} ${RARITY_STARS[bones.rarity]}`;
90+
process.stdout.write(`${label}\n`);
91+
process.stdout.write("\n");
92+
93+
idx++;
94+
}
95+
96+
renderFrame();
97+
const timer = setInterval(renderFrame, 500);
98+
99+
process.on("SIGINT", () => {
100+
clearInterval(timer);
101+
console.log("\n Bye bye! 👋\n");
102+
process.exit(0);
103+
});

0 commit comments

Comments
 (0)