deckfill runs on one small machine. One person pays for it and can log into it. This page says exactly what is on that machine, what is written down, what that person can see, and what they cannot.
It is written plainly on purpose. If it read like a privacy policy you would not know whether to trust it.
Nothing you write is stored on this server, and nothing you write appears in any log.
Your decks live in your Google Drive, not here. What is here is a small amount of bookkeeping — which deck you have open, which pictures you were offered, a permission slip for your Google account — and it is readable only by the account deckfill runs as, and by the person who runs the machine, who is root on it.
That last part is not a technicality and it is not something a setting can fix. It is the thing to weigh.
Under state/users/, one folder per person. The folder is named by a pseudonym — eight hex characters — so listing the folder tells you nothing about who is here or how many of us there are.
Inside your folder:
| the deck you have open | so you do not have to name it in every new chat |
| the nicknames you gave your decks | so "open the humanity deck" works tomorrow |
| the picture shortlists | so "use number 3" means the third row of the sheet you were just shown |
| the credits for placed pictures | so a photograph can be attributed |
| three caches | image fingerprints, face checks and a picture's own measurements, so the same picture is not scored twice |
| the temporary Drive files a placed picture is standing on | so none is thrown away while a slide still needs it |
| your FrameThrower token and your Pexels key | if you gave them. Mode 600, never printed back |
| linked Google accounts | the refresh token for each second account you connect, under google/<address>.json, mode 600; "remove me" deletes it |
| the file-to-account map | _deck_accounts.json: file ids and the account addresses that can open them, never titles or file contents |
| saved slide mappings | so building new slides does not re-measure the whole deck |
| what your deck's pages look like | which page is a cover, where a cover keeps its picture, which marks it carries — so deck_check can tell you a page has drifted from the rest of its own deck. Running marks are kept as fingerprints, never as their words |
| the picture rules and deck notes you set | the sentences you asked it to remember — "never a period frame", "idea slides get a one-sentence endline" — in your own words, so the next chat starts where the last one left off. deck_rules and deck_note show them and clear them |
| a recording you sent to be transcribed, and the words that came out of it | both in your own folder, mode 600. The sound is deleted the moment the words exist, and the words are swept seven days later |
| what happened to a picture after it went on | the url that was placed, when, and the KIND of picture it was: its film, its library, whether a face fills it. A picture swapped out within fifteen minutes is taken as a rejection, so later sheets rank that kind lower. Replacing a picture that stood longer teaches nothing unless you explicitly reject it with rejected=True, which counts whatever the time |
Deck ids are in there, because a deck id is how a deck is opened.
Deck titles are not. They used to be, to save an API call. A deck's title is usually a client's project name, so it is fetched fresh each time instead and never written down.
The words you search pictures with are not written to disk. A partial picture search can hold its retrieval metadata, descriptions and compressed previews in memory for up to 30 minutes so the same search can continue. These runs are separate for each person, limited to four runs and 16 MB of previews per person, and cleared on completion, restart or "remove me". Saved picks identify the search by a fingerprint. The record of what you did with a picture also avoids the search words: it knows that a frame from a named film was taken off a slide four minutes after it went on, and it does not know what anybody typed to find it.
Nothing you write is. No headline, no script, no body copy, at any point. The one place a draft ever touched this disk was a scratch file during a build; it is written so only deckfill can read it and deleted the moment the build finishes.
One exception is a rule you deliberately store: deck_rules("never a period frame") and deck_note("idea slides get a one-sentence endline") are kept, in your own words, because remembering them is the entire point of them. Nothing is inferred into that file — only what you asked for — and deck_rules(clear=True) / deck_note(clear=True) empty it.
The other is a recording you send to be transcribed. It is transcribed on this machine, by a model on this machine, so neither the sound nor the words are sent anywhere. Both live in your own folder, mode 600: the sound is deleted the moment the words exist, at the end of that run and not at the end of the day, and the words are swept seven days later, which is long enough to ask for them again in a new chat. Ask for a long transcript in a Google Doc and the doc is yours, in your Drive, with nothing about it kept here.
A fingerprint is not the words. Read fingerprints now stay only in the running server's memory, separately for each person: twelve characters for the words with spacing folded, and eight for the exact text, including its spacing and final newline. The record holds fingerprints, never the words. They let a write notice that a box changed after it was read. They go when the server restarts or you say "remove me". Older _reads.json files are no longer read; the next write that updates the read record removes the old file, and "remove me" removes the folder containing it.
Nor is anything deck_search reads. Looking inside your decks means reading their words, and those words are your script. They are held in the running server's memory, per person, the way the undo record below is: they go when the server restarts, and they go when you say "remove me". The words you searched with are not kept either.
How much of your key is left is not written down either. Every picture library says so on every answer, and deckfill keeps the last figure so it can tell you before a search stops working. It is one number per library, held in the running server's memory and filed against you — nobody is shown how much of anybody else's key is gone. It goes when the server restarts, and it goes when you say "remove me".
And the undo record is not on the disk either. deckfill remembers what a slide said before it changed it, so "put that back" works. That record is your own words, so it is held in the running server's memory and never written down — it is kept separately for each person, it goes when the server restarts, and it goes when you say "remove me". The cost of that is real: restart the server and yesterday's change cannot be undone. It is the right way round.
The new editing records stay in memory too. Each belongs to the person making the call, even when a linked Google account opens the deck:
deck_apply entries: what changed, the earlier text, styles and geometry, and what is needed to put back changes or remove newly created slides and elements.deck_diff can tell deckfill's work from later hand edits.deck_diff keeps a baseline: the earlier title, slide words, element ids, styles, positions and picture references used for comparison. It does not keep signed picture addresses.deck_jobs(calls=True) reply, separate from the server log described below.These records are cleared by "remove me" and by a server restart. None is written to disk or copied into the server log. The file-to-account map is the bookkeeping exception: write tools and deck_open also save its file ids and account addresses in your _deck_accounts.json. Read-only calls only read it. The linked accounts' permission files are stored separately as described in the table above.
Automatic backups are Google Drive files. Before a large or deleting deck_apply, deckfill copies the deck into "deckfill backups" in the My Drive of the account used for that deck. It creates a private folder there if needed and never adds sharing permissions to the folder or copies. If that folder already exists, it reuses it without checking whether you have shared it. The copies remain in your Drive when you say "remove me"; that clears the server's record, not your files. A reused copy can contain earlier values, and the reply says when it was taken.
Separately, two things live outside your folder:
state/users/_map.json — the one file that says which pseudonym is which address. Mode 600. It has to exist: without it, nobody could answer "delete my data" or "which folder is mine".If you connect a mailbox, deckfill can read it, and only read it. Whatever the permission on file would allow, the one deckfill uses asks Google for reading mail and nothing else, so it cannot send, reply to, change, delete or mark anything.
What is held is one permission per connected mailbox, the same kind of token as your Google permission above:
mail/<address>.json, mode 600. Nobody else's call ever looks there, the owner's included.What is never held is the mail. Not a subject, a sender, an address, a body, an attachment, or what you searched for. Mail is fetched from Google when you ask, held in the running server's memory for that one reply, and gone. The log line for a mail search says how many conversations it found and how long it took.
The caveat below applies here too: root can read that permission file and could use it to read that mailbox.
To remove one, say "disconnect" and the address in a chat: that is mail_connect(address, remove=True), which withdraws the permission at Google and deletes the file. One exception: when this machine also keeps a permission for the same account from the same Google app, withdrawing at Google would stop that one too, so only the file is deleted and the reply says so. Or remove deckfill at myaccount.google.com/permissions while signed in to that account. A mailbox this machine's settings name is removed in those settings, not from a chat. "Remove me" removes every mailbox you connected as well.
One line per tool call: the time, which tool, a pseudonym, how long it took, and whether it worked.
2026-08-21 11:04:22 INFO tool deck_write u_8b5a043f ok 412ms
That is the whole of it. No deck, no slide, no text, no search, no file name, no id, no address. Errors are recorded by class — [HttpError] — not by message, and without the traceback, because a traceback is the thing in a log most likely to be carrying a fragment of what someone wrote.
The web server in front of deckfill logs the same way: a method, a status and a duration, with the request path, the query string, the headers and your IP address all removed. Signing in logs that a login happened, not who by. A failed login keeps the IP address it came from, because that is how somebody trying to break in is spotted.
They are root on the machine. That means:
There is no technical wall stopping any of that, and this page is not going to pretend there is. What is true is narrower and worth saying exactly:
So the trust here is operational, not cryptographic. It rests on one person not doing something, not on them being unable to.
Not because they are prevented, but because it was never written down:
None of that reaches the disk or the journal. There is nothing there to find.
The same as always. Every edit deckfill makes is an ordinary Google Slides API call from your own account, and it appears in Google's own logs and in your Drive's revision history exactly as if you had made it. Nothing here changes that, and nothing here can.
In a chat, say "remove me" or "delete my data". It will tell you what is about to go and wait for you to say yes. Then it deletes, permanently:
For linked Google accounts, withdrawal is best effort. If the same Google app's grant is used by another credential on this machine, deckfill leaves that grant in place so it does not disconnect the other use; it still deletes your linked permission file. If Google does not confirm a withdrawal, the file still goes. Remove deckfill in that account's Google permissions to withdraw the grant yourself.
Your decks are in your own Drive and are not touched.
Whoever runs the server can also do this for you — ask them — and it deletes exactly the same things.
One last step, and it is the only one nobody can do for you: go to myaccount.google.com/permissions and remove deckfill. That withdraws the permission at Google's end as well as this one.
If you are working on something you are contractually not allowed to put on someone else's machine — an agency's client work, anything under an NDA — do not use the hosted connector. Not because it leaks, but because "the person who runs it is root and has your token" is not a thing you can put in writing to a client.
Run it on your own Mac instead. It is the same tool, it talks to Google directly from your machine, no server is involved and nothing about your work leaves your laptop. SETUP.md in the deckfill folder is that install, start to finish, and it takes about twenty minutes.
That is the only zero-trust option, and it is a real one.