DenchClaw Context API: App-Workspace Integration
How DenchClaw's Context API lets custom apps access workspace metadata, current user context, and active CRM object information.
DenchClaw Context API: App-Workspace Integration
DenchClaw's Context API (dench.context) gives custom Dench Apps access to their surrounding workspace environment — who's using the app, what object is currently open, what view is active, what theme is applied, and other workspace-level context that makes apps feel deeply integrated rather than isolated.
The Context API is the difference between a generic web app that happens to run in DenchClaw and a native Dench App that knows exactly where it is and adapts accordingly.
The Context API Overview#
// Get the full current context
const context = await dench.context.get();
/*
Returns:
{
user: {
id: "user-abc",
name: "Kumar",
email: "kumar@dench.com",
timezone: "America/Los_Angeles"
},
workspace: {
name: "Main Workspace",
version: "1.2.0",
rootPath: "/Users/kumareth/.openclaw-dench/workspace"
},
theme: {
mode: "dark",
accent: "#6366f1",
background: "#0f0f0f",
surface: "#1a1a1a",
text: "#e8e8e8"
},
currentObject: {
name: "deals",
label: "Deals",
icon: "trending-up",
currentView: "Pipeline Overview"
},
selectedEntries: ["abc-123", "def-456"],
app: {
slug: "my-pipeline-app",
name: "Pipeline Dashboard",
version: "1.0.0"
}
}
*/User Context#
Access information about the current user:
const { user } = await dench.context.get();
console.log(user.name); // "Kumar"
console.log(user.timezone); // "America/Los_Angeles"
// Format dates in the user's timezone
const now = new Date();
const localTime = now.toLocaleString('en-US', {
timeZone: user.timezone
});In a multi-user workspace, user context tells you which team member is viewing your app — useful for user-specific preferences and personalized views.
Workspace Context#
Access workspace metadata:
const { workspace } = await dench.context.get();
console.log(workspace.name); // "Main Workspace"
console.log(workspace.rootPath); // "/Users/kumareth/.openclaw-dench/workspace"
console.log(workspace.version); // "1.2.0"
// Use rootPath to reference workspace files
const customCSS = `${workspace.rootPath}/custom.css`;Theme Context#
Adapt your app to the current theme:
const { theme } = await dench.context.get();
// Apply theme to your app
document.documentElement.style.setProperty('--accent', theme.accent);
document.documentElement.style.setProperty('--background', theme.background);
document.documentElement.style.setProperty('--text', theme.text);
if (theme.mode === 'dark') {
document.body.classList.add('dark-mode');
} else {
document.body.classList.remove('dark-mode');
}Listen for theme changes:
dench.context.onThemeChange((newTheme) => {
applyTheme(newTheme);
});This listener fires when the user toggles dark mode or changes accent color — your app updates in real time.
Active Object Context#
Know which CRM object the user is currently viewing:
const { currentObject } = await dench.context.get();
if (currentObject?.name === "deals") {
// User is viewing the deals object
// Show deal-specific tools
showDealAnalysis();
} else if (currentObject?.name === "people") {
// User is viewing contacts
showContactInsights();
}This enables contextual apps that automatically adapt to what the user is doing:
// A "Smart Assistant" app that changes its behavior based on context
const { currentObject } = await dench.context.get();
const systemPrompt = currentObject
? `You are assisting with the ${currentObject.label} object. Help the user analyze and manage their ${currentObject.label.toLowerCase()}.`
: `You are a general workspace assistant.`;Selected Entries Context#
Access which CRM entries the user has currently selected:
const { selectedEntries } = await dench.context.get();
// Returns array of entry IDs currently selected in the CRM view
if (selectedEntries.length > 0) {
// Load the selected entries' data
const entries = await dench.db.query(`
SELECT * FROM v_deals
WHERE id IN (${selectedEntries.map(id => `'${id}'`).join(',')})
`);
displaySelectedDeals(entries);
}Listen for selection changes:
dench.context.onSelectionChange(async (newSelection) => {
if (newSelection.objectName === "deals") {
await updateDealAnalysisPanel(newSelection.entryIds);
}
});This creates tight integration between your app and the main CRM view — as the user clicks around in the CRM table, your app panel updates to show details about the currently selected records.
App Self-Context#
Apps can access their own metadata:
const { app } = await dench.context.get();
console.log(app.slug); // "pipeline-dashboard"
console.log(app.name); // "Pipeline Dashboard"
console.log(app.version); // "1.0.0"
// Check if running in widget mode
console.log(app.displayMode); // "widget" or "full"
if (app.displayMode === "widget") {
// Render compact widget view
renderWidget();
} else {
// Render full app view
renderFullApp();
}The displayMode check is essential for apps that support both full-screen and widget views.
Context-Aware Navigation#
Apps can trigger navigation in the main DenchClaw workspace:
// Navigate the main workspace to a specific entry
await dench.context.navigate("/crm/deals/abc-123");
// Navigate to an object view with a specific filter
await dench.context.navigate("/crm/deals", {
view: "Pipeline Overview",
filter: { field: "Status", value: "Active" }
});
// Open a specific app
await dench.context.navigate("/apps/email-composer");This turns your app into a launcher — select records, click a button, and DenchClaw navigates to the relevant view.
Practical Example: Context-Aware AI Assistant#
Here's a Dench App that uses context to provide relevant AI assistance:
// Load context and set up contextual chat
async function initContextualAssistant() {
const ctx = await dench.context.get();
// Build context-aware system prompt
const objectContext = ctx.currentObject
? `The user is currently working with their ${ctx.currentObject.label} data.`
: '';
const selectionContext = ctx.selectedEntries.length > 0
? `They have ${ctx.selectedEntries.length} entries selected.`
: '';
const systemContext = `You are a DenchClaw workspace assistant.
${objectContext} ${selectionContext}
Help them analyze, query, or take action on their CRM data.
Their timezone is ${ctx.user.timezone}.`;
// Initialize chat with this context
const session = await dench.chat.createSession({ systemPrompt: systemContext });
// Update context when it changes
dench.context.onSelectionChange(async (selection) => {
const entries = await loadEntries(selection.entryIds);
await dench.chat.send(session.id,
`[Context update: user selected ${entries.length} ${selection.objectName}]`,
{ hidden: true } // Don't show this message in the UI
);
});
return session;
}Context API Methods Summary#
| Method | Description |
|---|---|
dench.context.get() | Get full context snapshot |
dench.context.getUser() | Get user info only |
dench.context.getTheme() | Get theme info only |
dench.context.getCurrentObject() | Get active CRM object |
dench.context.getSelectedEntries() | Get selected entry IDs |
dench.context.navigate(path, opts) | Navigate workspace |
dench.context.onThemeChange(fn) | Theme change listener |
dench.context.onSelectionChange(fn) | Selection change listener |
dench.context.onObjectChange(fn) | Active object change listener |
See also: DenchClaw Inter-App Messaging for app-to-app coordination, and DenchClaw Store API for persistent app state.
Frequently Asked Questions#
Does the Context API work in widgets?#
Yes. Widgets receive full context including theme, current object, and selection. The app.displayMode === "widget" flag lets you detect you're running in widget mode and render appropriately.
Can my app change what object is currently viewed in the main CRM?#
Yes. Use dench.context.navigate("/crm/OBJECT_NAME") to navigate the main workspace view. Your app can programmatically drive the main CRM view.
What's the difference between context and the Store API?#
Context is the current runtime environment (ephemeral, real-time). The Store API is persistent state (saved across sessions). Use context for adapting to the current situation; use store for remembering user preferences.
Is user context available in a single-user workspace?#
Yes. Even in a single-user workspace, context.user is populated with workspace owner info. In multi-user workspaces, it reflects the currently logged-in user.
Can I use context in cron jobs?#
Cron jobs run in isolated sessions without a user-facing context. dench.context.get() in a cron returns limited context (workspace and theme, but no user selection or current object). Design cron tasks to not depend on user context.
Ready to try DenchClaw? Install in one command: npx denchclaw. Full setup guide →
