Email and chats

The email that went with a document is often as important as the document: the client’s approval, the figures someone sent, the version that was attached. Synck can keep those messages in the same repository and the same history as your files. A repository can also hold a running conversation, a chat, next to the documents it discusses.

Commit a message

Save an email from your mail program as an .eml file, or an Outlook .msg file, into the repository’s folder, and commit it like any file:

$ cp ~/Downloads/budget-email.eml .
$ synck status
A budget-email.eml
A proposal.txt
$ synck commit -m "Add the proposal and Maria's budget email"
committed sha256:dc0f1d61d0b7972d67bbb2c7df40c7a8f94b9cff19a0f5472fc466511443adda
$ synck status
nothing to commit, working tree clean

Synck does not store the message as a file. It reads it and records an EMAIL item, named after the file without its extension. The item keeps the sender, recipients and dates, the body, every attachment, and the exact bytes of the original .eml or .msg file. Emails are tree items, so a message saved into a folder is filed in that folder.

The .eml file stays in your folder unchanged, and synck status stops listing it once it has been recorded. A recorded email never changes: deleting the file afterwards changes nothing in the repository. If you edit the file, Synck lists it as a new message and refuses to commit it under the same name:

$ synck commit -m "Update the budget email"
synck: budget-email.eml: an email named "budget-email" is already recorded in this folder; a recorded email never changes, so save the changed message under a new file name or put the original file back

Save the changed message under a new file name, and Synck records it as a second email next to the first.

Messages that cannot be read, or that exceed the import limits (64 MiB per message and its decoded attachments, 1,000 attachments), are refused with an error, and nothing is committed. They are never stored as plain files instead. Reading a message never fetches anything from the network.

Read it back

Email items do not appear as files in your folder, so you read them with synck item, which answers in JSON. item list shows the items at the top of the repository. This example uses jq to print one line per item:

$ synck item list | jq -r '.items[] | "\(.item_type)\t\(.name)\t\(.item_id)"'
FILE	.synckignore	01a1795a-bf18-77b2-9767-f99b9773b7a2
EMAIL	budget-email	01a1795a-c068-716a-bfa8-484f924c0724
FILE	proposal.txt	01a1795a-c068-716a-bfa8-4850c6ec47d0
$ synck item show 01a1795a-c068-716a-bfa8-484f924c0724 | jq '.item.projection.metadata_json.mailcal | {subject, from, to, sent_at}'
{
  "subject": "Launch budget",
  "from": {
    "email": "[email protected]",
    "name": "Maria"
  },
  "to": [
    {
      "email": "[email protected]",
      "name": "Sam"
    }
  ],
  "sent_at": "2026-10-23T08:00:00+00:00"
}

The full output of item show also has every other header, the hashes that identify the stored body and original message, and one EMAIL::ATTACHMENT subitem per attachment, with its file name. Reading items and history describes the output in detail.

To get the original message back, exactly as it was saved, export it to a new file:

$ synck item export 01a1795a-c068-716a-bfa8-484f924c0724 ../original.eml
{"bytes":454,"destination":"../original.eml","item_id":"01a1795a-c068-716a-bfa8-484f924c0724","schema_version":1}

In the history

synck log and synck show list file and folder changes, so the commit above appears as 1 change:

$ synck log -n 1
2 | 2026-10-26 18:55 +01:00 | Alex | 1 change | Add the proposal and Maria's budget email
    A proposal.txt

synck repository log . lists every event in each commit, including the EMAIL::CREATE that recorded the message.

A recorded email is permanent, like everything else in the history. synck revert only reverses commits that change files and folders, so it refuses a commit that recorded an email. Check that a message belongs in the repository before you commit it.

Keep a chat

A chat is a non-tree item: it has a title but no place in a folder, so it never appears on disk. Create one with synck repository create-chat, then add messages from UTF-8 text files:

$ synck repository create-chat "Launch review"
{"commit_id":"sha256:40acf9cc32dd9296364098145f579dd4ce6e33653c3ac833051a05cc41ecd68a","item_id":"01a1795b-cb5c-7736-9772-d43242cc4770","schema_version":1}
$ printf 'Sent to the client.' > message.txt
$ synck repository append-chat 01a1795b-cb5c-7736-9772-d43242cc4770 message.txt --attachment proposal.txt
{"commit_id":"sha256:656aaa76938689b04e17ea2055c0663fa82841f40a55159c26b6daa9f60aa173","schema_version":1}

Each command records one commit. --attachment stores a copy of a file with the message; repeat it for several files. Read the conversation back with synck item show, as described in Reading items and history. The message file itself is not tracked, so keep it outside the repository’s folder, or add it to .synckignore, if you do not want it committed as a file later.