DocsScripts and agents

Scripts and agents

Everything Skwir does is a named command, and scripts and AI agents can run the same commands in your open window. What they would change comes to you as a plan, and nothing runs until you apply it.

Turn it on

Open Settings › Plugins and turn on Agents and scripts. The open window then listens on a channel only your account can reach; it closes with the window, or when you turn the plugin off.

It is off by default because, once on, any program running as you can reach the window, as it can your files. What an agent may do through it is limited (What an agent may do); a script you run yourself acts as you.

Every action is a command

Under its windows and menus, Skwir is a list of named commands. A key, a line of the palette, a menu item and a button each run one: a name plus arguments, as JSON. Scripts and agents run the same ones. Plugins register their own, and turning a plugin off withdraws them.

Every command carries a title, a description and the JSON Schema of its arguments, made from the code that handles it, so they can’t drift apart. Arguments are checked before anything runs, whoever sent them. A command answers with done, a value, or a plan.

The commands command lists them all: about 150, plus the window’s own ui.* commands. One entry, abridged:

{
"name": "query.search",
"title": "Search",
"description": "Search, shown in the pane (then `entries` lists what it found): words match names; `ext:pdf,md`, `kind:image,video`, `tag:x`, `content:/regex/`, `size>10M`, `modified<7d`, `rating>=4`, `near:lat,lon~5km`; `OR`, `NOT` or `-`, parentheses; …",
"owner": "query",
"args_schema": {
"type": "object",
"required": ["expr"],
"properties": {
"expr": { "type": "string", "description": "The query expression, e.g. `*.pdf modified<7d`." },
"root": { "description": "Subtree to search; the pane's current directory when omitted.", … }
}
}
}

Some of them, by family:

Family Commands
Places, selection and file operations navigate, back, forward, up, select, entries, sort, filter, rename, copy, move, trash, mkdir, new_file, undo, redo, plan_diff, apply_plan, commands
Search query.search, query.refine, query.save, query.describe, query.similar
Tags and notes tags.edit, tags.set, tags.rename, tags.list, notes.rate, notes.comment
Places on the map geo.search_area, geo.geotag
Batch changes rename_bulk, rename_bulk.preview, edit_as_buffer, shelf.add
Tabs and more tab.new, timeline.select, jump.to, open_with, shell.run, settings.apply, plugins.list, plugins.set_enabled
The window itself ui.view, ui.peek, ui.split, ui.toggle_preview, ui.sort, ui.zoom, ui.palette, ui.settings

A command acts on the files it names, by absolute path, in its entries; with none named, it acts on the active pane’s selection. A relative path is refused: the window’s working folder is not yours.

Scripts: skwir cmd

skwir cmd [--apply] <command> [<arguments, a JSON object>]

skwir cmd runs one command in the open window and prints its answer as JSON:

skwir cmd entries # what the active pane shows
skwir cmd query.search '{"expr": "*.pdf modified<7d"}'
skwir cmd --apply rename_bulk '{"template": "Coast {n:02}.{ext}"}'

A command that changes files prints its plan. With --apply, the plan is applied as your own action, as a key would apply it, and you can undo it in the window.

With no window open, the command runs in a Skwir of its own, without a window: a reading answers, a plan is printed, or applied with --apply. The window’s own commands (ui.*) need the window.

Agents: skwir mcp

An agent’s MCP client starts skwir mcp, which carries the agent’s requests to the open window. For Claude Code:

claude mcp add skwir -- skwir mcp

Other clients take it as a local server that runs skwir with the argument mcp, often in a configuration like this one:

{ "mcpServers": { "skwir": { "command": "skwir", "args": ["mcp"] } } }

Every command is a tool, with its description and argument schema. Its dots are written __: tags.edit is the tool tags__edit. If no window is listening, skwir mcp says to open Skwir and turn on Agents and scripts, and starts nothing.

What an agent may do

Every command says what it does when it is registered, and an agent’s call is held to it:

The command… When an agent calls it
reads, or changes only what the window shows runs
changes files its plan waits in the window for your review; the tool answers once you have applied it (with what applied) or dismissed it
does anything else: a setting, a plugin turned on or off, a program started, an undo waits for you to Allow it in the window (“An agent asks to run …”)
is yours alone: applying a plan, pressing a button, answering the window is refused, and not offered to the agent at all

So an agent can never apply its own plan, answer a question it caused, or press a button for you. The tool list marks which tools ask first, and which change nothing.

A script you run with skwir cmd is held to none of this: it is you.

Plans and review

A bulk rename, a folder edited as text, geotagging photos from a track, and anything an agent proposes all come as a plan: an ordered list of operations on files identified by who they are, not just by name.

{
"title": "Rename 4 photos",
"steps": [
{ "kind": "rename", "args": { "entry": …, "new_name": "Coast 01.jpg" } },
{ "kind": "rename", "args": { "entry": …, "new_name": "Coast 02.jpg" } },
{ "kind": "rename", "args": { "entry": …, "new_name": "Coast 03.jpg" } },
{ "kind": "rename", "args": { "entry": …, "new_name": "Coast 04.jpg" } }
]
}

Before it runs, Skwir checks each step against the disk and marks it pending, already done or in conflict, with the reason, and shows you the list. Nothing happens until you apply it. Every step it applies is recorded with its inverse (renames, moves, copies, the Trash, tags and photo locations), so you can undo it for as long as Skwir is open; a step that can't be undone is marked not undoable. Applying the same plan twice changes nothing the second time.

Private folders

Folders you mark private in Settings › Privacy never leave this machine. From the start, they are where keys and credentials live (~/.ssh, ~/.gnupg, ~/.password-store, the keyrings, ~/.pki, ~/.aws, ~/.kube, ~/.docker, ~/.netrc), and any folder holding a file named .private, each with everything under it.

  • An agent never names one: a call that does is refused.
  • An agent never sees one: its answers leave out every private file, and every text that names one. What it counts leaves them out too, so the numbers are those of a window without them.
  • A plugin from outside Skwir is never handed one.

What Skwir gathers about a whole folder in the background, like the sizes in the Usage view or the timeline over a folder and everything below it, includes private folders: an agent can learn how much they hold and when it changed, never their names nor what they hold.

Searching and settings from a command

query.search takes the same text as the address bar; Searching lists what it understands. A few examples:

expr Finds
*.pdf modified<7d PDFs changed in the last week
kind:image,video size>10M Photos and videos over 10 MB
content:"invoice" -ext:eml Files that mention “invoice”, except emails
tag:coast rating>=4 Your best-rated coast pictures
near:48.38,-4.49~5km Anything taken within 5 km of a place

query.describe breaks a search into its parts (where it looks, words, kind, date, size, tag, content), each with the command its choices run.

Settings are one file, checked against its schema and changed through settings.apply, so what you can set by hand, a script can set too, and an agent can ask to. Your keyboard shortcuts are records of the keyboard.bindings setting, each naming a command:

Keys Command Arguments When
ctrl-alt-g ui.view {"id": "grid"} pane
ctrl-alt-r rename_bulk {"template": "{date:%Y-%m-%d} {name}.{ext}"} pane selection
g d navigate {"location": "~/Downloads"} pane

What comes next

  • Plugins from outside Skwir are here, and experimental: a folder with a plugin.toml and a WebAssembly module, or a program that speaks JSON lines. Each stays off until you turn it on, and gets nothing it did not declare. The protocol may change before it is declared stable; Writing a plugin explains it.
  • Skwir’s own assistant is planned. You will ask in plain words (“organise this folder”, “what is safe to delete?”); its tools will be these commands, its answer a plan, and it will never run anything itself. Local models first; remote ones only if you opt in, with a visible sign while anything leaves your computer.

This page is also served as Markdown at /agents.md, for agents that would rather not read HTML.

Updated 11 October 2026 · 6 min read Edit this page on GitHub