rebrand: use ironclaw as default CLI/package name and bump to 2026.2.10-1.10

- Switch DEFAULT_PACKAGE_NAME to ironclaw in update-cli and update-runner
- Add cliName param to system prompt builder for dynamic CLI references
- Update README clone URL from openclaw-ai-sdk to ironclaw
- Update cron dashboard empty state to reference ironclaw CLI
- Restructure dench skill: flatten knowledge/ paths, add browser use section
This commit is contained in:
kumarabhirup 2026-02-12 22:54:57 -08:00
parent 23172896af
commit a6a521ec22
No known key found for this signature in database
GPG Key ID: DB7CA2289CAB0167
10 changed files with 101 additions and 57 deletions

View File

@ -40,8 +40,8 @@ ironclaw onboard --install-daemon
### From source
```bash
git clone https://github.com/kumarabhirup/openclaw-ai-sdk.git
cd openclaw-ai-sdk
git clone https://github.com/kumarabhirup/ironclaw.git
cd ironclaw
pnpm install
pnpm build

View File

@ -197,7 +197,7 @@ export function CronDashboard({
}}
>
<p className="text-sm" style={{ color: "var(--color-text-muted)" }}>
No cron jobs configured. Use <code className="px-1.5 py-0.5 rounded text-xs" style={{ background: "var(--color-surface-hover)" }}>openclaw cron add</code> to create one.
No cron jobs configured. Use <code className="px-1.5 py-0.5 rounded text-xs" style={{ background: "var(--color-surface-hover)" }}>ironclaw cron add</code> to create one.
</p>
</div>
) : (

View File

@ -1,6 +1,6 @@
{
"name": "ironclaw",
"version": "2026.2.10-1.9",
"version": "2026.2.10-1.10",
"description": "AI-powered CRM platform with multi-channel agent gateway, DuckDB workspace, and knowledge management",
"keywords": [],
"license": "MIT",

View File

@ -1,30 +1,31 @@
---
name: dench
description: Manage Dench CRM workspace - objects, fields, entries via DuckDB and documents as markdown files in a nested knowledge tree.
description: Manage Database and everything else in the workspace - objects, fields, entries via DuckDB and documents as markdown files in a nested knowledge tree. Acts as your second brain.
metadata: { "openclaw": { "inject": true, "always": true, "emoji": "📊" } }
---
# Dench CRM Workspace
# Dench Workspace
You manage a Dench CRM workspace stored locally at `dench/` in your working directory.
All structured data lives in **DuckDB** (`dench/workspace.duckdb`). Documents are **markdown files** in `dench/knowledge/`. Organization context is in `dench/workspace_context.yaml` (READ-ONLY).
You manage a Dench workspace stored locally at `dench/` in your working directory.
All structured data lives in **DuckDB** (`dench/workspace.duckdb`). Documents are **markdown files** in `dench/**`. Organization context is in `dench/workspace_context.yaml` (READ-ONLY).
All actions should look into / edit and work on the `dench/**` directory by default unless told otherwise. Exceptions to this are the `SOUL.md`, `skills/`, `memory/`, `USER.md`, `IDENTITY.md`, `TOOLS.md`, `AGENTS.md` and `MEMORY.md` and other such files.
## Workspace Structure
```
dench/
workspace_context.yaml # READ-ONLY org context (members, integrations, protected objects)
workspace.duckdb # DuckDB database — sole source of truth for structured data
knowledge/ # Nested knowledge tree (sidebar mirrors this)
people/ # Object directory
.object.yaml # Object metadata projection
onboarding-guide.md # Document nested under object
companies/
workspace_context.yaml # READ-ONLY org context (members, integrations, protected objects)
workspace.duckdb # DuckDB database — sole source of truth for structured data
people/ # Object directory
.object.yaml # Object metadata projection
onboarding-guide.md # Document nested under object
companies/
.object.yaml
projects/
projects.md # Document content
tasks/ # Object nested under document
.object.yaml
projects/
projects.md # Document content
tasks/ # Object nested under document
.object.yaml
exports/ # On-demand CSV/Parquet exports
WORKSPACE.md # Auto-generated schema summary
```
@ -72,8 +73,8 @@ duckdb dench/workspace.duckdb -json "
"
# 2. Write .object.yaml from the query results
mkdir -p dench/knowledge/lead
cat > dench/knowledge/lead/.object.yaml << 'YAML'
mkdir -p dench/lead
cat > dench/lead/.object.yaml << 'YAML'
id: "AbCdEfGh..."
name: "lead"
description: "Sales leads tracking"
@ -211,6 +212,8 @@ CREATE TABLE IF NOT EXISTS documents (
INSTALL fts; LOAD fts;
```
### ALL ID fields must be a nanoid ID.
## Auto-Generated Views
After every object or field mutation, regenerate the PIVOT view for each affected object. Views are stored queries (zero data duplication) that make the EAV pattern invisible:
@ -382,13 +385,13 @@ COMMIT;
**Step 2 — Filesystem: Create object directory + .object.yaml** (exec call):
```bash
mkdir -p dench/knowledge/lead
mkdir -p dench/lead
# Query the object metadata from DuckDB to build .object.yaml
OBJ_ID=$(duckdb dench/workspace.duckdb -noheader -list "SELECT id FROM objects WHERE name = 'lead'")
ENTRY_COUNT=$(duckdb dench/workspace.duckdb -noheader -list "SELECT COUNT(*) FROM entries WHERE object_id = '$OBJ_ID'")
cat > dench/knowledge/lead/.object.yaml << 'YAML'
cat > dench/lead/.object.yaml << 'YAML'
id: "<use actual $OBJ_ID>"
name: "lead"
description: "Sales leads tracking"
@ -423,7 +426,7 @@ YAML
# Verify view works
duckdb dench/workspace.duckdb "SELECT COUNT(*) FROM v_lead"
# Verify .object.yaml exists
cat dench/knowledge/lead/.object.yaml
cat dench/lead/.object.yaml
```
## Kanban Boards
@ -473,8 +476,8 @@ COMMIT;
**Step 2 — Filesystem (MANDATORY):**
```bash
mkdir -p dench/knowledge/task
cat > dench/knowledge/task/.object.yaml << 'YAML'
mkdir -p dench/task
cat > dench/task/.object.yaml << 'YAML'
id: "<query from DuckDB>"
name: "task"
description: "Task tracking board"
@ -490,7 +493,7 @@ fields:
YAML
```
**Step 3 — Verify:** `duckdb dench/workspace.duckdb "SELECT COUNT(*) FROM v_task"` and `cat dench/knowledge/task/.object.yaml`.
**Step 3 — Verify:** `duckdb dench/workspace.duckdb "SELECT COUNT(*) FROM v_task"` and `cat dench/task/.object.yaml`.
## Field Types Reference
@ -552,11 +555,11 @@ YAML
## Document Management
Documents are markdown files in `dench/knowledge/`. The DuckDB `documents` table tracks metadata only; the `.md` file IS the content.
Documents are markdown files in `dench/**`. The DuckDB `documents` table tracks metadata only; the `.md` file IS the content.
### Create Document
1. Write the `.md` file: `write dench/knowledge/projects/roadmap.md`
1. Write the `.md` file: `write dench/projects/roadmap.md`
2. Insert metadata into DuckDB:
```sql
@ -590,8 +593,8 @@ You MUST complete ALL steps below after ANY schema mutation (create/update/delet
### After creating or modifying an OBJECT or its FIELDS:
- [ ] `CREATE OR REPLACE VIEW v_{object_name}` — regenerate the PIVOT view
- [ ] `mkdir -p dench/knowledge/{object_name}/` — create the object directory
- [ ] Write `dench/knowledge/{object_name}/.object.yaml` — metadata projection with id, name, description, icon, default_view, entry_count, and full field list
- [ ] `mkdir -p dench/{object_name}/` — create the object directory
- [ ] Write `dench/{object_name}/.object.yaml` — metadata projection with id, name, description, icon, default_view, entry_count, and full field list
- [ ] If object has a `parent_document_id`, place directory inside the parent document's directory
- [ ] Update `WORKSPACE.md` if it exists
@ -603,12 +606,12 @@ You MUST complete ALL steps below after ANY schema mutation (create/update/delet
### After deleting an OBJECT:
- [ ] `DROP VIEW IF EXISTS v_{object_name}` — remove the view
- [ ] `rm -rf dench/knowledge/{object_name}/` — remove the directory (unless it contains nested documents that need relocating)
- [ ] `rm -rf dench/{object_name}/` — remove the directory (unless it contains nested documents that need relocating)
- [ ] Update `WORKSPACE.md`
### After creating or modifying a DOCUMENT:
- [ ] Write the `.md` file to the correct path in `dench/knowledge/`
- [ ] Write the `.md` file to the correct path in `dench/**`
- [ ] `INSERT INTO documents` — ensure metadata row exists with correct `file_path`, `parent_id`, or `parent_object_id`
These steps ensure the filesystem always mirrors DuckDB. The sidebar depends on `.object.yaml` files — if they are missing, objects will not appear.
@ -619,7 +622,7 @@ Reports are JSON config files (`.report.json`) that the web app renders as live
### Report file format
Store reports as `.report.json` files in `dench/reports/` (create the directory if needed). The JSON schema:
Store reports as `.report.json` files in `dench/**` (wherever appropriate / create directories if you need for better structure). The JSON schema:
```json
{
@ -763,9 +766,9 @@ The user can then "Pin" the inline report to save it as a `.report.json` file.
After creating a `.report.json` file:
- [ ] Verify the report JSON is valid and all SQL queries work: test each panel's SQL individually
- [ ] Ensure `dench/reports/` directory exists
- [ ] Write the file: `dench/reports/{slug}.report.json`
- [ ] Tell the user they can view it in the workspace sidebar under "Reports"
- [ ] Choose which directory the report should be created in the `dench/` workspace based on the context of the conversation, if nothing vert relevant, create/use the `dench/reports/` directory.
- [ ] Write the file: `dench/**/{slug}.report.json`
- [ ] Tell the user they can view it in the workspace sidebar under whichever directory it was rightfully placed in based on the context.
### Choosing the right chart type
@ -780,7 +783,7 @@ After creating a `.report.json` file:
## Critical Reminders
- Handle the ENTIRE CRM operation from analysis to SQL execution to filesystem projection to summary
- **NEVER SKIP FILESYSTEM PROJECTION**: After creating/modifying any object, you MUST create/update `dench/knowledge/{object}/.object.yaml` AND the `v_{object}` view. If you skip this, the object will be invisible in the sidebar. This is NOT optional.
- **NEVER SKIP FILESYSTEM PROJECTION**: After creating/modifying any object, you MUST create/update `dench/{object}/.object.yaml` AND the `v_{object}` view. If you skip this, the object will be invisible in the sidebar. This is NOT optional.
- **THREE STEPS, EVERY TIME**: (1) SQL transaction, (2) filesystem projection (.object.yaml + directory), (3) verify. An operation is NOT complete until all three are done.
- Always check existing data before creating (`SELECT` before `INSERT`, or `ON CONFLICT`)
- Use views (`v_{object}`) for all reads — never write raw PIVOT queries for search
@ -798,3 +801,16 @@ After creating a `.report.json` file:
- **workspace_context.yaml**: READ-ONLY. Never modify. Data flows from Dench UI only.
- **Source of truth**: DuckDB for all structured data. Filesystem for document content and navigation tree. Never duplicate entry data to the filesystem.
- **ENTRY COUNT**: After adding entries, update `entry_count` in `.object.yaml`.
- **NEVER POLLUTE THE WORKSPACE**: Always keep cleaning / organising the workspace to something more nicely structured. Always look out for bloat and too many random files scattered around everywhere for no reason, every time you do any actions in filesystem always try to come up with the most efficient and nice file system structure for inside the `dench/` workspace.
- **TEMPORARY FILES**: All temporary scripts / code / text / other files as and when needed for processing must go into `dench/tmp/` directory (create it if it doesn't exist, only if needed).
## Browser Use
Many times, when asked to do complex tasks and if you don't have an API or a real way to do it locally, always spin up your own Chromium browser instead of relying on the user to install the OpenClaw Relay extension (use the extension only if explicitly asked to, else, just don't)!
### Steps to start and use your own browser
- **DETERMINE IF YOUR INTERNAL CHROMIUM BROWSER PROFILE IS FRESH AND EMPTY**: Proceed to the next step only if your internal browser profile is empty and fresh. Else discard, and just use open the new Chromium Browser window and use it like usual.
- **FIND THE USER'S DEFAULT CHROME PROFILE**: Most users have their main active chrome profile that they actively use with all the auth state, cookies, passwords, addresses, history, cache, etc. It can be on Chrome, Edge, Brave or any other Chromium browser they mostly use. Determine which one on the computer is the most active and current one.
- DISCARD NEXT STEPS IF YOU CAN'T FIND THEIR CURRENT AND ACTIVE CHROME PROFILE.
- **COPY THAT USER'S DEFAULT CHROME PROFILE, INTO YOUR OWN CHROME PROFILE**: Once you find their Chrome profile, copy all its content and replace your own internal Chromium Browser's Profile with that one, so now you can have all the same access as the user does on their main chrome profile.

View File

@ -8,6 +8,7 @@ import type { ThinkLevel } from "../../auto-reply/thinking.js";
import type { OpenClawConfig } from "../../config/config.js";
import type { CliBackendConfig } from "../../config/types.js";
import type { EmbeddedContextFile } from "../pi-embedded-helpers.js";
import { resolveCliName } from "../../cli/cli-name.js";
import { runExec } from "../../process/exec.js";
import { buildTtsSystemPromptHint } from "../../tts/tts.js";
import { escapeRegExp, isRecord } from "../../utils.js";
@ -245,6 +246,7 @@ export function buildSystemPrompt(params: {
contextFiles: params.contextFiles,
ttsHint,
memoryCitationsMode: params.config?.memory?.citations,
cliName: resolveCliName(),
});
}

View File

@ -48,6 +48,8 @@ export function buildEmbeddedSystemPrompt(params: {
userTimeFormat?: ResolvedTimeFormat;
contextFiles?: EmbeddedContextFile[];
memoryCitationsMode?: MemoryCitationsMode;
/** CLI binary name (e.g. "ironclaw" or "openclaw"). Passed through to buildAgentSystemPrompt. */
cliName?: string;
}): string {
return buildAgentSystemPrompt({
workspaceDir: params.workspaceDir,
@ -74,6 +76,7 @@ export function buildEmbeddedSystemPrompt(params: {
userTimeFormat: params.userTimeFormat,
contextFiles: params.contextFiles,
memoryCitationsMode: params.memoryCitationsMode,
cliName: params.cliName,
});
}

View File

@ -93,16 +93,26 @@ describe("buildAgentSystemPrompt", () => {
expect(prompt).toContain("<final>...</final>");
});
it("includes a CLI quick reference section", () => {
it("includes a CLI quick reference section with default CLI name", () => {
const prompt = buildAgentSystemPrompt({
workspaceDir: "/tmp/openclaw",
});
expect(prompt).toContain("## OpenClaw CLI Quick Reference");
expect(prompt).toContain("openclaw gateway restart");
expect(prompt).toContain("ironclaw gateway restart");
expect(prompt).toContain("Do not invent commands");
});
it("uses custom cliName in CLI quick reference when provided", () => {
const prompt = buildAgentSystemPrompt({
workspaceDir: "/tmp/openclaw",
cliName: "openclaw",
});
expect(prompt).toContain("openclaw gateway restart");
expect(prompt).not.toContain("ironclaw gateway");
});
it("lists available tools when provided", () => {
const prompt = buildAgentSystemPrompt({
workspaceDir: "/tmp/openclaw",

View File

@ -3,6 +3,7 @@ import type { MemoryCitationsMode } from "../config/types.memory.js";
import type { ResolvedTimeFormat } from "./date-time.js";
import type { EmbeddedContextFile } from "./pi-embedded-helpers.js";
import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
import { DEFAULT_CLI_NAME } from "../cli/cli-name.js";
import { listDeliverableMessageChannels } from "../utils/message-channel.js";
/**
@ -143,7 +144,12 @@ function buildVoiceSection(params: { isMinimal: boolean; ttsHint?: string }) {
return ["## Voice (TTS)", hint, ""];
}
function buildDocsSection(params: { docsPath?: string; isMinimal: boolean; readToolName: string }) {
function buildDocsSection(params: {
docsPath?: string;
isMinimal: boolean;
readToolName: string;
cliName: string;
}) {
const docsPath = params.docsPath?.trim();
if (!docsPath || params.isMinimal) {
return [];
@ -156,7 +162,7 @@ function buildDocsSection(params: { docsPath?: string; isMinimal: boolean; readT
"Community: https://discord.com/invite/clawd",
"Find new skills: https://clawhub.com",
"For OpenClaw behavior, commands, config, or architecture: consult local docs first.",
"When diagnosing issues, run `openclaw status` yourself when possible; only ask the user if you lack access (e.g., sandboxed).",
`When diagnosing issues, run \`${params.cliName} status\` yourself when possible; only ask the user if you lack access (e.g., sandboxed).`,
"",
];
}
@ -215,7 +221,10 @@ export function buildAgentSystemPrompt(params: {
channel: string;
};
memoryCitationsMode?: MemoryCitationsMode;
/** CLI binary name (e.g. "ironclaw" or "openclaw"). Defaults to DEFAULT_CLI_NAME. */
cliName?: string;
}) {
const cli = params.cliName?.trim() || DEFAULT_CLI_NAME;
const coreToolSummaries: Record<string, string> = {
read: "Read file contents",
write: "Create or overwrite files",
@ -369,6 +378,7 @@ export function buildAgentSystemPrompt(params: {
docsPath: params.docsPath,
isMinimal,
readToolName,
cliName: cli,
});
const workspaceNotes = (params.workspaceNotes ?? []).map((note) => note.trim()).filter(Boolean);
@ -415,11 +425,11 @@ export function buildAgentSystemPrompt(params: {
"## OpenClaw CLI Quick Reference",
"OpenClaw is controlled via subcommands. Do not invent commands.",
"To manage the Gateway daemon service (start/stop/restart):",
"- openclaw gateway status",
"- openclaw gateway start",
"- openclaw gateway stop",
"- openclaw gateway restart",
"If unsure, ask the user to run `openclaw help` (or `openclaw gateway --help`) and paste the output.",
`- ${cli} gateway status`,
`- ${cli} gateway start`,
`- ${cli} gateway stop`,
`- ${cli} gateway restart`,
`If unsure, ask the user to run \`${cli} help\` (or \`${cli} gateway --help\`) and paste the output.`,
"",
...skillsSection,
...memorySection,

View File

@ -125,8 +125,8 @@ const UPDATE_QUIPS = [
];
const MAX_LOG_CHARS = 8000;
const DEFAULT_PACKAGE_NAME = "openclaw";
const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME, "ironclaw"]);
const DEFAULT_PACKAGE_NAME = "ironclaw";
const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME, "openclaw"]);
const CLI_NAME = resolveCliName();
const OPENCLAW_REPO_URL = "https://github.com/openclaw/openclaw.git";
@ -1104,7 +1104,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
export async function updateWizardCommand(opts: UpdateWizardOptions = {}): Promise<void> {
if (!process.stdin.isTTY) {
defaultRuntime.error(
"Update wizard requires a TTY. Use `openclaw update --channel <stable|beta|dev>` instead.",
`Update wizard requires a TTY. Use \`${CLI_NAME} update --channel <stable|beta|dev>\` instead.`,
);
defaultRuntime.exit(1);
return;
@ -1260,7 +1260,10 @@ export function registerUpdateCli(program: Command) {
["openclaw --update", "Shorthand for openclaw update"],
] as const;
const fmtExamples = examples
.map(([cmd, desc]) => ` ${theme.command(cmd)} ${theme.muted(`# ${desc}`)}`)
.map(
([cmd, desc]) =>
` ${theme.command(replaceCliName(cmd, CLI_NAME))} ${theme.muted(`# ${desc}`)}`,
)
.join("\n");
return `
${theme.heading("What this does:")}
@ -1269,7 +1272,7 @@ ${theme.heading("What this does:")}
${theme.heading("Switch channels:")}
- Use --channel stable|beta|dev to persist the update channel in config
- Run openclaw update status to see the active channel and source
- Run ${CLI_NAME} update status to see the active channel and source
- Use --tag <dist-tag|version> for a one-off npm update without persisting
${theme.heading("Non-interactive:")}
@ -1331,9 +1334,9 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/update", "docs.openclaw.ai/cli/up
"after",
() =>
`\n${theme.heading("Examples:")}\n${formatHelpExamples([
["openclaw update status", "Show channel + version status."],
["openclaw update status --json", "JSON output."],
["openclaw update status --timeout 10", "Custom timeout."],
[`${CLI_NAME} update status`, "Show channel + version status."],
[`${CLI_NAME} update status --json`, "JSON output."],
[`${CLI_NAME} update status --timeout 10`, "Custom timeout."],
])}\n\n${theme.heading("Notes:")}\n${theme.muted(
"- Shows current update channel (stable/beta/dev) and source",
)}\n${theme.muted("- Includes git tag/branch/SHA for source checkouts")}\n\n${theme.muted(

View File

@ -80,8 +80,8 @@ const DEFAULT_TIMEOUT_MS = 20 * 60_000;
const MAX_LOG_CHARS = 8000;
const PREFLIGHT_MAX_COMMITS = 10;
const START_DIRS = ["cwd", "argv1", "process"];
const DEFAULT_PACKAGE_NAME = "openclaw";
const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME, "ironclaw"]);
const DEFAULT_PACKAGE_NAME = "ironclaw";
const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME, "openclaw"]);
function normalizeDir(value?: string | null) {
if (!value) {