Files changed: - CHANGES.md - VERSION - 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/export-guidelines.md - docs/how-to/export-to-a-synced-folder.md - docs/reference/commands/README.md - docs/reference/commands/exports.md - docs/reference/commands/git.md - docs/reference/commands/guideline-export.md - docs/reference/commands/instance-health.md - docs/reference/commands/raw-material-and-uploads.md - docs/reference/configuration.md - docs/reference/exit-codes.md - instructions/setup-instance.md - raw/CONTRACT.md - tools/CONTRACT.md - tools/README.md - tools/chemenu/backup.py - tools/chemenu/cli_contract.py - tools/chemenu/commands/doctor.py - tools/chemenu/commands/export_cmd.py - tools/chemenu/commands/git_publish.py - tools/chemenu/commands/raw/_common.py - tools/chemenu/commands/raw/accept.py - tools/chemenu/commands/raw/capture.py - tools/chemenu/config_shapes.py - tools/chemenu/guideline_export.py - tools/chemenu/page_export.py - tools/chemenu/reference_doc.py - tools/chemenu/repo_capture.py - tools/chemenu/tests/test_config_shapes.py - tools/chemenu/tests/test_export_run.py Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
8.5 KiB
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.
Contents
- Why the instance does not live in the synced folder
- Set it up
- What is backed up, and what is not
- Restore
- One device writes
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 gcandgit repackthen 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
-
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. -
Write the
backupsection into.wikitool-local.jsonat the root of the instance - by hand, since its fields decide what leaves this machine andconfig setrefuses them:{ "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_namedefaults to the computer's host name;extralists further paths inside the instance to copy, and can be left out. -
Tell the agent:
Set up the backup target from the
backupsection.The agent runs
tools/wikitool backup init. It creates<target>/gitas a bare repository and makes itorigin- unless the instance already has anoriginthat points elsewhere: then it changes nothing and shows you both URLs, and whetheroriginmoves is yours to decide (git remote set-url origin "<target>\git"). -
Allow the push target, if your
.wikitool-local.jsonhas aremotessection:backup initthen prints that section with<target>\gitadded. Copy it into the file yourself - the list is the Publish-Remote Gate, and no agent edits it. Without aremotessection there is nothing to do. -
Publish. The next
tools/wikitool publishpushes the whole history to<target>/gitand, withmachine_dataon, copies the machine data into<target>/<machine>/. From then on every publish that pushes does both.tools/wikitool backup runcopies the machine data on its own, whenever you want it current without publishing - after dropping a file intoincoming/, for instance, which is otherwise only copied by the next publish. -
Check it:
tools/wikitool doctor. Thebackupline names the target and how old the last copy of the machine data is; aWARNthere 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:
-
Clone the repository and check it:
git clone "<target>/git" "<new folder>" cd "<new folder>" git fsck --fullThe clone is outside the synced folder, like the original; its
originis the bare repository already. -
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>/". -
Bootstrap the checkout - tell the agent:
Bootstrap this checkout.
It follows instructions/bootstrap.md: the preflight, the published skills,
doctor. -
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) - and sign in again withraw loginfor each host that needs it.doctor'ssettings-secretsline 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.
A folder the sync client uploads can also hold a read-only version of selected pages, for readers outside the repository: Export pages to a synced folder. It is a separate folder with its own settings, and never the backup target.