| name | moldable |
| description | Complete guide for building Moldable apps. Use this skill when creating or modifying apps, creating or managing Scheduled automations, implementing workspace-aware storage, using typed native APIs for media, location, clipboard, notifications, displays, shortcuts, power/session state, local authentication, haptics, secure storage, USB, HID, serial, MIDI, or Bluetooth, declaring nativeHardware permissions, integrating with Moldable desktop messages, publishing artifacts, configuring workspaces, managing skills/MCPs, or troubleshooting app issues. |
Moldable App Development
This skill provides comprehensive knowledge for building and modifying apps within the Moldable desktop application.
Quick Reference
| Resource | Path |
|---|
| App source code | ~/.moldable/shared/apps/{app-id}/ |
| App runtime data | ~/.moldable/workspaces/{workspace-id}/apps/{app-id}/data/ |
| Workspace config | ~/.moldable/workspaces/{workspace-id}/config.json |
| MCP config | ~/.moldable/shared/config/mcp.json |
| Skills | ~/.moldable/shared/skills/{repo}/{skill}/ |
| Environment | ~/.moldable/shared/.env |
Default Tech Stack
- Framework: Vite + Hono + React 19 + TypeScript
- Styling: Tailwind CSS 4 + shadcn/ui (semantic colors only)
- State: TanStack Query v5
- Storage: Filesystem via
@moldable-ai/storage
- Dev Reloading: Vite client HMR via Portless-aware
MOLDABLE_APP_URL; Hono server reloads via tsx watch
- Package Manager: pnpm
Creating Apps
ALWAYS use the scaffoldApp tool — never create app files manually.
scaffoldApp({
appId: 'expense-tracker',
name: 'Expense Tracker',
icon: '💰',
description: 'Track expenses and generate reports',
extraDependencies: {
zod: '^3.0.0',
},
})
After scaffolding, customize:
src/client/app.tsx — Main app view
src/server/app.ts or src/server/routes/ — Hono API routes (including /api/moldable/health and /api/moldable/today)
src/client/components/ or src/components/ — React components
Today contribution
The home screen is the host-rendered Today view. Apps participate by implementing GET /api/moldable/today, which returns items/resume only when something genuinely needs the user (quiet by default). See references/today.md.
Scheduled agent work
The desktop UI calls this area Scheduled; its tools and internal data model
use the term automation. Chat can create and manage Scheduled work with
first-class automation tools. Use those tools instead of creating an app,
editing automations.json, or configuring OS cron. Scheduled work is scoped to
one workspace and runs only while the Moldable desktop is open.
Choose exactly one creation tool from the user's scheduling intent; their input
schemas are strict:
createRelativeAutomation — run once after a relative delay in seconds,
minutes, hours, days, or weeks.
createOneTimeAutomation — run once at a local YYYY-MM-DD date and HH:mm
time.
createDailyAutomation — run every day at a local time.
createRecurringAutomation — run daily, on weekdays, weekly, monthly, or
yearly at a local time.
createIntervalAutomation — run every N seconds, minutes, hours, days, weeks,
months, or years.
createCronAutomation — use only when the user explicitly asks for a cron
expression; prefer the structured tools otherwise.
For createRecurringAutomation, supply weekdays as 0–6 (0 is Sunday) for a
weekly recurrence, dayOfMonth for monthly, and both dayOfMonth and
monthOfYear for yearly. Sub-day intervals keep a UTC cadence; day-or-longer
intervals preserve local wall-clock time across timezone changes.
For every creation:
- Provide a short
name, a self-contained prompt, and the user's IANA
timezone. Let the runtime resolve concrete timestamps; never calculate UTC
or the next run yourself.
- Make the prompt describe the source apps, filters, desired result or
mutation, and what should count as useful output. Scheduled runs are
independent agent runs and must not depend on unstated chat context.
- For work involving app data, call
listMoldableAppApi for the relevant apps
before creating the automation. Declare every target in appAccess using
exact returned method/scope IDs, with read unless a requested mutation
requires write. Never guess scopes or read another app's data directory.
- Keep
includeSuccessesInToday false unless the user explicitly wants every
successful run shown. The default keeps routine results quiet while blocked
or failed work can still surface in Today.
- Use
maxRuns for a bounded series. Omit it for an unbounded recurring
schedule.
- After creation, quote the returned
schedule.confirmationText; do not
reinterpret or recompute the schedule.
Creating or updating appAccess grants those declared scopes to the
workspace-scoped moldable-automations caller. Unattended runs cannot broaden
their own access. If a run reports a missing app API scope, verify the scope
with listMoldableAppApi, then use updateAutomation only when the user has
authorized that access.
Use listAutomations and getAutomation to resolve an existing item before
acting. Use updateAutomation for its name, prompt, app access, or Today policy;
toggleAutomation to pause or resume it; runAutomationNow for an immediate
run; and deleteAutomation to remove it. The chat update tool does not change
schedules: create and verify a replacement schedule first, then delete the old
automation only when the user's request clearly authorizes replacement.
Detailed References
Read these for in-depth guidance:
Core Concepts
Implementation Patterns
- references/design.md — Moldable app design system for full app layouts, state handling, density, copy, motion, and UI polish. Read this before visible UI work.
- references/today.md — The Today home view: implementing
GET /api/moldable/today, item kinds, actions, and the "quiet by default" rules.
- references/ui.md — @moldable-ai/ui components, shadcn/ui, themes, rich text editor, Cmd+K app commands
- references/storage-patterns.md — Filesystem storage, React Query, workspace-aware APIs
- references/browser-storage-audit.md — Current browser storage usage and migration guidance
- references/desktop-apis.md — Router for desktop integration APIs
- references/desktop-message-apis.md — Window, chat, file, and artifact postMessage APIs
- references/native-apis.md — Typed native capability API overview and usage rules; hardware UI components (CameraPreview, SerialConsole, LocationPanel, …) are listed in references/ui.md
- references/native-api-support.md — Native capability support matrix and permission summary
- references/native-api-permissions.md —
nativeHardware declarations and per-app workspace grants
- references/native-api-media.md — Camera, microphone, display capture, macOS permission status/request/diagnostics, and system audio
- references/native-api-location.md — Current-position API and permission behavior
- references/native-api-clipboard.md — Native clipboard text APIs
- references/native-api-notifications.md — Native system notifications and permissions
- references/native-api-displays.md — Connected display metadata
- references/native-api-global-shortcuts.md — Global shortcut registration, events, conflicts, and cleanup
- references/native-api-power-session.md — Power, current thermal and idle state, lifecycle events, plus queryable sleep blockers
- references/native-api-local-authentication.md — Biometric-only or device-owner verification policies
- references/native-api-haptics.md — API acceptance and honest physical-feedback semantics
- references/native-api-secure-storage.md — Scoped credential values and non-secret backend diagnostics
- references/native-api-usb.md — Filtered WebUSB/native device access and transfers
- references/native-api-hid.md — Filtered WebHID/native reports and listeners
- references/native-api-serial.md — Web Serial/native ports, streams, and signals
- references/native-api-midi.md — Web MIDI/native ports, messages, and SysEx rules
- references/native-api-bluetooth.md — Web Bluetooth/native BLE GATT access
- references/native-api-platform-macos.md — macOS permission and support notes
- references/native-api-platform-windows.md — Windows permission and support notes
- references/native-api-platform-linux.md — Linux runtime and validation notes
- references/artifact-publishing.md — Publishing public unlisted HTML/CSS/asset bundles through Moldable Artifacts
- references/app-to-app-communication.md — App-to-app RPC, capability manifests, workspace-scoped grants, Calendar-owned OAuth/data access
- references/skills-mcps.md — Skills library, MCP configuration, custom MCP servers
Essential Patterns
For any visible app UI, read references/design.md before editing src/client/app.tsx or client components. The design reference is self-contained and does not require other apps to be installed.
1. UI Components (@moldable-ai/ui)
Always use @moldable-ai/ui for all UI work. It includes shadcn/ui components, theme support, and a rich text editor.
import { MarkdownEditor } from '@moldable-ai/editor'
import {
Button,
Card,
CodeBlock,
Dialog,
Input,
Markdown,
Select,
Tabs,
ThemeProvider,
WorkspaceProvider,
downloadFile,
sendToMoldable,
useTheme,
} from '@moldable-ai/ui'
Use semantic colors only:
<div className="bg-background text-foreground border-border" />
<Button className="bg-primary text-primary-foreground" />
<div className="bg-white text-gray-900" />
See references/ui.md for complete component list and usage.
For native hardware UI (camera, mic, location, serial, BLE, …), use the
prebuilt hardware components from @moldable-ai/ui — CameraPreview,
MicrophoneMeter, LocationPanel, SerialConsole, CapabilityMatrix, etc. —
instead of building your own on the imperative helpers. They ship the
permission flows, device pickers, and live/error states already styled. Full
list in references/ui.md § Hardware Components; read the
component source to discover props.
2. Workspace-Aware Storage
All apps must isolate data per workspace:
import { getAppDataDir, getWorkspaceFromRequest } from '@moldable-ai/storage'
const { workspaceId, fetchWithWorkspace } = useWorkspace()
const { data } = useQuery({
queryKey: ['items', workspaceId],
queryFn: () => fetchWithWorkspace('/api/items').then((r) => r.json()),
})
export async function GET(request: Request) {
const workspaceId = getWorkspaceFromRequest(request)
const dataDir = getAppDataDir(workspaceId)
}
3. Desktop Integration
Apps communicate with Moldable desktop via postMessage:
window.parent.postMessage(
{ type: 'moldable:open-url', url: 'https://...' },
'*',
)
window.parent.postMessage(
{ type: 'moldable:show-in-folder', path: '/path/to/file' },
'*',
)
window.parent.postMessage(
{ type: 'moldable:set-chat-input', text: 'Help me...' },
'*',
)
window.parent.postMessage(
{
type: 'moldable:set-chat-instructions',
text: 'User is viewing meeting #123...',
},
'*',
)
For public, shareable static outputs such as slides, meeting notes, reports,
HTML/CSS demos, image galleries, or generated app snapshots, prefer
publishMoldableArtifact() from @moldable-ai/ui instead of hand-rolled
network calls. See references/artifact-publishing.md.
4. Layout Setup
Required providers for Moldable apps:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ThemeProvider, WorkspaceProvider } from '@moldable-ai/ui'
import { App } from './app'
import { QueryProvider } from './query-provider'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ThemeProvider>
<WorkspaceProvider>
<QueryProvider>
<App />
</QueryProvider>
</WorkspaceProvider>
</ThemeProvider>
</StrictMode>,
)
5. Adding Dependencies
Use sandbox: false for package manager commands:
await runCommand({
command: 'cd ~/.moldable/shared/apps/my-app && pnpm add zod',
sandbox: false,
})
App Management Tools
| Tool | Purpose | Reversible |
|---|
scaffoldApp | Create new app | — |
getAppInfo | Check which workspaces use an app | — |
unregisterApp | Remove from current workspace only | ✅ Re-add later |
deleteAppData | Delete app's data (keep installed) | ❌ Data lost |
deleteApp | Permanently delete from ALL workspaces | ❌ Everything lost |
File Structure
~/.moldable/
├── shared/
│ ├── apps/{app-id}/ # App source code
│ │ ├── moldable.json # App manifest
│ │ ├── package.json
│ │ └── src/
│ ├── skills/{repo}/{skill}/ # Skills library
│ ├── mcps/{mcp-name}/ # Custom MCP servers
│ └── config/mcp.json # Shared MCP config
│
└── workspaces/{workspace-id}/
├── config.json # Registered apps
├── .env # Workspace env overrides
├── apps/{app-id}/data/ # App runtime data
└── conversations/ # Chat history
Common Mistakes to Avoid
- ❌ Creating apps manually — Always use
scaffoldApp
- ❌ Using localStorage/sessionStorage for app data or settings — Use workspace-scoped server APIs and
@moldable-ai/storage; browser storage is only acceptable for disposable same-session UI state.
- ❌ Forgetting workspaceId — Include in query keys and API calls
- ❌ Hardcoding paths — Use
getAppDataDir() for portability
- ❌ Using raw colors — Use shadcn semantic colors (
bg-background, not bg-gray-100)
- ❌ Running pnpm with sandbox — Set
sandbox: false for network access
Study Existing Apps
For complex features, reference apps in ~/.moldable/shared/apps/:
- scribo — Translation journal with language selection
- meetings — Audio recording with real-time transcription
- calendar — Google Calendar integration with OAuth
These demonstrate data fetching, storage patterns, API routes, and UI components.