Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.archal.ai/llms.txt

Use this file to discover all available pages before exploring further.

Linear and Ramp twins work via archal run and archal twin start but don’t yet have route-mode manifests for Vitest.
Prerequisites. archal/vitest talks to hosted twins provisioned by the Archal control plane, so every run needs an auth token — either run archal login once on your laptop or set ARCHAL_TOKEN=arc_... (recommended in CI). The first hosted session in a process spends ~30 seconds while AWS provisions an ECS-backed twin; later runs within the 30-minute TTL reuse that session and finish in ~2 seconds. Budget for the cold start in your test timeouts and CI step timings.

Install

pnpm add -D vitest archal
archal login
In CI, set ARCHAL_TOKEN instead of running archal login.

Add Archal to your existing vitest.config.ts

If your project already has a vitest.config.ts, wrap the value of test: with withArchal. It’s a merge helper — every field you already had (coverage, alias, globalSetup, poolOptions, custom reporters, etc.) is preserved, and Archal composes its setup file, reporter, and session env on top.
import { defineConfig } from 'vitest/config';
import { withArchal } from 'archal/vitest';

export default defineConfig({
  test: withArchal(
    {
      // everything you already had in test:, unchanged
      globals: true,
      setupFiles: ['./test/my-setup.ts'],
      coverage: { provider: 'v8' },
    },
    {
      services: {
        github: { mode: 'route', seed: 'small-project' },
        stripe: { mode: 'route' },
      },
    },
  ),
});
If you’re starting from scratch, pass {} as the first argument: withArchal({}, { services: { ... } }).

Or add a separate project in vitest.workspace.ts

For monorepos or when only a subset of tests should hit twins, use a workspace:
import { archalVitestProject } from 'archal/vitest';

export default [
  './vitest.config.ts', // your existing unit-test project untouched
  archalVitestProject(
    {
      name: 'hosted-twins',
      services: {
        github: { mode: 'route', seed: 'small-project' },
        stripe: { mode: 'route' },
      },
    },
    { include: ['__tests__/hosted/**/*.test.ts'] },
  ),
];
Only tests matching the include glob will provision hosted twins; the rest run as normal Vitest.

Write a test

Your test code uses normal SDK clients or direct HTTP calls. Route mode intercepts the HTTP traffic and redirects it to twins. No base URL configuration, no SDK mocking.
import { Octokit } from '@octokit/rest';
import { describe, it, expect } from 'vitest';

describe('issue triage', () => {
  it('creates and labels an issue', async () => {
    // route mode redirects api.github.com calls to the twin automatically
    const github = new Octokit();
    const { data: issue } = await github.issues.create({
      owner: 'acme',
      repo: 'webapp',
      title: 'Bug report',
    });
    expect(issue.title).toBe('Bug report');
  });
});
First run takes ~30 seconds for cold-start provisioning. Subsequent runs within the same 30-minute session TTL finish in ~2 seconds (the session is cached by (name, services, seeds) hash).

Seeds

Seeds control the twin’s starting state. Omit seed: to get a twin’s default empty state. Pass a named seed for a known fixture (e.g. small-project on GitHub gives you one repo with a few issues and PRs). Named seeds are documented per twin in Seeds.

Reset state between tests

import { beforeEach } from 'vitest';
import { resetArchalTwins } from 'archal/vitest';

beforeEach(async () => {
  await resetArchalTwins();
});
This restores each twin to its post-seed state and drains the webhook queue. No cold-start — it’s a local state snapshot reapplied to the existing session.

Inspect the session

If you need to check which services, seeds, or versions the backend resolved:
import { getInstalledArchalVitestSession } from 'archal/vitest';

const session = getInstalledArchalVitestSession();
console.log(session?.resolvedRuntime.resolvedServices);
console.log(session?.resolvedRuntime.resolvedSeeds);

Troubleshooting

  • Real API responses instead of twin responses — your test file isn’t matched by the project’s include glob.
  • 401 at setupARCHAL_TOKEN isn’t set (or archal login wasn’t run).
  • Test hangs for 30+ seconds on first run — that’s the ECS cold-start, not a hang.
  • Reset isn’t working — call resetArchalTwins() in beforeEach, not beforeAll.
  • CI credential race — when multiple jobs run in parallel, export ARCHAL_TOKEN directly instead of relying on ~/.archal/credentials.json.