autoInstall() — one-line install

Zero-config on-ramp. Returns a fully-constructed DotDotDuck with sensible defaults so you can see the SDK working before deciding what to configure.

Minimum

import { autoInstall } from '@perhapxin/dddk';
import '@perhapxin/dddk/styles.css';

const dddk = autoInstall();

That's it. You get:

  • Command palette wired to Ctrl+K / ⌘K.
  • Subtitle bar mounted center-bottom.
  • Dwell long-press detector on desktop mouse input.
  • Mobile FAB (bottom-right).
  • All six default duck sprites loaded from the SDK's bundled dist/duck/.
  • Locale auto-detected: zh / zh-*'zh-TW', everything else → 'en'.
  • SDK-shipped prompt defaults registered on dddk.prompts.
  • A demo LLM that responds to any completion with a "wire your real provider" nudge — so agent / InlineAgent / voice-cleanup don't silently no-op; the user sees why nothing is happening.

Passing overrides

Every field of DotDotDuckConfig is accepted verbatim, plus one factory-specific flag (demoLLM).

const dddk = autoInstall({
  llm: myOpenAIProvider,          // real LLM replaces the demo stub
  siteName: 'Acme',
  agentName: 'Rex',
  paletteCommands: myCommands,
  brand: { voice: 'friendly' },
  webAgent: {
    contextProvider: () => ({ tenant: currentTenant() }),
  },
});

autoInstall(overrides) and new DotDotDuck({ ...factoryDefaults, ...overrides }) are functionally equivalent — the factory just picks the defaults. Anything you don't override keeps the demo default.

Disabling the demo LLM

By default, if you don't pass llm, autoInstall wires a demo stub. To keep the old "silent no-op if no LLM" behaviour (matches raw new DotDotDuck({})), set demoLLM: false:

const dddk = autoInstall({ demoLLM: false });
// Palette + Dwell + FAB still mount; agent-side features silently
// no-op until an `llm` gets wired at runtime.

Useful when your LLM provider is async-loaded (e.g. behind auth) and you want the SDK up before it's ready.

Full option type

interface AutoInstallOptions extends Partial<DotDotDuckConfig> {
  /**
   * When true and no `llm` is provided, wire a demo LLM that returns
   * a canned "wire an LLM" response. Default: true. Set to false to
   * keep the agent silently no-op — matches raw `new DotDotDuck({})`
   * behaviour, useful when the host will wire an LLM later.
   */
  demoLLM?: boolean;
}

Return type: DotDotDuck. Same instance you'd get from new DotDotDuck(...). All methods (startAgent, runSkill, submitSurface, etc.) are available.

When NOT to use autoInstall

  • You already wire every config field explicitly. Migrating to autoInstall({...}) would just move code around — no benefit.
  • You need SSR-safe initialisation. autoInstall reads navigator.language at construction time, so it can't run on the server. Call it inside onMount (Svelte) / useEffect (React) / mounted (Vue).
  • You want the demo LLM to be permanent. The demo LLM is intentionally hostile-to-real-use — its response tells the user to wire a real provider. If your product legitimately doesn't need an LLM, pass demoLLM: false and skip the pill.

Common integration patterns

Vanilla HTML + <script>

<script type="module">
  import { autoInstall } from 'https://esm.sh/@perhapxin/dddk@0.2.2';
  import 'https://esm.sh/@perhapxin/dddk@0.2.2/styles.css';

  const dddk = autoInstall();
  window.dddk = dddk; // for DevTools poking
</script>

SvelteKit

<script lang="ts">
  import { onMount } from 'svelte';
  import { autoInstall } from '@perhapxin/dddk';
  import '@perhapxin/dddk/styles.css';

  onMount(() => {
    const dddk = autoInstall({
      llm: myProvider,
      paletteCommands: buildCommands(),
    });
    return () => dddk.destroy?.();
  });
</script>

React / Next.js

'use client';
import { useEffect } from 'react';
import { autoInstall } from '@perhapxin/dddk';
import '@perhapxin/dddk/styles.css';

export function DddkBoot() {
  useEffect(() => {
    const dddk = autoInstall({ llm: getLLM() });
    return () => dddk.destroy?.();
  }, []);
  return null;
}