Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .fallowrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
{
"$schema": "./node_modules/fallow/schema.json",
"minimumVersion": "3.22.0",
"entry": ["src/index.ts", "src/cli.ts", "scripts/*.mjs"],
"ignoreDependencies": ["postject"]
"entry": [
"src/index.ts",
"src/cli.ts",
"scripts/*.mjs",
"docs/assets/theme.css"
],
"ignoreDependencies": [
"postject",
"@docusaurus/theme-common",
"@mdx-js/react",
"react"
]
}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ dist/
.env.*
workstation.config.ts
workstation.lock

website/.docusaurus/
website/static/api/
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Unreleased

- Move the documentation website to Docusaurus with an ordered learning path, local search, complete developer-workstation walkthrough, conceptual guidance, focused resource recipes, and redirects for existing links.

- Publish the searchable handbook and API reference on GitHub Pages with guide navigation, responsive styling, and light/dark themes.

- Expand the documentation into a linked handbook with a first-run tutorial, feature recipes, operational workflows, embedded API examples, and troubleshooting; correct outdated lock, task, service, and ownership guidance.

## 0.6.2 — 2026-09-11

- Allow upgrades of adopted APT packages after refreshing their pins, while preserving their protection from automatic uninstall when removed from configuration.
Expand Down
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ See [managed setup, shell activation and interruption recovery](docs/managed-set

## Documentation

Read the **[documentation website](https://dovocode.github.io/workstation/)**, or
start with the [Workstation handbook](docs/README.md), including a feature index
and guides for both the CLI and TypeScript API.

- [First-run tutorial](docs/tutorial.md): a complete configuration you can try without installing packages.
- [Everyday workflows](docs/workflows.md): multiple machines, upgrades, migrations, removal, and rollback.
- [Files](docs/files.md), [shells](docs/shells.md), and [provisioning recipes](docs/provisioning.md): practical examples and policy choices.
- [Embedded API](docs/embedding.md): integration, custom runners, and isolated tests.
- [Troubleshooting](docs/troubleshooting.md): symptoms, diagnostics, and recovery steps.
- [Docker, Docker Sandboxes, and Microsandbox task integration](docs/environments.md)

### Use inside a TypeScript codebase
Expand Down Expand Up @@ -280,8 +289,9 @@ As with other file resources, declare each target only once.
- [Configuration and machines](docs/configuration.md)
- [Locks and recovery](docs/operations.md)

Run `corepack pnpm run docs` and open `dist/docs/index.html` for the generated
API reference and guides. `corepack pnpm check` and `corepack pnpm test` validate
Run `pnpm docs:dev` for the Docusaurus handbook with live reload. Use
`pnpm run docs` and `pnpm --filter @dovocode/workstation-docs serve` to preview
the production site, local search, and generated API reference. `corepack pnpm check` and `corepack pnpm test` validate
the package without applying a workstation configuration.

## Native binaries
Expand All @@ -291,6 +301,7 @@ without Node.js, npm, Corepack, or pnpm; selected Node-based tasks bootstrap the
pinned runtime through mise. Download
the binary for your platform and make it available as `workstation` on PATH.
The commands above automate those steps. macOS builds are ad-hoc signed, not notarized.
The config's package import must still resolve in its project.
Built-in config imports use the bundled API when no local package resolves;
third-party imports require explicit project dependencies.

To build locally: `corepack pnpm build:native`. Outputs are under `dist/bin/`.
135 changes: 111 additions & 24 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,111 @@
# Workstation documentation

Workstation describes your machine in TypeScript and executes the setup with
one CLI command. It manages packages, symlinks, generated configuration files,
custom executables, and user or system services on macOS and Linux.

## Guides

1. [Getting started](getting-started.md): prerequisites, build, first execution, CLI options.
2. [Configuration](configuration.md): imports, conditions, machines, paths, and overrides.
3. [Resources](resources.md): packages, files, JSONC, shells, and custom builds.
4. [Services](services.md): macOS LaunchAgents and Linux systemd units.
5. [Operations](operations.md): locks, updates, ownership, removal, and recovery.
6. [Tasks and aliases](tasks.md): named commands, argument forwarding, and shortcuts.
7. [API and development](development.md): embedding helpers and generating documentation.

8. [CLI reference](cli.md): commands, option placement, output and exit codes.
9. [Architecture](architecture.md): boundaries, storage, invariants and extension workflow.
10. [Environment tasks](environments.md): Docker, Docker Sandboxes and Microsandbox.

The generated API reference comes from source JSDoc. Bare `workstation` shows help;
`workstation build` applies configuration. The embedded `createWorkstation` API
supports inline or file-based definitions. The HTML roadmap is a proposal, not a
claim that every planned feature is implemented.
---
title: Your workstation, defined in TypeScript
slug: /
sidebar_label: Start here
---

Workstation turns a TypeScript configuration into a working macOS or Linux setup:
development runtimes, command-line tools, desktop applications, configuration
files, shell startup, and background services. Keep the inputs in Git, review the
changes, and run `workstation build` whenever the machine needs to match them.

## Start with a working setup

**New to Workstation?** Follow these guides in order. Each introduces the next
piece only after you have something working.

| Step | What you will learn | What you will have afterward |
| --- | --- | --- |
| **1. [Understand the model](concepts.md)** | Declarations, pins, ownership, and reconciliation | Know what a build will change and what it will preserve |
| **2. [Install Workstation](getting-started.md)** | Native executable, required managers, and configuration loading | A working `workstation` command |
| **3. [Build your first configuration](tutorial.md)** | Preview, create, update, run a task, and remove | A verified file-only setup you can safely explore |
| **4. [Build a developer workstation](developer-workstation.md)** | Combine packages, activation, dotfiles, platform differences, and tasks | A useful configuration you can adapt to your own machines |

The native executable includes its runtime. You can use built-in configuration
helpers without installing Node.js or creating a JavaScript project first.
Install the package locally when you want editor types or a pinned library version.

## What does a configuration look like?

```ts
import { defineConfig, files, task, tools } from "@dovocode/workstation";

const versions = { node: "lts", pnpm: "12.3.4" };

export default defineConfig({
resources: [
tools.mise(versions),
files.mise("~/.config/mise/config.toml", versions),
files.json("~/.config/example/settings.json", { theme: "dark" }),
],
tasks: {
hello: task("echo", ["Your setup is ready"], {
description: "An explicit command, separate from reconciliation",
}),
},
});
```

This declares tools to install, a mise file that selects their exact locked
versions, a generated settings file, and a named command. A declaration describes
the desired result. It does not install anything merely because you imported it.

```sh
workstation build # Prepare supported managers, resolve pins, apply the setup
workstation status # Check recorded declarations against the machine
workstation hello # Run only the explicit task
```

If the managers already exist, run `workstation plan` before a build to inspect
proposed changes. Generated files overwrite differing content by default and save
the original for restoration. Review existing files before adapting this example;
[choose a file policy](files.md#pick-the-existing-file-policy) when you only want
to manage a section or selected keys.

## Make it your own

Start with the change you actually want to make:

| Goal | Read next |
| --- | --- |
| Use one setup across your laptop and desktop | [Configuration, machines, and paths](configuration.md) |
| Choose the right abstraction for automation | [Design your setup](designing-your-setup.md) |
| Install runtimes, CLI tools, and desktop applications | [Packages and runtimes](resources.md) |
| Generate settings or bring dotfiles under management | [Files and existing content](files.md) |
| Make installed tools available in new terminals | [Shells and activation](shells.md) |
| Build your own executable from local source | [Custom tools](custom-tools.md) |
| Keep a background process running | [Services](services.md) |
| Configure repositories, seed app settings, and repair installations | [Provisioning](provisioning.md) |

## Use it every day

A build is not just a one-time installer. Run it after an intentional configuration
change or to reconcile a machine that has drifted. Keep your package pins stable
until you choose to refresh them.

- **[Everyday workflows](workflows.md):** add a machine, upgrade selected packages,
migrate dotfiles, move your checkout, and remove old declarations.
- **[Ownership and recovery](operations.md):** understand what is adopted, what is
removed, where originals live, and when snapshot rollback is possible.
- **[Troubleshooting](troubleshooting.md):** interpret diagnostics and recover without
losing the state needed to restore your original files.

## Go further

Use [tasks and aliases](tasks.md) for explicit project commands and
[post-apply hooks](tasks.md#post-apply-scripts) for repeatable follow-up work.
Use [Docker and sandbox tasks](environments.md) to control separate environments,
or [embed the client](embedding.md) in your own TypeScript application.

The [CLI reference](cli.md) provides exact command and option behavior.
The [generated API reference](https://dovocode.github.io/workstation/api/) lists
public helpers and types. Read [architecture](architecture.md) and
[development](development.md) when extending Workstation itself.

## Know the boundary

Workstation manages declared resources. It does not capture an entire machine,
back up application databases, purchase App Store software, or automatically
revert every package-manager transaction. Keep configuration and locks in Git;
keep ownership state and original-file backups private. Authentication and
application initialization remain explicit operations.
10 changes: 8 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
title: "Architecture and maintenance"
sidebar_label: "Architecture"
---

# Architecture and maintenance

This documents the implementation. The HTML roadmap describes future work.
Expand Down Expand Up @@ -49,8 +54,9 @@ state fingerprints describe resolved resources, including their applied pins.

Default state hashes the absolute configuration path and machine. An explicit
`stateFile` overrides isolation; moving a config changes the default namespace.
Legacy state requires deliberate reuse/migration. Separate namespaces do not yet
detect overlapping targets. Do not silently infer or transfer ownership.
Legacy state requires deliberate reuse/migration. A machine-local claim registry rejects overlapping resource IDs between registered
configurations. It cannot infer ownership from unregistered historical state.
Do not silently infer or transfer ownership.

Changing a resource shape requires updating config validation, manifest encoding and
decoding, and state validation. TypeScript types alone do not validate persisted data.
Expand Down
1 change: 1 addition & 0 deletions docs/assets/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 65 additions & 0 deletions docs/assets/theme.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Keep TypeDoc's accessible navigation, search, code controls, and theme switch. */
:root {
--light-color-background: #ffffff;
--light-color-background-secondary: #f5f8f7;
--light-color-background-active: #e3f2eb;
--light-color-active-menu-item: #e3f2eb;
--light-color-accent: #dce5e0;
--light-color-text: #263c33;
--light-color-contrast-text: #112c20;
--light-color-text-aside: #52675d;
--light-color-link: #087747;
--light-color-focus-outline: #087747;
--dark-color-background: #111b17;
--dark-color-background-secondary: #17251e;
--dark-color-background-active: #254333;
--dark-color-active-menu-item: #254333;
--dark-color-accent: #344b3e;
--dark-color-text: #d7e6dd;
--dark-color-contrast-text: #f1f8f4;
--dark-color-text-aside: #a4bbad;
--dark-color-link: #73dfaa;
--dark-color-focus-outline: #73dfaa;
--dim-toolbar-contents-height: 3.5rem;
}

body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
line-height: 1.65;
-webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { line-height: 1.25; color: var(--color-contrast-text); }
h1 { letter-spacing: -0.035em; font-size: clamp(2rem, 4vw, 2.75rem); }
h2 { letter-spacing: -0.02em; margin-top: 2.5rem; }
code, pre { font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; }
pre { padding: 1.25rem; border: 1px solid var(--color-accent); border-radius: 10px; line-height: 1.65; }
.tsd-typography p code, .tsd-typography li code, .tsd-typography td code {
padding: 0.15em 0.35em;
border-radius: 4px;
}
.tsd-typography > p:first-of-type { font-size: 1.08rem; color: var(--color-text-aside); }
.tsd-typography a { text-underline-offset: 3px; }
.tsd-typography table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; }
.tsd-typography th { text-align: left; background: var(--color-background-secondary); }
.tsd-typography td, .tsd-typography th { padding: 0.8rem 1rem; border: 1px solid var(--color-accent); }
.tsd-page-toolbar { border-bottom: 1px solid var(--color-accent); }
.tsd-page-toolbar .title { font-weight: 750; letter-spacing: -0.025em; }
.tsd-page-toolbar .title::before { content: ">_"; color: var(--color-link); margin-right: 0.7rem; font-family: monospace; }
.tsd-navigation a { border-radius: 5px; }
.tsd-page-title { margin-bottom: 2rem; }
.tsd-panel { border-radius: 10px; }
:focus-visible { outline: 2px solid var(--color-focus-outline); outline-offset: 3px; }

@media (min-width: 1200px) {
.container-main { gap: 2.5rem; }
}
@media (max-width: 767px) {
h1 { font-size: 2rem; }
pre { padding: 1rem; }
.tsd-typography td, .tsd-typography th { padding: 0.6rem 0.75rem; }
}
@media print {
body { color: #000; background: #fff; }
pre, .tsd-typography table { overflow: visible; white-space: pre-wrap; }
}
55 changes: 55 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
title: "CLI reference"
sidebar_label: "CLI commands"
---

# CLI reference

| Invocation | Behavior |
Expand Down Expand Up @@ -44,3 +49,53 @@ workstation upgrade package:mise:npm:@example/cli

Only declared packages are managed; unrelated global npm installations and
project `package.json` dependencies are outside this command's scope.

## Option placement examples

```sh
workstation build --config /path/setup.ts --machine studio --no-remove
workstation plan --config /path/setup.ts --frozen-lockfile
workstation --config /path/setup.ts --machine studio status
workstation --config /path/setup.ts --verbose doctor
workstation --config /path/setup.ts lock update package:mise:node
workstation --config /path/setup.ts history
workstation --config /path/setup.ts rollback RUN --apply
workstation --config /path/setup.ts --list-tasks
workstation --config /path/setup.ts test -- --watch
```

Replace paths, task names, and `RUN` with your actual configuration values.
`build`, `plan`, and `upgrade` parse global options alongside the command. The
other command names use task-style parsing: flags after their name become command
arguments and may be rejected. Put global flags before those names consistently.
`--config=PATH` is not supported; use separate arguments.

## Choosing a read-only command

| Command | Resolves new versions? | Runs resource inspections? | Writes Workstation data? |
| --- | --- | --- | --- |
| `--help`, `--version` | No | No configuration loading | No |
| `--list-tasks` | No | No; loads configuration | No |
| `doctor` | No | Package command availability and state validation | No |
| `status` | No | Recorded declarations and live state | No |
| `plan` | If needed, unless frozen | Yes | No |
| `history` | No | Reads recovery identifiers | No |
| `rollback RUN` | May query exact mise availability | Restoration preconditions | No |
| `lock update` | Yes | Version queries | Lock only |

Executable configuration can perform its own side effects during loading. Read-only
provision checks must really be read-only, and native metadata queries may maintain
their own caches. Planning does not install missing managers or repositories.

## Output and failures

Builds show loading, version resolution, inspections, planned changes, and results.
`--verbose`/`-v` includes command traces, per-resource inspection detail, query
output, and exit timings. Mutations and CLI tasks stream output. Machine-readable
JSON output is not implemented; use the embedded API for structured results.

`--no-remove` rejects actual removal actions during build/upgrade, but permits
ownership-only forget actions. Although the parser accepts it for `plan`, it does
not filter or reject that plan's output. It is not a general no-mutation switch.
A failed build can have completed earlier actions; inspect the failure and rerun
after fixing its cause. See [recovery](workflows.md#recover-after-a-failed-or-interrupted-build).
Loading
Loading