Files changed: - .gitignore - CHANGES.md - VERSION - docs/explanation/architecture.md - docs/explanation/pipeline-rationale.md - docs/how-to/README.md - docs/how-to/back-up-to-a-synced-folder.md - docs/how-to/collect-from-a-synced-folder.md - docs/how-to/ingest-a-source.md - docs/how-to/set-up-the-mcp-server.md - docs/reference/commands/README.md - docs/reference/commands/git.md - docs/reference/commands/instance-health.md - docs/reference/commands/raw-material-and-uploads.md - docs/reference/configuration.md - instructions/gates.md - instructions/ingest-queue.md - instructions/mcp-read-server.md - instructions/migrations/10.0.0-settings-tiers.md - instructions/wiki-ingest/SKILL.md - raw/CONTRACT.md - tools/CONTRACT.md - tools/README.md - tools/chemenu/cli_contract.py - tools/chemenu/collect.py - tools/chemenu/commands/backup_cmd.py - tools/chemenu/commands/docs_verify.py - tools/chemenu/commands/doctor.py - tools/chemenu/commands/raw/pending.py - tools/chemenu/commands/upload_cmd.py - tools/chemenu/config.py - tools/chemenu/config_shapes.py - tools/chemenu/legacy_settings.py - tools/chemenu/mcp/server.py - tools/chemenu/reference_doc.py - tools/chemenu/tests/test_backup.py - tools/chemenu/tests/test_collect.py - tools/chemenu/tests/test_config_shapes.py - tools/chemenu/tests/test_doctor.py - tools/chemenu/tests/test_legacy_settings.py - tools/chemenu/tests/test_mcp_server.py - tools/chemenu/tests/test_upload.py - tools/chemenu/tests/test_upload_cmd.py - tools/chemenu/upload.py Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
159 lines
8.3 KiB
Markdown
159 lines
8.3 KiB
Markdown
# Back up to a synced folder
|
|
|
|
Back an instance up into a folder a sync client uploads - OneDrive, or any other client that keeps a
|
|
local folder in step with a server - when there is no git server to push to. The instance itself
|
|
stays in a folder the sync client does not touch; the synced folder receives a git repository to
|
|
push to and a copy of the files on this machine that are not in git. What the settings look like:
|
|
[configuration reference](../reference/configuration.md#backup-to-a-synced-folder).
|
|
|
|
<!-- wikitool:toc -->
|
|
## Contents
|
|
|
|
- [Why the instance does not live in the synced folder](#why-the-instance-does-not-live-in-the-synced-folder)
|
|
- [Set it up](#set-it-up)
|
|
- [What is backed up, and what is not](#what-is-backed-up-and-what-is-not)
|
|
- [Restore](#restore)
|
|
- [One device writes](#one-device-writes)
|
|
<!-- /wikitool:toc -->
|
|
|
|
## Why the instance does not live in the synced folder
|
|
|
|
Putting the whole instance - `.git` included - into the synced folder looks like the simplest
|
|
backup, and fails in three ways:
|
|
|
|
- **Locks.** On Windows, OneDrive holds a file it is uploading open for a moment. `git gc` and
|
|
`git repack` then fail to delete or replace a file under `.git` ("unlink failed").
|
|
- **Placeholders.** With Files On-Demand, the client offloads files it considers unused and leaves a
|
|
placeholder behind; git then reads objects that first have to be downloaded, or are not there
|
|
when the machine is offline.
|
|
- **Conflict copies.** As soon as a second device syncs the same folder, two writers meet inside
|
|
`.git`, and the client resolves that by making copies of the files both changed - a repository
|
|
git can no longer read.
|
|
|
|
So the instance lives outside the synced folder, and the synced folder gets a layout git writes to
|
|
in a way a sync client handles well:
|
|
|
|
```
|
|
<target>/git/ a bare repository - origin of the instance; publish pushes to it
|
|
<target>/<machine>/ a copy of this machine's files that are not in git, plus .chemenu-backup.json
|
|
```
|
|
|
|
Git writes into the bare repository only on a push, and then mostly adds new files that never
|
|
change again.
|
|
|
|
`tools/wikitool doctor` reports `sync-folder` as a `WARN` when the instance's git directory lies in
|
|
a synced folder. On Windows, check that line even if you never chose such a folder: when Documents
|
|
or Desktop is redirected into OneDrive (Known Folder Move), an instance under Documents lies in
|
|
OneDrive without looking like it. Move the instance to a folder outside it - `C:\Wiki\<name>`, say -
|
|
before you go on.
|
|
|
|
## Set it up
|
|
|
|
1. **Pick the target**: a folder inside the synced folder, for example
|
|
`C:\Users\<you>\OneDrive - <company>\Chemenu-Backup`. It must not lie inside the instance.
|
|
2. **Write the `backup` section** into `.wikitool-local.json` at the root of the instance - by hand,
|
|
since its fields decide what leaves this machine and `config set` refuses them:
|
|
|
|
```json
|
|
{
|
|
"backup": {
|
|
"target": "C:\\Users\\<you>\\OneDrive - <company>\\Chemenu-Backup",
|
|
"machine_data": true,
|
|
"machine_name": "WORK-LAPTOP",
|
|
"extra": [".claude/settings.local.json"]
|
|
}
|
|
}
|
|
```
|
|
|
|
Backslashes in a JSON string are doubled. `machine_name` defaults to the computer's host name;
|
|
`extra` lists further paths inside the instance to copy, and can be left out.
|
|
3. **Tell the agent:**
|
|
|
|
> Set up the backup target from the `backup` section.
|
|
|
|
The agent runs `tools/wikitool backup init`. It creates `<target>/git` as a bare repository and
|
|
makes it `origin` - unless the instance already has an `origin` that points elsewhere: then it
|
|
changes nothing and shows you both URLs, and whether `origin` moves is yours to decide
|
|
(`git remote set-url origin "<target>\git"`).
|
|
4. **Allow the push target**, if your `.wikitool-local.json` has a `remotes` section: `backup init`
|
|
then prints that section with `<target>\git` added. Copy it into the file yourself - the list is
|
|
the Publish-Remote Gate, and no agent edits it. Without a `remotes` section there is nothing to do.
|
|
5. **Publish.** The next `tools/wikitool publish` pushes the whole history to `<target>/git` and,
|
|
with `machine_data` on, copies the machine data into `<target>/<machine>/`. From then on every
|
|
publish that pushes does both. `tools/wikitool backup run` copies the machine data on its own,
|
|
whenever you want it current without publishing - after dropping a file into `incoming/`, for
|
|
instance, which is otherwise only copied by the next publish.
|
|
6. **Check it:** `tools/wikitool doctor`. The `backup` line names the target and how old the last
|
|
copy of the machine data is; a `WARN` there names what is missing.
|
|
|
|
If a publish reports a `WARN` that the machine-data backup failed, the commit and the push have
|
|
still happened. Fix what the line names - a synced folder that is not there, a folder that is not
|
|
writable - and run `tools/wikitool backup run`. Another publish does not help: it has nothing new to
|
|
push.
|
|
|
|
## What is backed up, and what is not
|
|
|
|
| Path | Backed up | Why |
|
|
|------|-----------|-----|
|
|
| Everything committed (`kb/`, `raw/`, `wikitool.json`, ...) | yes, in `<target>/git` | that is what `publish` pushes |
|
|
| `.wikitool-local.json` | yes | the settings of this checkout |
|
|
| `ENVIRONMENT.md` | yes, if present | written by hand |
|
|
| Everything in `incoming/` but `.gitkeep` | yes | sources waiting there are backed up nowhere else |
|
|
| The `extra` paths | yes | what you named |
|
|
| `quarantine/` | no | material that arrived through an intake channel and that nobody has reviewed yet |
|
|
| `reports/` | no | regenerated by `lint`; telemetry holds prompts |
|
|
| `.wikitool-tools.json`, `tools/.venv/`, the published skills | no | the preflight and `instructions sync` rebuild them |
|
|
| The secrets file | **never** | it lies outside the instance, and a backup reads nothing outside it |
|
|
|
|
**Private values reach the synced folder.** `.wikitool-local.json` is copied as it is, so a plain
|
|
private value in it - an internal host name, an internal URL - ends up in OneDrive. A secret does
|
|
not: a secret is never in that file, only a reference to it, and the secrets file it resolves
|
|
through (`%APPDATA%\chemenu\<instance_id>\secrets.json`, with the sessions `raw login` stored)
|
|
lies outside the instance. An `extra` path that leads outside the instance - through `..` or a
|
|
link - is refused, so no setting can copy it either.
|
|
|
|
In `<target>/<machine>/` a run writes and deletes only what is its own: it removes a file only when
|
|
its previous run copied it and the instance no longer has it (a source `raw accept` moved out of
|
|
`incoming/`, say), and refuses a folder that is not empty and has no `.chemenu-backup.json`, rather
|
|
than copying into somebody else's folder. A link inside a copied directory is skipped and named,
|
|
never followed.
|
|
|
|
## Restore
|
|
|
|
On the same machine or a new one:
|
|
|
|
1. **Clone the repository and check it:**
|
|
|
|
```bash
|
|
git clone "<target>/git" "<new folder>"
|
|
cd "<new folder>"
|
|
git fsck --full
|
|
```
|
|
|
|
The clone is outside the synced folder, like the original; its `origin` is the bare repository
|
|
already.
|
|
2. **Copy the machine data back**: everything in `<target>/<machine>/` except
|
|
`.chemenu-backup.json`, into the new folder, keeping the paths. On Windows:
|
|
`robocopy "<target>\<machine>" "<new folder>" /E /XF .chemenu-backup.json`; elsewhere:
|
|
`rsync -a --exclude .chemenu-backup.json "<target>/<machine>/" "<new folder>/"`.
|
|
3. **Bootstrap the checkout** - tell the agent:
|
|
|
|
> Bootstrap this checkout.
|
|
|
|
It follows [instructions/bootstrap.md](../../instructions/bootstrap.md): the preflight, the
|
|
published skills, `doctor`.
|
|
4. **Provide the secrets again.** They were never in the backup. Put each value back where its
|
|
reference reads it - 1Password, the secrets file, or a `WIKITOOL_SECRET_<NAME>` variable
|
|
([use-1password-for-settings.md](use-1password-for-settings.md)) - and sign in again with
|
|
`raw login` for each host that needs it. `doctor`'s `settings-secrets` line names every reference
|
|
that does not resolve yet.
|
|
|
|
`doctor` must then run through without a `FAIL`.
|
|
|
|
## One device writes
|
|
|
|
Only one device publishes to `<target>/git`. Two devices pushing into the same synced folder are two
|
|
writers again, only one step removed - and the sync client resolves that with conflict copies, not
|
|
with a merge. An instance on a second device gets a target of its own. The sync client is a backup
|
|
here, not a way to work on one instance from two devices.
|