Skip to main content

JavaScript API Reference

Krema injects a global window.krema object providing access to native APIs.

Core IPC

invoke

Invoke a backend command.

function invoke<T = unknown>(command: string, args?: Record<string, unknown>): Promise<T>;

Example:

const result = await window.krema.invoke('greet', { name: 'World' });
// result: "Hello, World!"

on

Register an event listener.

function on<T = unknown>(event: string, callback: (data: T) => void): () => void;

Returns: Unsubscribe function

Example:

const unsubscribe = window.krema.on('file-changed', (data) => {
console.log('File changed:', data.path);
});

// Later: remove listener
unsubscribe();

Built-in Events

app:error

Emitted when an unhandled error occurs in either the Java backend or the WebView frontend. Krema automatically captures uncaught Java exceptions, JavaScript errors (window.onerror), and unhandled Promise rejections.

Payload:

interface AppError {
source: 'JAVA' | 'WEBVIEW';
message: string;
stackTrace: string;
thread?: string; // Java thread name (Java errors only)
fileName?: string; // Source file (WebView errors only)
lineNumber?: number; // Line number (WebView errors only)
os: string;
appVersion: string;
recentCommands: string[];
}

Example:

window.krema.on('app:error', (error) => {
console.error(`[${error.source}] ${error.message}`);

// Send to your error tracking service
myErrorTracker.report({
source: error.source,
message: error.message,
stack: error.stackTrace,
context: {
os: error.os,
version: error.appVersion,
recentCommands: error.recentCommands
}
});
});

Dialog API

openFile

Open a file selection dialog.

interface FileFilter {
name: string;
extensions: string[];
}

interface OpenFileOptions {
title?: string;
defaultPath?: string;
filters?: FileFilter[];
}

function openFile(options?: OpenFileOptions): Promise<string | null>;

Example:

const file = await window.krema.invoke('dialog:openFile', {
title: 'Select a file',
filters: [
{ name: 'Text Files', extensions: ['txt', 'md'] },
{ name: 'All Files', extensions: ['*'] }
]
});

openFiles

Open a multi-file selection dialog.

function openFiles(options?: OpenFileOptions): Promise<string[] | null>;

saveFile

Open a save file dialog.

interface SaveFileOptions {
title?: string;
defaultPath?: string;
filters?: FileFilter[];
}

function saveFile(options?: SaveFileOptions): Promise<string | null>;

selectFolder

Open a folder selection dialog.

function selectFolder(options?: FolderOptions): Promise<string | null>;

message

Show a message dialog.

type MessageType = 'info' | 'warning' | 'error';

function message(title: string, message: string, type?: MessageType): Promise<void>;

confirm

Show a confirmation dialog.

function confirm(title: string, message: string): Promise<boolean>;

prompt

Show a text input prompt.

function prompt(title: string, message: string, defaultValue?: string): Promise<string | null>;

Clipboard API

readText

Read text from the clipboard.

function readText(): Promise<string | null>;

writeText

Write text to the clipboard.

function writeText(text: string): Promise<boolean>;

readHtml

Read HTML from the clipboard.

function readHtml(): Promise<string | null>;

hasText / hasImage

Check clipboard content type.

function hasText(): Promise<boolean>;
function hasImage(): Promise<boolean>;

readImageBase64

Read image as base64 PNG.

function readImageBase64(): Promise<string | null>;

clear

Clear clipboard contents.

function clear(): Promise<boolean>;

Window API

setTitle

Set the window title.

function setTitle(title: string): Promise<void>;

setSize

Set window dimensions.

function setSize(width: number, height: number): Promise<void>;

setPosition

Set window position.

function setPosition(x: number, y: number): Promise<void>;

center

Center the window on screen.

function center(): Promise<void>;

minimize / maximize / restore

Window state controls.

function minimize(): Promise<void>;
function maximize(): Promise<void>;
function restore(): Promise<void>;

setFullscreen

Toggle fullscreen mode.

function setFullscreen(fullscreen: boolean): Promise<void>;

setAlwaysOnTop

Set always-on-top state.

function setAlwaysOnTop(alwaysOnTop: boolean): Promise<void>;

close

Close the window.

function close(): Promise<void>;

Notification API

show

Show a desktop notification.

interface NotificationOptions {
title: string;
body: string;
icon?: string;
}

function show(options: NotificationOptions): Promise<void>;

Example:

await window.krema.invoke('notification:show', {
title: 'Download Complete',
body: 'Your file has been downloaded successfully.'
});

Shell API

open

Open a file or URL with the default application.

function open(path: string): Promise<void>;

Example:

// Open a URL in the browser
await window.krema.invoke('shell:open', { path: 'https://example.com' });

// Open a file with its default app
await window.krema.invoke('shell:open', { path: '/path/to/document.pdf' });

execute

Execute a shell command.

interface ExecuteResult {
stdout: string;
stderr: string;
exitCode: number;
}

function execute(command: string, args?: string[]): Promise<ExecuteResult>;

Path API

appDataDir

Get the application data directory.

function appDataDir(): Promise<string>;

appConfigDir

Get the application config directory.

function appConfigDir(): Promise<string>;

homeDir

Get the user's home directory.

function homeDir(): Promise<string>;

desktopDir / documentsDir / downloadsDir

Get common user directories.

function desktopDir(): Promise<string>;
function documentsDir(): Promise<string>;
function downloadsDir(): Promise<string>;

Screen API

all

Get all displays.

interface ScreenBounds {
x: number;
y: number;
width: number;
height: number;
}

interface ScreenInfo {
name: string;
frame: ScreenBounds; // Full screen bounds
visibleFrame: ScreenBounds; // Excluding taskbars/menubar
scaleFactor: number;
refreshRate: number;
isPrimary: boolean;
}

function all(): Promise<ScreenInfo[]>;

primary

Get the primary display.

function primary(): Promise<ScreenInfo>;

cursorPosition

Get current cursor position.

function cursorPosition(): Promise<{ x: number; y: number }>;

Store API

get

Get a value from the store.

function get<T = unknown>(key: string): Promise<T | null>;

set

Set a value in the store.

function set(key: string, value: unknown): Promise<void>;

delete

Delete a key from the store.

function delete(key: string): Promise<boolean>;

has

Check if a key exists.

function has(key: string): Promise<boolean>;

keys

Get all keys in the store.

function keys(): Promise<string[]>;

Secure Storage API

Store sensitive data in the OS keychain.

set

function set(key: string, value: string): Promise<void>;

get

function get(key: string): Promise<string | null>;

delete

function delete(key: string): Promise<void>;

has

function has(key: string): Promise<boolean>;

Updater API

check

Check for updates.

interface UpdateCheckResult {
updateAvailable: boolean;
version?: string;
notes?: string;
pubDate?: string;
}

function check(): Promise<UpdateCheckResult>;

download

Download an available update.

function download(): Promise<void>;

Events:

  • download-progress: Emitted during download with { percent: number, downloaded: number, total: number }

install

Install the downloaded update and restart.

function install(): Promise<void>;

TypeScript Support

Generated Command Types

Krema automatically generates TypeScript type definitions for your @KremaCommand methods at compile time. When you build your Java backend, the annotation processor emits a krema-commands.d.ts file that provides full autocompletion and type checking for krema.invoke() calls.

For example, given this Java code:

@KremaCommand
public String greet(String name) { ... }

@KremaCommand
public SystemInfo systemInfo() { ... }

public record SystemInfo(String osName, int processors) {}

The processor generates:

// Auto-generated by Krema annotation processor. Do not edit.

export interface SystemInfo {
osName: string;
processors: number;
}

export interface KremaCommandMap {
'greet': { args: { name: string }; result: string };
'systemInfo': { result: SystemInfo };
}

declare namespace krema {
function invoke<K extends keyof KremaCommandMap>(
command: K,
...args: KremaCommandMap[K] extends { args: infer A }
? [args: A]
: [args?: Record<string, never>]
): Promise<KremaCommandMap[K]['result']>;
}

With these types in place, krema.invoke() calls are fully type-safe:

// Type-safe — command name, args, and return type are all checked
const greeting = await krema.invoke('greet', { name: 'World' });
// ^? string

const info = await krema.invoke('systemInfo');
// ^? SystemInfo

// Compile error: missing required arg 'name'
await krema.invoke('greet');

// Compile error: unknown command
await krema.invoke('nonexistent');

The generic invoke<T>(command: string, ...) fallback from krema-types.d.ts still works for dynamic or unknown commands.

Output Configuration

By default, the generated file is written to target/classes/krema-commands.d.ts. To write it directly into your frontend source tree, set the -Akrema.ts.outDir annotation processor option in your pom.xml:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>build.krema</groupId>
<artifactId>krema-processor</artifactId>
<version>${krema.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Akrema.ts.outDir=${project.basedir}/src</arg>
</compilerArgs>
</configuration>
</plugin>

Base Type Definitions

Krema's built-in API types (dialogs, clipboard, shell, etc.) are provided via krema-types.d.ts, bundled as a resource in the krema-core JAR. After building your Java backend, the file is available at target/classes/krema-types.d.ts. Copy it into your frontend source directory (e.g. src/) so TypeScript picks it up:

cp target/classes/krema-types.d.ts src/

With the type definitions in place, the window.krema API is fully typed — no imports needed:

// Types are available globally via window.krema
const file = await window.krema.invoke('dialog:openFile', { title: 'Pick a file' });

window.krema.on('user-updated', (user: { id: string; name: string }) => {
console.log('User updated:', user.name);
});