Kotoba

Where to start

What Kotoba isWho she is and where she runs, in one page
InstallingOne package, two commands
First runA key, a model, her first words
The approval gateHow she asks before she acts
The two voice modesLocal voice, or the agent tunnel
The soul fileChange who she is
RoadmapWhat grows next, and what was cut on purpose

Or a section

↑↓ move openesc close124 pages
All pages

Vision2 of 5

Session captures — what she saw while working

About 4 minutes to read

On this page

A session capture is a screenshot she took, or an image you handed her at the terminal, during this run. It is scratch, not a keepsake. Its whole job is to survive elision: the picture drops out of the model's context within the turn, and the capture log is what lets her name it and open it again afterwards instead of asking you to resend it.

Two halves make it work, and they have different lifetimes.

HalfWhereLives for
The image~/.kotoba/files/screenshots/<source>/, in her Files libraryUntil you delete it
The log entry (filename, caption, timestamp)The backend's memory, keyed by session idUntil the backend stops

Restart the backend and she forgets that a screenshot was ever taken. The file is still there, and view_capture still opens it if she is given the name.

Where a capture lands

When a tool result carries an image, the loop saves it before feeding it back to the model:

~/.kotoba/files/screenshots/browser/screenshot-1-ad8d25.png
~/.kotoba/files/screenshots/desktop/screenshot-2-9f01c7.png

The subfolder is inferred from the tool's name, not from what it did. A name containing browser files under screenshots/browser/, one containing blender under screenshots/blender/, and everything else under screenshots/desktop/. A browser is on Kotoba's list of known MCP servers, so that folder is the one you will actually see; the other two are for servers you connect yourself. The number counts captures within that one turn or work job, and the six hex characters keep two of them from colliding.

The Files panel receives an artifact event as each one is written, so a new screenshot appears in the panel while she is still working. The model is told the name in the same breath — the tool result gains a line reading "Saved to the user's Files as … — refer to it by that name."

One exception: a delegated helper's screenshots are not filed. The filing step and the capture log both run only on the main agent's tool calls, so an image a delegate helper saw is seen once and never again.

The captions

Right after a capture is filed, a background request asks the model for a one-line description of it, and that line becomes the entry's caption. It is best-effort in the strict sense:

  • it is fired and never awaited, so it never delays the turn;
  • it asks the rate limiter first. The limiter stalls for at most 15 seconds waiting on the token window, and if the budget is still short after that the caption is dropped, not sent — a request into a window the limiter has just called insufficient is a near-certain 429, and it would take budget from the live turn that produced the screenshot;
  • any error at all returns an empty caption. The entry keeps the empty string it already had.

So some captures are captioned and some are not, and that is by design rather than a fault.

What she is told

If the session has captures, a block is inserted into the turn naming them:

RECENT CAPTURES — screenshots you took, and images the user shared with you, THIS session (saved in
the user's Files). Re-open any with view_capture(file) to look again; don't ask the user to resend one
you already have. (If one is worth remembering long-term — a person, the user, a product — save it
with remember_image.)
- screenshots/browser/screenshot-1-ad8d25.png — a search results page
- shared/clip-1.png — [Image #1] — the user shared this with you

The last 12 entries are listed. The block names both provenances on purpose: some of these she took and some you gave her, and a block that said "you took" of the second kind would have her claim a capture she never made.

The log itself holds 30 entries per session. Past that the oldest entry falls off the list; the file on disk is untouched. Re-capturing the same filename replaces the entry rather than adding a second one.

A delegated helper is given neither this block nor the visual-memory one.

Opening one again

view_capture(file) reads a saved capture back off disk and returns it as an image, so the model looks at it a second time. It is a read-only tool, jailed to the Files library, and it is available in an ordinary conversation as well as in work mode — a spoken follow-up is exactly the case it exists for.

It resolves the name in three passes, each of them jailed:

  1. the path as given, relative to the library — screenshots/browser/shot.png;
  2. the bare filename in the library root;
  3. a recursive search for that filename anywhere under the library, newest match winning.

The second and third passes matter because the model usually has only the basename. .., absolute paths and symlinks that leave the library are rejected, and a file whose media type is not image/* is refused.

When nothing resolves, the tool returns nothing and she says "I couldn't find that capture to look at again." It does not guess.

On Discord, view_capture is owner-only. It resolves a name by recursive glob over the host's file library and reads the bytes to a vision model that will then describe them in a public channel, so a guest asking for it is told these are not their pictures to open — and the refusal happens inside the tool, not only in the schema list it was withheld from.

Finding them afterwards

They are ordinary files. Open the Files panel in the browser, or look in ~/.kotoba/files/screenshots/ (or wherever KOTOBA_FILES_DIR points). Delete one from the panel and it is gone from disk.

Deleting the file does not delete the log entry. For the rest of that session she may still see the name in her RECENT CAPTURES block, try to open it, and get the honest failure line.

Next: Visual memory.