# Development Setup
Source: https://dorkos.ai/docs/contributing/development-setup

Set up a local development environment for DorkOS



{/* Internal deep-dive (repo-only): contributing/development-workflow.md - keep in sync */}

# Development Setup [#development-setup]

Get DorkOS running locally for development.

## Prerequisites [#prerequisites]

<Callout type="info">
  DorkOS requires Node.js 22 or later. Check with 

  `node --version`

  .
</Callout>

* **Node.js 22+**
* **pnpm 10+**
* **A Claude API key** from [console.anthropic.com](https://console.anthropic.com/)

## Installation [#installation]

<Steps>
  <Step>
    ### Clone and install [#clone-and-install]

    ```bash
    git clone https://github.com/dork-labs/dorkos.git
    cd dorkos
    pnpm install
    ```
  </Step>

  <Step>
    ### Configure environment [#configure-environment]

    ```bash
    cp .env.example .env
    ```

    Edit `.env` and set `ANTHROPIC_API_KEY=your-key-here`.
  </Step>

  <Step>
    ### Start development servers [#start-development-servers]

    ```bash
    pnpm dev
    ```

    This starts both the Express server (port 6242) and the Vite dev server (port 6241). Open [http://localhost:6241](http://localhost:6241) in your browser.
  </Step>
</Steps>

### Running Individual Apps [#running-individual-apps]

<Tabs items="['Server only', 'Client only']">
  <Tab value="Server only">
    `bash dotenv -- turbo dev --filter=@dorkos/server `
  </Tab>

  <Tab value="Client only">
    `bash dotenv -- turbo dev --filter=@dorkos/client `
  </Tab>
</Tabs>

<Callout type="warn">
  Always use `pnpm` scripts or prefix commands with `dotenv --` to ensure `.env` is loaded. Bare
  `turbo` commands do not pick up environment variables.
</Callout>

## Common Commands [#common-commands]

<TypeTable
  type="{
  'pnpm dev': { type: 'command', description: 'Start all dev servers' },
  'pnpm dev:dogfood': {
    type: 'command',
    description:
      'Run the hot-reloading dev preview (:6241) alongside the built CLI in production mode (:4242): work in one, build the other',
  },
  'pnpm test': { type: 'command', description: 'Run all tests (Vitest, watch mode)' },
  'pnpm test -- --run': { type: 'command', description: 'Single test run (no watch)' },
  'pnpm build': { type: 'command', description: 'Build all packages' },
  'pnpm typecheck': { type: 'command', description: 'Type-check all packages' },
  'pnpm lint': { type: 'command', description: 'ESLint across all packages' },
  'pnpm lint -- --fix': { type: 'command', description: 'Auto-fix ESLint issues' },
  'pnpm format': { type: 'command', description: 'Prettier format all files' },
  'pnpm format:check': { type: 'command', description: 'Check formatting without writing' },
}"
/>

## Docker & Smoke Tests [#docker--smoke-tests]

<TypeTable
  type="{
  'pnpm smoke:docker': { type: 'command', description: 'CLI install smoke test in Docker' },
  'pnpm smoke:integration': {
    type: 'command',
    description: 'Full integration test (server + API + client in Docker)',
  },
  'pnpm smoke:npm': {
    type: 'command',
    description: 'Integration test against published npm package',
  },
  'pnpm docker:build': {
    type: 'command',
    description: 'Build runnable Docker image from local code',
  },
  'pnpm docker:run': { type: 'command', description: 'Run DorkOS in Docker (build first)' },
  'pnpm publish:cli': { type: 'command', description: 'Publish dorkos CLI to npm' },
}"
/>

## Running Specific Tests [#running-specific-tests]

```bash
pnpm vitest run apps/server/src/services/session/__tests__/transcript-reader.test.ts
```

## Monorepo Structure [#monorepo-structure]

<Files>
  <Folder name="apps">
    <Folder name="client">
      <File name="package.json" />
    </Folder>

    <Folder name="server">
      <File name="package.json" />
    </Folder>

    <Folder name="site">
      <File name="package.json" />
    </Folder>

    <Folder name="obsidian-plugin">
      <File name="package.json" />
    </Folder>

    <Folder name="e2e">
      <File name="package.json" />
    </Folder>
  </Folder>

  <Folder name="packages">
    <Folder name="cli">
      <File name="package.json" />
    </Folder>

    <Folder name="shared">
      <File name="package.json" />
    </Folder>

    <Folder name="db">
      <File name="package.json" />
    </Folder>

    <Folder name="relay">
      <File name="package.json" />
    </Folder>

    <Folder name="mesh">
      <File name="package.json" />
    </Folder>

    <Folder name="typescript-config">
      <File name="package.json" />
    </Folder>

    <Folder name="eslint-config">
      <File name="package.json" />
    </Folder>

    <Folder name="icons">
      <File name="package.json" />
    </Folder>

    <Folder name="test-utils">
      <File name="package.json" />
    </Folder>
  </Folder>

  <File name="turbo.json" />

  <File name="vitest.config.ts" />

  <File name="package.json" />
</Files>

| Directory                    | Package                     | Description                                     |
| ---------------------------- | --------------------------- | ----------------------------------------------- |
| `apps/client`                | `@dorkos/client`            | React 19 SPA (Vite 6, Tailwind 4, shadcn/ui)    |
| `apps/server`                | `@dorkos/server`            | Express API server                              |
| `apps/site`                  | `@dorkos/site`              | Marketing site & docs (Next.js 16, Fumadocs)    |
| `apps/obsidian-plugin`       | `@dorkos/obsidian-plugin`   | Obsidian sidebar plugin                         |
| `apps/e2e`                   | `@dorkos/e2e`               | Playwright browser tests                        |
| `packages/cli`               | `dorkos`                    | Publishable npm CLI                             |
| `packages/shared`            | `@dorkos/shared`            | Zod schemas, shared types, Transport interface  |
| `packages/db`                | `@dorkos/db`                | Drizzle ORM schemas (SQLite)                    |
| `packages/relay`             | `@dorkos/relay`             | Inter-agent messaging                           |
| `packages/mesh`              | `@dorkos/mesh`              | Agent discovery & registry                      |
| `packages/typescript-config` | `@dorkos/typescript-config` | Shared tsconfig presets                         |
| `packages/eslint-config`     | `@dorkos/eslint-config`     | Shared ESLint presets (base, react, node, test) |
| `packages/icons`             | `@dorkos/icons`             | SVG icon & logo registry                        |
| `packages/test-utils`        | `@dorkos/test-utils`        | Mock factories, test helpers                    |

## Next Steps [#next-steps]

<Cards>
  <Card title="Architecture" href="/docs/contributing/architecture">
    Hexagonal architecture, Transport interface, and data flow
  </Card>

  <Card title="Testing" href="/docs/contributing/testing">
    Testing patterns, conventions, and how to write component and service tests
  </Card>

  <Card title="API Reference" href="/docs/api">
    REST and SSE endpoints
  </Card>
</Cards>
