# How to Use the craftagents:// URL Scheme for Deep Linking in Craft Agents

> Learn how to use the craftagents:// URL scheme to deep link into the Craft Agents app. Navigate directly to workspaces, sessions, or actions from external apps with this guide.

- Repository: [Craft Ai Agents/craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss)
- Tags: how-to-guide
- Published: 2026-07-06

---

**The `craftagents://` URL scheme enables external applications and web pages to launch the Craft Agents desktop app and navigate directly to specific workspaces, sessions, or actions by registering a custom protocol handler in Electron that parses URLs into typed navigation targets.**

The Craft Agents open-source application (`craft-ai-agents/craft-agents-oss`) implements a custom protocol handler that transforms `craftagents://` URLs into internal navigation commands. This deep linking system allows users to open specific views, trigger actions with parameters, or target particular workspaces directly from external sources such as web browsers, other desktop applications, or system shortcuts.

## How the Deep Link System Works

The implementation spans three architectural layers: protocol registration, URL classification, and parsing with routing.

- **Protocol registration** occurs in [`apps/electron/src/main/index.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/main/index.ts), where the Electron app registers itself as the default handler for `craftagents://` URIs using `app.setAsDefaultProtocolClient`.
- **URL classification** in [`packages/shared/src/utils/url-safety.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/utils/url-safety.ts) distinguishes internal deep links from external URLs to prevent security vulnerabilities.
- **Parsing and routing** handled by [`apps/electron/src/main/deep-link.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/main/deep-link.ts) converts valid URLs into structured `DeepLinkTarget` objects, while [`packages/server-core/src/handlers/rpc/system.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/server-core/src/handlers/rpc/system.ts) dispatches navigation requests via the `RPC_CHANNELS.shell.OPEN_URL` handler.

## Registering the craftagents:// Protocol

The Electron main process registers the custom protocol during application startup. The scheme defaults to `craftagents` but can be customized via the `CRAFT_DEEPLINK_SCHEME` environment variable for development environments.

```typescript
// apps/electron/src/main/index.ts
const DEEPLINK_SCHEME = process.env.CRAFT_DEEPLINK_SCHEME || 'craftagents';
app.setAsDefaultProtocolClient(`${DEEPLINK_SCHEME}://`);

```

This registration tells the operating system to launch the Craft Agents executable whenever a user clicks a `craftagents://` link. During development, you can run multiple instances by setting distinct schemes such as `CRAFT_DEEPLINK_SCHEME=craftagents1` or `craftagents2`.

## Security and URL Classification

Before routing, the system validates URLs to ensure internal deep links do not open in external browsers. The `classifyExternalUrl` function in [`packages/shared/src/utils/url-safety.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/utils/url-safety.ts) identifies `craftagents:` schemes as internal resources.

```typescript
// packages/shared/src/utils/url-safety.ts
const INTERNAL_DEEPLINK_SCHEME = 'craftagents:';

export function classifyExternalUrl(url: string) {
  // Returns { kind: 'internal-deeplink' } for craftagents://…
}

```

When the system RPC handler receives an `OPEN_URL` request, it checks this classification. If the URL is an internal deep link, the handler intercepts it and routes through the internal parser rather than invoking `shell.openExternal`.

## Parsing Deep Links into Navigation Targets

The `parseDeepLink` function in [`apps/electron/src/main/deep-link.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/main/deep-link.ts) extracts structured data from `craftagents://` URLs. It supports compound routes, workspace-specific paths, and action-based URLs with query parameters.

```typescript
// apps/electron/src/main/deep-link.ts
export function parseDeepLink(url: string): DeepLinkTarget | null {
  const parsed = new URL(url);
  if (parsed.protocol !== 'craftagents:') return null;

  const host = parsed.hostname;
  const pathParts = parsed.pathname.split('/').filter(Boolean);
  const windowMode = parseWindowMode(parsed);
  const rightSidebar = parseRightSidebar(parsed);

  // Compound routes (e.g., craftagents://allSessions/session/abc)
  if (COMPOUND_ROUTE_PREFIXES.includes(host)) {
    return { 
      view: host + (pathParts.length ? '/' + pathParts.join('/') : ''), 
      windowMode, 
      rightSidebar 
    };
  }

  // Workspace-specific routes
  if (host === 'workspace') {
    const workspaceId = pathParts[0];
    // ... workspace handling logic
  }

  // Action routes (e.g., craftagents://action/new-chat)
  if (host === 'action') {
    const result: DeepLinkTarget = {
      action: pathParts[0],
      actionParams: {},
      windowMode,
      rightSidebar,
    };
    // Copy search params into actionParams
    return result;
  }

  return null;
}

```

The parser extracts the `window` query parameter to determine display mode (e.g., `focused` or `full`) and returns a `DeepLinkTarget` containing the view path, workspace ID, action name, and parameters.

## RPC Handling and Navigation Dispatch

The [`packages/server-core/src/handlers/rpc/system.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/server-core/src/handlers/rpc/system.ts) file implements the bridge between the main process and renderer. When a deep link arrives, the `RPC_CHANNELS.shell.OPEN_URL` handler validates and forwards the navigation.

```typescript
// packages/server-core/src/handlers/rpc/system.ts
server.handle(RPC_CHANNELS.shell.OPEN_URL, async (_ctx, rawUrl: string) => {
  const classification = classifyExternalUrl(rawUrl);
  
  if (classification.kind === 'internal-deeplink') {
    const target = parseDeepLink(rawUrl);
    if (!target) return { success: false, error: 'Invalid deep link' };
    
    const navigation: DeepLinkNavigation = {
      view: target.view,
      action: target.action,
      actionParams: target.actionParams,
    };
    
    await requestClientOpenExternal(server, ctx.clientId, navigation);
    return { success: true };
  }
  
  // Fallback to external browser
  await requestClientOpenExternal(server, ctx.clientId, rawUrl);
  return { success: true };
});

```

This handler ensures that `craftagents://` URLs trigger internal navigation within the active window, while standard HTTP URLs open in the system default browser.

## Practical craftagents:// URL Examples

### Opening a Specific Session

Navigate directly to a session within the All Sessions view:

```javascript
const url = 'craftagents://allSessions/session/abc123';
window.open(url);

```

This opens the Craft Agents app and displays the session with ID `abc123`.

### Accessing Settings Pages

Deep link to specific settings subsections:

```javascript
const url = 'craftagents://settings/shortcuts';
window.open(url);

```

The renderer receives `view: 'settings/shortcuts'` and navigates to the shortcuts configuration panel.

### Triggering Actions with Parameters

Start a new chat with pre-filled input and automatic sending:

```javascript
const url = 'craftagents://action/new-chat?input=Hello%20world&send=true';
window.open(url);

```

The parser produces:

```json
{
  "action": "new-chat",
  "actionParams": { "input": "Hello world", "send": "true" }
}

```

### Targeting Specific Workspaces

Execute actions within a particular workspace context:

```javascript
const url = 'craftagents://workspace/ws42/action/delete-session/12345';
window.open(url);

```

This switches to workspace `ws42` and executes the `delete-session` action on session `12345`.

### Opening Views in New Windows

Use the `window=focused` parameter to spawn a new Electron window:

```javascript
const url = 'craftagents://allSessions?window=focused';
window.open(url);

```

Instead of navigating the current window, this creates a new focused window displaying the All Sessions view.

## Summary

- The `craftagents://` URL scheme is registered in [`apps/electron/src/main/index.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/main/index.ts) using `app.setAsDefaultProtocolClient`.
- **Security validation** occurs in [`packages/shared/src/utils/url-safety.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/utils/url-safety.ts) to prevent internal links from opening in external browsers.
- The **parser** in [`apps/electron/src/main/deep-link.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/main/deep-link.ts) converts URLs into structured `DeepLinkTarget` objects supporting views, workspaces, and actions.
- **Navigation dispatch** happens through `RPC_CHANNELS.shell.OPEN_URL` in [`packages/server-core/src/handlers/rpc/system.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/server-core/src/handlers/rpc/system.ts), which routes internally or falls back to the OS browser.
- You can customize the scheme via the `CRAFT_DEEPLINK_SCHEME` environment variable for development scenarios.

## Frequently Asked Questions

### Can I customize the URL scheme to something other than craftagents://?

Yes. According to the source code in [`apps/electron/src/main/index.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/apps/electron/src/main/index.ts), you can override the default scheme by setting the `CRAFT_DEEPLINK_SCHEME` environment variable before launching the application. This is particularly useful for running multiple development instances simultaneously with schemes like `craftagents1://` or `craftagents2://`.

### What happens if Craft Agents is not installed when a craftagents:// link is clicked?

If the application is not installed, the operating system cannot resolve the protocol handler and will typically display an error dialog or prompt the user to find an application capable of opening the link. The deep link only functions when the Craft Agents Electron app has registered itself as the protocol client.

### How do I open a specific workspace using the deep link scheme?

Use the `workspace` host segment followed by the workspace ID and optional action path. For example, `craftagents://workspace/ws42` opens workspace `ws42`, while `craftagents://workspace/ws42/action/delete-session/12345` opens that workspace and executes a specific action. The parser in [`deep-link.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/deep-link.ts) handles these compound routes by extracting the workspace ID from the path segments.

### Are craftagents:// links safe to use in web browsers?

Yes, but with caveats. The [`packages/shared/src/utils/url-safety.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/src/utils/url-safety.ts) module explicitly classifies these URLs as internal deeplinks, and the system RPC handler intercepts them before they reach `shell.openExternal`. However, if Craft Agents is not installed, clicking the link will result in a protocol error. For web applications, consider providing fallback instructions or checking protocol support via `navigator.registerProtocolHandler` where appropriate.