Skip to main content
Studio loads its default interface from the bundled fused-studio pack, maintained by Fused. Your packs use the same versioned manifest, asset snapshots, contribution slots, and module lifecycle. The host owns authentication and recovery; packs own the visible interface.

Configure with a coding agent

Install the bundled coding-agent skills in the project where you maintain your packs:
Use $harnest-studio for workspace, company-pack, and builder configuration. Use $harnest-studio-ui for visual changes, including a Tailwind or Panda CSS section replacement. The skills include manifest guidance, build boundaries, validation, and recovery checks. They configure Studio; they are separate from runtime Agent Skills or a pack’s builder guidance.

Choose your customization

UI contributions belong to Studio. They are not installed into your agent project and do not become agent tools or builder instructions. A pack may contain both UI contributions and the project resources used to build agents.

Choose a CSS framework

Studio consumes built HTML, CSS, and JavaScript. Each pack owns its build tools, so you can use Tailwind CSS, Panda CSS, or plain CSS independently of the default pack. Changing frameworks means rebuilding the relevant pack assets; there is no Studio-wide framework setting. Follow Replace one section with Tailwind for a buildable example, exact configuration, and the file-by-file change record. Use the same compiled-asset boundary with another framework.

Load a theme and layout

Add a ui section to an ordinary Studio Pack:
studio-pack.yaml
Open Appearance, choose your theme and layout, and click Save. Selection changes preview immediately; Cancel restores the previous appearance. Preferences are stored in this browser for the workspace. Missing selections fall back to the bundled defaults. One theme is selected at a time. Its tokens overlay the bundled defaults. Common tokens include bg, panel, soft, hover, line, muted, text, accent, accent-ink, danger, font-ui, font-size, font-code, editor-bg, editor-gutter, and editor-size. Use literal values, such as hex colors, 14px, or a font stack. CSS functions, resource URLs, and stylesheet syntax are rejected. Names beginning with studio- are reserved for the host. A layout lists sidebar, workspace, and inspector exactly once in order. It may hide sidebar or inspector. The default shell applies column order on desktop. At widths of 960 pixels or less, the assistant and inspector collapse instead of moving below the workspace. Click Build / Inspect to open the side panel; close it with Close, Escape, or the backdrop. Drafts and the selected tab survive closing and resizing. Hiding controls does not change backend permissions. The default shell keeps guided actions under Steps. Click Focus to hide the workspace heading and tool row while retaining editor tabs and the side-panel control. Exit focus restores those controls without remounting the work area or losing edits.

Contribute an isolated view

Declare each asset explicitly under the pack’s assets/ directory. HTML panels use inline CSS and JavaScript; external resource loads are blocked by the panel’s content security policy.
assets/welcome.html
Frames run without same-origin access. The host transfers a private message port and sends only explicitly requested state. state.connection supplies { ready }; state.project supplies { id, name, framework }. Frames do not receive credentials, project source, filesystem paths, or a command bridge. Contribution IDs are qualified as pack-name/local-id. Use replaces to replace an existing contribution in the same slot. Two replacements for the same contribution, replacement cycles, and missing targets are rejected. Pack load order never chooses a winner. The resolved interface must have one shell and one welcome contribution. The bundled pack exposes fused-studio/shell, fused-studio/welcome, fused-studio/appearance, and fused-studio/deployment. You can retain the shell and replace a welcome view or deployment workflow, or replace the shell with your own implementation.

Write a trusted module

Modules export activate(studio, host) and may return a cleanup function. The entrypoint and every imported module or HTML fragment must be listed in ui.assets. Stylesheets listed in ui.styles also require trust.
studio-pack.yaml
assets/summary.css must exist before validation or launch. For a replacement welcome module, change slot to welcome and add replaces: fused-studio/welcome. For a replacement shell, use slot: shell and replaces: fused-studio/shell. The referenced JavaScript must implement that view; changing a slot does not generate a shell.
assets/summary.js
Trust grants a pack JavaScript execution in Studio’s page with full Studio access. A manifest cannot grant this authority to itself. Without launch-time trust, module contributions and stylesheets are omitted; themes, layouts, and isolated frames remain available.
The version-one host context includes: Command registration, slot registration, navigation guards, and state subscriptions return cleanup functions. Module cleanup runs when mounting fails. The default shell publishes connection and project state and registers studio.project.create, studio.project.refresh, and studio.file.open. Those commands are supplied by the default shell, not guaranteed by an arbitrary replacement shell. The shell also publishes jobs and supplies studio.editor.isDirty, studio.jobs.run(body), studio.notice(message), and studio.proposal.review(projectId, proposal). The deployment service owns studio.deployment.open. See the deployment UI contract for arguments, completion handling, and server checks. A replacement shell declares its regions using data-studio-region="sidebar", workspace, and inspector, and supplies data-studio-slot containers for its selected views. It can register slot adapters to build navigation for contributed views. Service modules receive null as their mount container.

TypeScript and IDE support

Export the UI types from the Harnest installation that will run your pack:
Use the archive filename printed by the command. Commit that archive and your npm lockfile so teammates use the same contract. The archive is generated locally; it does not require an npm registry release. Repeat the export when upgrading Studio, using a new output directory if an archive already exists. The package contains declarations only. import type adds no browser code and works with React, other frameworks, and ordinary TypeScript:
src/summary.ts
Use ViewActivate for visual slots, ServiceActivate for a service with a null container, or Activate when the implementation handles both. StudioContext is available for helper and component props. Build the entrypoint to JavaScript and declare its output in the manifest as usual. JavaScript authors can use /** @type {import('@harnest/studio-ui').ViewActivate} */ above an exported const activate with checkJs enabled. Commands, state, slot names, appearance, navigation, and request arguments have shared types. Add your company’s command and state contracts through declaration merging; this preserves argument checking for the built-in names:
A contribution must still register acme.deploy at runtime. Types do not install commands or grant trust. The built-in command signatures describe the default shell and services; a replacement shell must supply those commands if its packs use them. request<T>(path, method, body) defaults its response to unknown; specifying T describes your expected response without validating it at runtime. JSON requests use paths relative to /api/, while transport takes /api/....

Package and recover

The existing pack validation and company wheel commands include UI manifests and their exact asset snapshots. Assets use content-revision URLs, and edits to publisher files take effect after restarting Studio. Existing Studio and Harnest compatibility requirements still apply. Each pack can snapshot up to 128 UI assets, with a 1 MiB limit per file and an 8 MiB total UI limit. Referenced assets must be supported UTF-8 text; symlinks and path traversal are rejected. Use Restore default UI to reload the bundled interface without custom UI contributions. The host also displays this recovery link if composition fails. To bypass all external packs, including missing or malformed pack directories, launch:
Browser recovery leaves your saved appearance preferences intact. The safe launch flag excludes external packs entirely for that launch, including their agent resources and builder defaults.