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
94 changes: 94 additions & 0 deletions docs/src/content/docs/guides/new-machine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: Set up a new machine
description: Bring your configuration to a new computer, by hand or with a bootstrap script.
sidebar:
order: 1
---

This guide takes a machine from nothing to your configuration, using a dotfiles repository you already have. If you don't have one yet, start with [Your first dotfiles repository](/getting-started/tutorial/).

## 1. Install configfile

On macOS, install [Homebrew](https://brew.sh) first if it isn't there yet, then:

```sh
brew install mindsers/tap/configfile
```

Homebrew also installs Node.js and git. [Installation](/getting-started/installation/) lists the other ways.

## 2. Give the machine access to your repository

For a private repository, the machine needs your git credentials before *configfile* can clone it: add an SSH key to your git host, or sign in with its command line tool (`gh auth login` for GitHub). A public repository can be cloned with its `https://` URL without credentials.

Avoid putting a token in the repository URL: *configfile* saves the URL in `~/.configfilerc`, and warns when it contains credentials.

## 3. Connect configfile to the repository

```sh
configfile init
```

*configfile* asks for the repository's URL and clones it into `~/.configfile/dotfiles`.

## 4. Deploy your modules

See what would be deployed, and what is in the way:

```sh
configfile modules status
configfile modules deploy --all --dry-run
```

Then deploy every module:

```sh
configfile modules deploy --all
```

Files that already exist where yours go, such as the default `~/.zshrc` of a new machine, are moved aside to `.old`, so you can compare them or bring them back with `configfile modules undeploy`.

## 5. Run your setup script

If your repository has a setup script, for example to install your tools, run it:

```sh
configfile scripts run setup
```

With a version per system (`setup.macos.sh`, `setup.linux.sh`), *configfile* picks the one for this machine. See [Scripts](/reference/scripts/).

## 6. Copy local files into your projects

Local files, such as an `.editorconfig`, are copied into the current folder rather than linked. In each project that needs them:

```sh
cd ~/projects/my-project
configfile modules deploy --all --local
```

## Do it all with one script

To set up machines regularly, put the steps in a script. Without a terminal to ask questions in, *configfile* needs everything as options: `--repo` for `init`, and module names or `--all` for `modules deploy`. [Use configfile in scripts and CI](/guides/scripts-and-ci/) lists them.

```sh title="bootstrap.sh"
#!/bin/sh
set -e

brew install mindsers/tap/configfile
configfile init --repo git@github.com:me/dotfiles.git
configfile modules deploy --all
configfile scripts run setup
```

`set -e` stops the script at the first step that fails: *configfile* exits with a non-zero code when a command fails. On a machine that already has a configuration, `init` refuses to replace it without `--force`.

## Keep the machine in sync

When you push changes to your repository, bring them to the machine with:

```sh
configfile update
```

Linked files are up to date right away. Run `configfile modules deploy --all` again when you add files or modules, as `update` reminds you, and `configfile modules undeploy --removed` to remove what the repository no longer deploys, which `update` warns about.
94 changes: 94 additions & 0 deletions docs/src/content/docs/guides/scripts-and-ci.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
title: Use configfile in scripts and CI
description: Run configfile without a terminal, rely on its exit codes, and check a dotfiles repository on every push.
sidebar:
order: 2
---

Every *configfile* command can run without anyone at the keyboard: in a bootstrap script, a cron job, or a CI workflow. This guide covers what changes without a terminal, and how to check your dotfiles repository automatically.

## Answering questions with options

When it runs in a terminal, *configfile* asks for what it needs. When its input is not a terminal, it can't ask: a command that would need an answer stops with an error that names the option to pass instead.

```txt
$ configfile modules deploy < /dev/null
Error No module given. Pass module names, or --all to deploy every module.
```

| Command | Question in a terminal | Option to pass instead |
| --- | --- | --- |
| `configfile init` | the repository's URL | `--repo <url>` |
| `configfile init` | whether to replace an existing configuration | `--force` |
| `configfile modules deploy` and `undeploy` | whether to use every module | module names, or `--all` |
| `configfile modules deploy --local` | whether to replace an existing file that differs | `--force` (without it, the file is skipped and the command fails) |

`configfile init --folder <path>` also lets a script choose where the repository is cloned. The [commands reference](/reference/commands/) lists every option.

## Exit codes

*configfile* exits with:

- `0` when the command succeeded;
- another code when it failed, with an error message saying why: usually `1`, or git's own code when a git command fails (for example `128` when the repository can't be fetched);
- the script's own exit code with `configfile scripts run`, so a failing setup script fails the step that runs it;
- `130` when you press Ctrl+C at a question.

In a shell script, `set -e` therefore stops at the first *configfile* command that fails.

## Output

With `configfile scripts run`, *configfile*'s own messages go to stderr and the script's output to stdout, unchanged: you can pipe or redirect the script's output as if you had run it directly.

`configfile history --json` prints the [history](/reference/history/) as JSON Lines, one run per line, for scripts that need to know what *configfile* did.

## Check your dotfiles repository on every push

A mistake in a `settings.json`, such as invalid JSON, a missing `target_path`, or a target *configfile* refuses, is usually found on the next machine you set up. A CI workflow can find it when you push, by deploying the repository into a throwaway home folder with `--dry-run`: *configfile* reads every module and entry, checks every target, and exits with `1` if anything can't be deployed.

With GitHub Actions, add this workflow to your dotfiles repository:

```yaml title=".github/workflows/check.yml"
name: Check dotfiles

on: [push, pull_request]

permissions:
contents: read

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
- run: npm install --global https://github.com/mindsers/configfile/releases/download/1.0.0/configfile-1.0.0.tgz
# The following steps use a throwaway home folder, not the runner's.
- run: |
mkdir -p "$RUNNER_TEMP/home"
echo "HOME=$RUNNER_TEMP/home" >> "$GITHUB_ENV"
- run: configfile init --repo "$GITHUB_WORKSPACE"
- run: configfile modules deploy --all --dry-run
```

`init` accepts a local folder as the repository, here the checkout of the commit being tested. Nothing is deployed for real, and the runner's home folder isn't touched. The dry run fails if any module or entry is invalid, even when the others are fine, local files included. A file whose entry has no `deploy` strategy only produces a warning, as it does on your machines.

To also test your setup script, add a step that runs it, on the systems it supports:

```yaml
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
# … the steps above, then:
- run: configfile scripts run setup
```

Run it only if the script is safe to run on a fresh CI machine: it installs and changes things for real, as on your own computer.

:::tip
In your editor, the [JSON Schema of `settings.json`](/reference/modules/#completion-and-validation-in-your-editor) catches most of these mistakes before you even commit.
:::
2 changes: 2 additions & 0 deletions docs/src/content/docs/guides/upgrading-from-0-3.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
---
title: Upgrading from 0.3
description: What changes for users of configfile 0.3.
sidebar:
order: 3
---

- Node.js 24.11 or later is required, on macOS or Linux. Install again as described in [Installation](/getting-started/installation/). To switch to Homebrew, remove the npm version first (`npm uninstall --global configfile`).
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ description: Manage your dotfiles and setup scripts from a git repository, on ma
- [How it works](/concepts/how-it-works/): your repository, the mirror configfile keeps, and what it deploys.
- [Safety and trust](/concepts/safety/): what configfile protects, and what it refuses to touch.
- Reference: [commands](/reference/commands/), [modules and `settings.json`](/reference/modules/), [scripts](/reference/scripts/), [configuration](/reference/configuration/), [history](/reference/history/).
- [Upgrading from 0.3](/guides/upgrading-from-0-3/).
- Guides: [set up a new machine](/guides/new-machine/), [use configfile in scripts and CI](/guides/scripts-and-ci/), [upgrade from 0.3](/guides/upgrading-from-0-3/).
- [Changelog](https://github.com/mindsers/configfile/blob/develop/CHANGELOG.md): what changed in each version.

## Contribution
Expand Down
Loading