Opening a complete repository
A complete repository is what you get when a project is exported from
SynckHub: one directory that holds the project’s entire retained history and
every byte that history refers to. That includes files, folders, conversations
and more. In this tutorial you will open one with nothing but the synck
command. No account, no server and no network.
You need Synck installed. The tutorial also uses
jq, a small JSON tool, to make output easier to read.
It is optional, and every step says what to do without it.
Get the sample
Download the sample repository: launch-project.zip (16 KB). It is a small, made-up SynckHub project in which Maria and Sam prepare a proposal to open a new office. Unzip it in a working folder, either by double-clicking it or from the terminal:
$ unzip -q launch-project.zip
$ ls -A launch-project
.synck
That is all there is: a directory containing .synck. Unlike the repository
in the previous tutorial, this one has no checkout, so
there are no files on disk. Everything is stored inside .synck, and you read it through
Synck. (When you want ordinary files to edit, you can
check them out later.)
Inside the sample, the project looks like this:
launch-project
├── FOLDER Launch a workspace
│ ├── FILE proposal.txt created by Maria, revised once
│ └── FILE budget.csv
└╌╌ CHAT "Launch review" a team chat: three messages between Sam and Maria
Launch is a workspace: in SynckHub, the folder that holds a project’s
files. The chat is a non-tree item. It is not inside any folder. (What is
Synck? explains the difference.)
Its history has eight commits:
| # | Author | What happened |
|---|---|---|
| 1 | Maria | Created the Launch workspace |
| 2 | Maria | Created the Launch review chat |
| 3 | Maria | Added the first draft of proposal.txt |
| 4 | Sam | “Please check the budget before Friday.” |
| 5 | Maria | Added budget.csv |
| 6 | Maria | Saved a revised proposal.txt |
| 7 | Maria | “The revised figures are ready. Fit-out was missing.” |
| 8 | Sam | “Approved. Send it to the client.” |
Verify it first
Before you rely on a repository someone gave you, check it:
$ synck repository verify launch-project
{"repo_id":"01a174b7-8a7d-74e0-b0d7-81b1dcfa6ccd","terminal_repo_seq":8,"commits":8,"items":4,"blobs":3,"bodies":3}
Verification replays the entire history, checks its structure and recomputes the hash of every stored file version and message body. The report counts what it checked:
terminal_repo_seqis the last position in the history. Eight commits mean the history runs up to position 8.itemscounts the workspace folder, the two files and the chat.blobscounts file contents: two versions of the proposal and one of the budget.bodiescounts message texts.
If anything were missing or altered, the command would fail with an error instead. That would be your cue to get a fresh copy rather than use this one.
Verification proves that the copy is internally consistent. It does not prove where the copy came from; for that you still rely on how you received it. See copies you can trust.
Browse the items
List what is at the top level of the repository:
$ synck item list --path launch-project
{"items":[{"repo_id":"01a174b7-8a7d-74e0-b0d7-81b1dcfa6ccd","item_id":"01a174b7-8a7d-74e0-b0d7-81d946ca6792","item_type":"CHAT","parent_folder_id":null,"name":"chat-01a174b7-8a7d-74e0-b0d7-81d946ca6792",...},{...,"item_id":"01a174b7-8a7d-74e0-b0d7-81cf3866d6b9","item_type":"FOLDER","parent_folder_id":null,"name":"Launch",...}],"next_cursor":null}
(Output abbreviated with ....) The synck item commands always answer in
JSON, because they are designed to be easy for scripts and other programs to
read. Each item carries its type, its name and, most importantly, its
item_id. You refer to items by ID, because names can change and IDs never
do. --path names the repository; leave it out when you run the command from
inside the repository’s directory.
With jq, you can print just the interesting fields:
$ synck item list --path launch-project | jq -r '.items[] | "\(.item_type)\t\(.name)\t\(.item_id)"'
CHAT chat-01a174b7-8a7d-74e0-b0d7-81d946ca6792 01a174b7-8a7d-74e0-b0d7-81d946ca6792
FOLDER Launch 01a174b7-8a7d-74e0-b0d7-81cf3866d6b9
Two things stand out.
The chat is listed next to the folder, not inside it. Chats are non-tree items: they have no parent folder. The top level of a listing therefore shows both the top of the folder tree and every non-tree item.
The chat’s name is not “Launch review”. A non-tree item’s name is an internal
identifier. The title people see is stored with the chat, and item show
reveals it:
$ synck item show 01a174b7-8a7d-74e0-b0d7-81d946ca6792 --path launch-project | jq -r '.item.chat | "\(.title) (\(.profile.chat_kind))"'
Launch review (ROOM)
ROOM is SynckHub’s kind for a team chat, as opposed to a direct message or an
assistant conversation. The folder, meanwhile, is not an ordinary folder:
$ synck item show 01a174b7-8a7d-74e0-b0d7-81cf3866d6b9 --path launch-project | jq -c '{name: .item.projection.name, item_subtype: .item.projection.item_subtype}'
{"name":"Launch","item_subtype":"STANDARD_CASE"}
STANDARD_CASE marks a SynckHub workspace. To look inside it, pass its ID as
the parent:
$ synck item list --parent 01a174b7-8a7d-74e0-b0d7-81cf3866d6b9 --path launch-project | jq -r '.items[] | "\(.item_type)\t\(.name)\t\(.item_id)"'
FILE budget.csv 01a174b7-9089-76c2-82ae-adfd661146f1
FILE proposal.txt 01a174b7-8f4e-76f1-8ac4-440db922fb52
Read a conversation
synck item show reconstructs one item from its history. For a chat, that
includes every message:
$ synck item show 01a174b7-8a7d-74e0-b0d7-81d946ca6792 --path launch-project | jq -r '.item.subitems[] | "\(.sender_id): \(.body)"'
Sam: Please check the budget before Friday.
Maria: The revised figures are ready. Fit-out was missing.
Sam: Approved. Send it to the client.
Without jq, look for the subitems list in the JSON. Each message has a
sender_id, a created_at time and a body.
This is the point of a complete repository. The conversation that explains why the budget changed is preserved alongside the file, and you can read it without the chat application that originally hosted it.
Extract a file
To get a file’s content out as an ordinary file, use synck item export with
the file’s ID and a destination that does not exist yet:
$ synck item export 01a174b7-8f4e-76f1-8ac4-440db922fb52 proposal.txt --path launch-project
{"bytes":110,"destination":"proposal.txt","item_id":"01a174b7-8f4e-76f1-8ac4-440db922fb52","schema_version":1}
$ cat proposal.txt
Launch proposal
Goal: open the Lisbon office on 1 March.
Budget: 52,500 EUR (includes fit-out).
Owner: Maria
Synck checks the bytes against their stored hash before it writes the file, and it never overwrites an existing file.
Go back in time
The proposal was revised in commit 6. To see it as it was before that, read
the repository through an earlier position in its history. --through 5
means “as of the end of commit 5”:
$ synck item export 01a174b7-8f4e-76f1-8ac4-440db922fb52 proposal-first-draft.txt --through 5 --path launch-project
{"bytes":91,"destination":"proposal-first-draft.txt","item_id":"01a174b7-8f4e-76f1-8ac4-440db922fb52","schema_version":1}
$ diff proposal-first-draft.txt proposal.txt
4c4
< Budget: 48,000 EUR.
---
> Budget: 52,500 EUR (includes fit-out).
--through works with every item command, so you can also see the
conversation as it stood at that moment:
$ synck item show 01a174b7-8a7d-74e0-b0d7-81d946ca6792 --through 5 --path launch-project | jq -r '.item.subitems[] | "\(.sender_id): \(.body)"'
Sam: Please check the budget before Friday.
At position 5, Sam had asked about the budget and nobody had answered yet. Every item can be viewed at any point in the repository’s history like this.
Make your own copy
The sample you unzipped is someone else’s copy. To keep a copy of your own, let Synck make it, rather than copying the directory with your file manager:
$ synck repository import launch-project my-copy
{"imported":"my-copy","schema_version":1}
$ synck repository verify my-copy
{"repo_id":"01a174b7-8a7d-74e0-b0d7-81b1dcfa6ccd","terminal_repo_seq":8,"commits":8,"items":4,"blobs":3,"bodies":3}
repository import locks the source, takes a consistent snapshot of it,
verifies everything in a private staging area, and only then creates my-copy. The
copy keeps the same repository ID, item IDs, authors and history. It adds no
commit of its own. If anything fails, my-copy is never created.
Look at the copy’s configuration:
$ cat my-copy/.synck/config.json
{"storage_mode":"WHOLE_FILE","format_version":6,"repo_id":"01a174b7-8a7d-74e0-b0d7-81b1dcfa6ccd","authority":"FOLLOWER"}
"storage_mode":"WHOLE_FILE" says how the copy stores content on disk. A copy
keeps the layout of its source, and this sample stores each file whole.
Storage space explains the two
layouts.
"authority":"FOLLOWER" means that this copy can be read, verified and copied
again, but it does not accept changes yet. Copying a repository does not
give you the right to write to it. Becoming a writer is a separate, explicit
step, which Complete repositories explains.
What you learned
- A complete repository is a directory with a
.synckinside. It needs no service to read. synck repository verifychecks every commit and every stored byte.synck item listandsynck item showbrowse items by ID, and answer in JSON. Chats and other non-file items are first-class.synck item exportextracts a file, and--throughreads any earlier point in the history.synck repository importmakes a verified copy of your own. Copies start as read-only followers.
Next, learn to work with complete repositories in depth, including how to edit their files, or go back to Synck basics for everyday work in a tracked folder.