A Windows desktop app (Electron) that works like a file browser, with a chat panel in the style of Claude Code. The chat is connected as an agent to your file system and automatically receives the selected file or folder as context.
The agent can read, list, and inspect files (and write them — with your approval).
It also supports Agent Skills: SKILL.md folders that are loaded at runtime to
extend what the agent can do.
The full product spec, IPC channels, and tools are documented in SPEC.md.
This project is a learning exercise in how Agent Skills actually get wired into an LLM-based agent — from the client application's side, not the model's.
A Skill is just a folder with a SKILL.md file (frontmatter name + description,
plus a body of instructions). The model itself never "discovers" skills on its own —
the client app is responsible for:
- Discovery — scanning a skills folder on disk, parsing each
SKILL.md, and loading the result into memory (seeSkillsStore/loadSkillsinsrc/main/services/skills.ts). - Disclosure — telling the model which skills exist. This project exposes an
activate_skilltool (a normal function-calling tool, no special API) whose description embeds a bullet-list catalog of every skill'sname+description(seesrc/main/services/agent-tools.ts). - Activation — when the model decides a task matches a skill, it calls
activate_skill({ name })like any other tool. The tool looks the skill up in the in-memory store and returns its full body as the tool result, which becomes part of the conversation the model then follows for the rest of the task.
The key insight: any model trained on tool calling can use Skills, with zero
special training or API support — it's a convention built entirely on top of ordinary
function calling. This app targets the Gemini API
(via @google/genai), but nothing about SkillsStore or the skills catalog is
Gemini-specific — only the tool-declaration format at the very edge
(agent-tools.ts) is provider-specific; the discovery and disclosure logic would
work unchanged against any tool-calling API.
- Node.js 18+
- Windows (the app is built around Windows drives,
safeStorage, and Explorer) - A Gemini API key — free at aistudio.google.com/apikey
(enter it in the app, or via
.env— see below)
# 1. Install dependencies
npm i
# 2. Finish installing the Electron binary
# Required step — without it the app won't start correctly
node node_modules/electron/install.js
# 3. Run in development mode
npm run dev
⚠️ Don't skip step 2. In this setupnpm idoesn't always fully download the Electron binary, and runningnode node_modules/electron/install.jscompletes it.
Other scripts:
| Command | Description |
|---|---|
npm run dev |
Run in development mode (HMR) |
npm run build |
Build the app (electron-vite build) |
npm start |
Run the build (preview) |
npm run typecheck |
Type-check both main and renderer |
Skills are stored in your user folder, by default under:
C:\Users\<username>\.file-browser-agent\skills
(for example: C:\Users\user1\.file-browser-agent\skills)
Each skill is a sub-folder containing a SKILL.md file. When you install a skill
with the "Add skill" button in the app, it is extracted into this folder.
Make sure this folder exists, or the app won't work. You can create it manually:
mkdir "$env:USERPROFILE\.file-browser-agent\skills"This repo ships a sample skill at examples/skills/example-report/.
Copy it into your skills folder to try it:
Copy-Item -Recurse .\examples\skills\example-report "$env:USERPROFILE\.file-browser-agent\skills\example-report"Its SKILL.md:
---
name: example_report
description: Help summarize a folder or file set into a concise report with bullet points.
---
You are a reporting assistant.
When the user asks for a summary, report, or analysis of files or folders, do the following:
1. Inspect the relevant files or directory contents.
2. Summarize the most important findings in a short bullet list.
3. Mention any missing or unclear details.
4. Keep the response concise and structured.Now, in the app:
- Select any folder with a few files in it.
- Ask the chat something that matches the skill's
description, e.g. "Give me a short report on the files in this folder." - Watch the chat: before answering, the agent calls the
activate_skilltool (shown as a tool-call card, same aslist_dirorread_text_file), with{ "name": "example_report" }. That call returns the skill's full body as the tool result, and the model's final answer follows the report format defined above (bullet points, missing/unclear details noted) instead of its default style.
That round trip — the model reading example_report: Help summarize a folder... in
the activate_skill tool's description, deciding it matches, and calling the tool to
fetch the full instructions — is the entire "magic" behind Skills: it's just tool
calling, disclosed as a catalog and activated on demand.
The location is controlled by the FILE_BROWSER_SKILLS_DIR environment variable.
To change it, copy .env.example to .env and edit the value:
# Defaults to ~/.file-browser-agent/skills when unset.
FILE_BROWSER_SKILLS_DIR=C:\Users\user1\.file-browser-agent\skillsThe .env file is loaded when the Electron main process starts.
There are two ways to provide the Gemini API key:
- In the app — on first launch you'll be prompted to enter a key; it is stored
encrypted using Electron
safeStorage. - Via
.env— addGEMINI_API_KEY=AIza...to your.envfile.
Get a free key at aistudio.google.com/apikey — no billing required for the free tier.
- Electron + electron-vite — scaffolding and bundling
- React 19 + TypeScript — renderer UI
- Zustand — state management
- @google/genai — Gemini agent loop (function calling) and Files API
- fflate — extracting skills from zip files
Project structure:
src/
├─ main/ ← Main process (Node): IPC, fs-service, agent, secrets, skills
├─ preload/ ← contextBridge: exposes a small window.api to the renderer
└─ renderer/ ← React app (chat, browser, tree)