Files
Skald-Circle/docs/files.md
T
Daniele 488c702517
Nightly Build / build (push) Successful in 5m36s
feat(files): a Files section over the caller's whole space
Until now file browsing existed only inside a project, and the two memory
stores were reachable only by the agent's tools. `#files` is the general
surface: home, both memory stores, the shared folders and projects the
caller belongs to, plus the read-only skills and docs trees.

The root is virtual, and that is the design. Anchoring at `~` is wrong:
the explorer reads host-side, while `shared/`, `projects/`, `skills/` and
`docs/` are bind mounts inside the container — a page rooted at the home
would show less than the user has with no way to reach the rest, and on
native Linux would show Docker's empty mountpoint stubs, a door that
appears to work and leads nowhere. So level 0 is a synthetic list from the
new `GET /api/files/roots`, serialized from the caller's `UserFs` plus the
two virtual memory roots. It sends `kind`, never a label: labels are copy
and get translated.

`GET /api/files/dir` now answers `{ path, can_write, entries }`, and a
memory path is classified before `resolve_view_path` (which refuses one)
and listed from `memory_docs`: one level derived from the flat key space
by the pure `memory_docs::immediate_children`, over a single query whose
unslashed prefix also spots an exact note as "not a directory". Memory is
read-only from the page — every writer routes through `resolve_view_path`,
and `shared-memory/*` is `@fs_write require` for the agent, so a button
that walks past that rule is a decision of its own.

The explorer moves out of projects into `shared/file-explorer.js`, taking
`root` + `rootLabel` and reading `can_write` from the listing rather than
from its host: writability changes per branch and comes from the same
`UserFs::can_write_to` the server rejects writes with, so the buttons
offered and the writes accepted cannot disagree. Deep-linking needed it
steerable without a two-way binding, hence `rel` in and
`explorer-navigate` out — the event fires only for a click, never for a
`rel` the host set, so echoing it back is a no-op.

The URL carries the agent path of the open folder in one parameter, the
same vocabulary the assistant uses, so a link is shareable and pasteable
into a conversation; which root it belongs to is derived, not stored.

docs/: a new files.md, plus two pages this made false — shared-folders.md
claimed in three places that a shared folder has no explorer, and
memory.md never said a user can now read their own notes.
2026-08-22 20:09:56 +01:00

4.8 KiB

Files

The Files page (sidebar → Files) is where a member sees their own space: everything they can reach, in one list. Before it existed, files were reachable only through you — a user could ask "what's in the recipes folder?" but could not go and look. Now they can, and this document exists so you know what they are looking at when they mention it.

What they see first

The page opens on a list of places, not files. This is deliberate: the things a person can reach are not folders inside one another, they are separate roots, and the list is the only level where they all appear together.

Place Path Notes
Home ~ Their own workspace. Always writable.
Personal memory user-memory/ Their private notes — the ones you keep for them
Shared memory shared-memory/ The group's common notes
Shared folders shared/{name} One entry per folder they are a member of
Projects projects/{owner}/{name} One entry per project they can reach
Skills skills/ Installed skill folders. Read-only
Documentation docs/ This documentation. Read-only

A place they have no access to simply is not in the list — there is nothing to explain away.

The paths shown are the paths you use. Under each name the page prints the real path (shared/recipes, projects/anna/holiday), which is the same string you would pass to a file tool. That is worth pointing out to a user who asks how to tell you where to look: they can read the path off the page and say "the file in shared/recipes/dolci", and you will find it.

Inside a place

Clicking a place opens a file explorer: one folder at a time, folders first, with size and dates. From there:

  • Clicking a file opens it in the usual file viewer — Markdown rendered, images, PDFs, colored code, plain text.
  • Clicking a folder goes into it; the breadcrumb at the top walks back out, and the browser's back button works too. The address bar carries the folder, so a user can bookmark or paste a link to exactly where they are.
  • The listing is live. A file you create from a conversation, or another member uploads, appears within a second without a refresh. If a user says "it's not there", ask them to check the folder rather than assuming the write failed — but the page updates on its own, so a truly missing file is missing.
  • ZIP download — the button in the toolbar downloads the whole open folder as a single archive. Useful when someone wants "all the photos" rather than one file.

What they can change, and where

Write buttons — new folder, upload (including drag & drop), rename, delete — appear only where that person may write. Everywhere else the page shows a Read-only badge and no buttons.

Read-only for everyone: Skills, Documentation, and both memory stores. Read-only for some people: a shared folder or project where they were given read access only.

This matters when a user asks you to do something they just failed to do in the page: if the badge said read-only, you cannot do it either — the same rule applies to your file tools, and asking you is not a way around it. Tell them who to ask (an admin for a shared folder, the owner for a project).

Memory in the page

The two memory stores appear as ordinary folders, and this is the first place a person can read their notes themselves rather than asking you. Two things to explain if it comes up:

  • They are read-only here. A user can open and read a note, but cannot edit or delete it from the page. Changing memory goes through you, in conversation — which is what keeps the history in log.md honest and, for shared memory, what keeps the confirmation step in place.
  • The folders are not on disk. Notes live in the database, not as files, so they will not appear if someone goes looking in a terminal. The page shows them as folders because that is the useful way to read them, not because they are files.

What is not there

  • Places outside their space. Only what is in the list. A path inside the sandbox but not under any of those roots (/tmp/…, for example) is not browsable from the page, though you can still read it with your own tools.
  • Search. There is no search box yet. Finding something by content is still a question for you — you can search notes and files far better than a folder-by-folder look.
  • The phone app. The Files page is desktop-only for now.
  • shared-folders.md — who may see a shared folder, and read vs write access
  • projects.md — projects have their own explorer on the project page, the same one this page uses
  • memory.md — what goes in each memory store, and why shared memory asks for confirmation
  • skills.md — what the skill folders hold and why they can only be changed by installing