Syncing a workspace with the Deepnote CLI
Mirror your Deepnote workspace to a local directory with deepnote sync, and push local notebook edits back to the cloud
deepnote sync mirrors your whole Deepnote workspace into a local directory and pushes local edits
back. Every project becomes a directory holding one .deepnote file per notebook, laid out along
your workspace's folder tree.
deepnote sync ./workspace
Prerequisites
- The Deepnote CLI. Install it with
npm install -g @deepnote/cli(or run it throughnpx @deepnote/cli). - An API token with access to the workspace you are mirroring.
Authentication
The CLI reads your token from the DEEPNOTE_TOKEN environment variable, or from an explicit
--token flag. Create a token in your workspace under
Settings & members → API tokens.
export DEEPNOTE_TOKEN="<your-token>"
deepnote sync ./workspace
Without a token the command exits with code 2 and prints where to get one.
Token safety
- Prefer the environment variable. A token passed as
--tokenis visible in your shell history and in the process list of a shared machine. - In CI or a cron job, use a secret from your provider's secret store, exposed as
DEEPNOTE_TOKENfor that step only. - Rotate and revoke from the same settings page if a token is ever exposed.
- The token decides which workspace you are mirroring. Pointing a sync directory at a different workspace's token is the most common cause of a confusing first run — see Safety rails.
What the local directory looks like
A project maps to a directory, because a project's export is one .deepnote document per notebook
rather than a single file:
workspace/
├── .deepnote-sync.json # sync state (safe to commit)
├── Analytics/ # a workspace folder
│ └── Sales report/ # a project
│ ├── main.deepnote # one file per notebook
│ ├── forecast.deepnote
│ └── .files/ # working-directory files (--all-files only)
│ ├── requirements.txt
│ └── data/input.csv
└── Scratch project/
└── main.deepnote
.deepnote-sync.json is sync's state file. It maps project IDs to local directories and records
fingerprints of what was last synced, which is how sync tells "you edited this" from "someone edited
it in Deepnote." Projects are tracked by ID, not by name, so renaming a project or moving it between
folders in Deepnote becomes a directory move locally rather than a delete and re-download. The file
is plain JSON with sorted keys, so it diffs cleanly if you commit it.
Both directions
Sync decides per project which way to move, purely by comparing content:
- Pull — the project changed in Deepnote, or does not exist locally yet. The exported documents are written down.
- Push — the project changed only locally. The same documents are uploaded back, with lost-update protection: if the cloud copy moved since your last sync, the upload is rejected and becomes a conflict rather than a silent overwrite.
- Unchanged — both sides match.
- Conflict — the project changed both locally and in Deepnote.
Project names and integration attachments are applied from the documents on push. Notebook outputs are not part of the format, so they never sync.
Conflicts
By default sync asks, per project, whether to keep the cloud version (discarding your local changes) or skip the project for now.
# Answer up front instead of being prompted
deepnote sync ./workspace --on-conflict skip
deepnote sync ./workspace --on-conflict override
| Mode | Behavior |
|---|---|
ask | Prompt per conflicting project (default) |
skip | Leave every conflicting project untouched |
override | Overwrite local changes with the cloud version |
Working-directory files
By default sync handles notebooks only. --all-files also mirrors each project's
working-directory files — data files, requirements.txt, anything else in the project — into a
.files/ subdirectory:
deepnote sync ./workspace --all-files
Files follow their project's direction: a pulled project downloads changed files, a pushed project uploads them. Downloads are incremental, so unchanged files are not re-fetched.
Before uploading any file, sync checks its current state in Deepnote. A file that changed — or was
deleted — since sync last recorded it goes through the same --on-conflict choice as a diverged
notebook, and skipped files are reported as N file(s) kept from Deepnote. This matters because
sync is not the only writer of a project's files: deepnote publish
deploys into the static root, and anyone editing the project in Deepnote can change files too.
Options
| Option | Description | Default |
|---|---|---|
--all-files | Also sync working-directory files (download on pull, upload on push) | false |
--on-conflict <mode> | Conflict handling: ask, skip, or override | ask |
--delete-missing-notebooks | On push, delete cloud notebooks removed from the local project | false |
--prune | Delete local files for projects and files that no longer exist in the cloud | false |
--dry-run | Report what would be synced without writing anything | false |
--token <token> | API token | DEEPNOTE_TOKEN |
--url <url> | API base URL (for single-tenant instances) | https://api.deepnote.com |
-o, --output <format> | Machine-readable output: json or llm | text |
Ownership of the static site directory
A project's published static website lives under _deepnote_static in the same file store that
--all-files mirrors, so it appears in .files/_deepnote_static/ like any other project file. The
two commands share one rule:
deepnote publishwrites it. That is the deploy command, and the only one that should author those files. Its source of truth is your local build directory.deepnote syncmirrors it and never silently overwrites it. The per-file check described above applies to the static root too, so a site someone republished after your last sync is surfaced as a conflict instead of being reverted to your older local copy.- A publish inside a synced workspace keeps the mirror in step. Publishing updates the local
mirror and
.deepnote-sync.jsonfor you, so the next sync does not see the deploy as drift and re-download the whole site.
Deleting things
Sync is deliberately conservative about deletion, in both directions.
- Pulls remove local
.deepnotefiles for notebooks that no longer exist in the cloud export. --pruneis required before sync deletes a local directory for a project that no longer exists in the cloud, or a local working file that no longer exists in the project.--delete-missing-notebooksis required before a push deletes cloud notebooks you removed locally.- Files removed locally are never deleted in the cloud by
--all-filesalone; that is too destructive to infer.
Safety rails
- Sync never creates or deletes cloud projects. Local
.deepnotefiles outside a tracked project directory are reported and left alone. Usedeepnote opento import one. - Pruning is refused when none of the tracked project IDs match the workspace the API returned.
That combination almost always means the token or
--urlpoints at a different workspace, and pruning on that assumption would delete a correct local mirror. Verify the connection and retry. - A stale tracking entry cannot delete a directory whose path is now used by a current cloud project; only the stale tracking is removed.
- Sync does not run Git. It writes ordinary files. Committing, branching, and pushing are yours to do — which is the main difference from Deepnote file sync, where Deepnote drives the repository side.
Use --dry-run to see what a run would do before it does it:
deepnote sync ./workspace --all-files --dry-run
Automating it
--on-conflict skip plus -o json gives a run that never prompts and reports a parsable summary,
which is what you want from a cron job or CI step:
deepnote sync ./workspace --all-files --on-conflict skip -o json
Exit codes
| Code | Meaning |
|---|---|
0 | Success — skipped conflicts are reported but do not fail the run |
1 | One or more projects failed to sync |
2 | Invalid usage — missing token or bad arguments |
A single broken project does not abort the rest of the workspace; it is reported as an error and the run continues.
Choosing between the three
| You want to… | Use |
|---|---|
| Keep one project in a Git repo, synced automatically by Deepnote | Deepnote file sync |
| Mirror many projects to your machine on demand, and push notebook edits | deepnote sync |
| Deploy a built static site or app to a project | deepnote publish |
Related
- Publishing static sites with the Deepnote CLI
- Deepnote file sync — the in-product Git-linked feature
- Deepnote file format — what is inside a
.deepnotefile - How to set up Deepnote locally — editors and other local tooling