Fable Developer

v0.0.0

Use when working on the Fable codebase — modifying, debugging, or extending any part of the Electron + React creative writing app. Covers architecture, codin...

0· 12·0 current·0 all-time
MIT-0
Download zip
LicenseMIT-0 · Free to use, modify, and redistribute. No attribution required.
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
The name/description (Fable Developer) align with the provided content: architecture notes, recipes, IPC/channel lists, and workspace layout for an Electron+React app. There are no unexpected env vars, binaries, or install steps requested that would be unrelated to a developer guide.
Instruction Scope
SKILL.md and the reference docs provide detailed developer-facing procedures (adding IPC handlers, commands, storage layout, agent/tool descriptions). They reference on-disk paths (project manifest, files/, .fable/chat.db), IPC channels, and tooling (adding API keys when adding an LLM provider) — all appropriate for a repo guide. Note: the instructions assume access to the project workspace and describe operations that would modify the codebase; the skill itself is instruction-only and does not execute code, but an agent using this guide could recommend or draft code changes that would need to be applied by a user.
Install Mechanism
No install spec and no code files that would be written/executed. Instruction-only skills are lowest-risk for install-time code execution.
Credentials
The skill declares no required environment variables, credentials, or config paths. The docs mention that adding a new LLM provider would require adding an API key, but the skill does not request any secrets itself — proportionate for a developer reference.
Persistence & Privilege
Flags show default behavior (always: false, autonomous invocation allowed). The skill does not request permanent presence or elevated privileges and does not modify other skills' configuration. As with any developer skill, autonomous invocation gives the agent discretion to act, but this is platform default.
Assessment
This skill is an internal developer handbook for the Fable codebase — it is coherent with its stated purpose and requests nothing sensitive. Before installing: confirm you actually want an assistant that will advise on editing this specific codebase (the guide assumes the project repository and discusses file paths, IPC channels, and the per-project chat DB). The skill itself doesn't execute code or ask for secrets, but an agent using it may suggest code edits or commands that would modify local files; if you enable autonomous invocation, consider whether to allow the agent to run actions that change your repo or to require manual approval for any file changes.

Like a lobster shell, security has layers — review code before you run it.

latestvk97dwp9se7nxttfn945p5sbfs9842n43

License

MIT-0
Free to use, modify, and redistribute. No attribution required.

SKILL.md

Fable Development Guide

Fable is a creative-writing desktop app: Electron + React 19 + Vite + TanStack Query + Plate.js frontend, Node.js + SQLite + custom indexed filesystem backend, Google ADK for AI features.

Critical Invariant

Every file can have children, not just folders. FileNode.children exists on ANY node regardless of category. A text document can contain child documents (chapters containing scenes). Never assume only folders have children.

parentId and siblingIndex are computed by buildFileTree() at runtime — never persist them.

Where Does My Code Go?

digraph code_placement {
    rankdir=TB;
    node [shape=diamond];
    "Used by both\nfrontend & backend?" -> "src/shared/" [label="yes"];
    "Used by both\nfrontend & backend?" -> "Runs in\nNode.js only?" [label="no"];
    "Runs in\nNode.js only?" -> "IPC handler?" [label="yes"];
    "Runs in\nNode.js only?" -> "React component\nor hook?" [label="no"];
    "IPC handler?" -> "src/backend/handlers/" [label="yes"];
    "IPC handler?" -> "src/backend/services/" [label="no"];
    "React component\nor hook?" -> "src/frontend/components/" [label="component"];
    "React component\nor hook?" -> "src/frontend/hooks/" [label="hook"];
    "React component\nor hook?" -> "src/frontend/services/" [label="service/singleton"];

    node [shape=box];
    "src/shared/" [style=filled, fillcolor="#e8f5e9"];
    "src/backend/handlers/" [style=filled, fillcolor="#e3f2fd"];
    "src/backend/services/" [style=filled, fillcolor="#e3f2fd"];
    "src/frontend/components/" [style=filled, fillcolor="#fff3e0"];
    "src/frontend/hooks/" [style=filled, fillcolor="#fff3e0"];
    "src/frontend/services/" [style=filled, fillcolor="#fff3e0"];
}

Shared code constraint: src/shared/ must NOT import browser APIs, Node.js APIs, or React.

How Do I Access / Mutate Data?

digraph data_access {
    rankdir=TB;
    node [shape=diamond];
    "Inside React\ncomponent?" -> "Use query hooks" [label="yes"];
    "Inside React\ncomponent?" -> "Use queryService\nsingleton" [label="no\n(command, service)"];

    "Need to mutate\nfile tree?" -> "queryService.mutations.*\n(optimistic updates)" [label="always"];
    "Need to read\nfile content?" -> "readFileContent()\nhelper (cache-first)" [label="preferred"];

    node [shape=box];
    "Use query hooks" [style=filled, fillcolor="#e8f5e9"];
    "Use queryService\nsingleton" [style=filled, fillcolor="#e8f5e9"];
    "queryService.mutations.*\n(optimistic updates)" [style=filled, fillcolor="#fff3e0"];
    "readFileContent()\nhelper (cache-first)" [style=filled, fillcolor="#fff3e0"];
}

Never call window.api.* directly for tree mutations — always go through queryService.mutations.* which handles optimistic updates and rollback.

Key Directories

DirectoryWhat to find
src/types.tsAll shared types (FileNode, FileMetadata, ChatSession, Agent, etc.)
src/shared/Code shared by both processes (graph, agentFlow, toolDescriptors, search)
src/backend/handlers/IPC handlers: file, project, agent, agentFlow
src/backend/services/IndexedFsService, UserDataService, ReferenceIndexService, agent/
src/backend/services/agent/AI system: AdkRunner, ToolFactory, providers, ChatDatabaseService
src/frontend/components/All React components (chat/, graph/, fileViewer/, collectionViewer/)
src/frontend/services/commandInfra/VS Code-style commands, keybindings, context keys
src/frontend/services/query/TanStack Query: queryService, mutations, treeTransformations
src/frontend/hooks/Custom hooks: useFileTree, useChat, useAgentFlowRun, etc.
src/frontend/styles/plate/Plate.js editor plugins and kits
src/locales/{en,zh-CN}/i18n translations (8 namespaces)
e2e/Playwright E2E tests
electron/preload.tsIPC bridge — window.api.* definitions
src/global.d.tsTypeScript declarations for Window.api

Common Task Recipes

Read references/recipes.md for detailed step-by-step procedures including:

  • Adding a new IPC channel (5-step checklist)
  • Adding a new command (5-step checklist)
  • Adding a new file subType (8-step checklist)
  • Adding a new agent tool (6-step checklist)
  • Adding a new sidebar panel or editor handler
  • Adding i18n strings

Architecture at a Glance

Read references/architecture.md for the full breakdown. Key mental model:

Frontend (React) --window.api.*--> Preload --IPC--> Backend handlers --> Services --> Disk
                 <--transport push events--  <--IPC--  ProjectManager <-- IndexedFsService events
  • State: TanStack Query is single source of truth. staleTime: Infinity everywhere.
  • File tree: Event-driven push from backend, never polled. useFileTree sets up listener.
  • Mutations: createTreeMutation factory: optimistic update -> IPC call -> rollback on error.
  • Commands: VS Code-style CommandService + ContextService + KeybindingService.
  • Editor routing: ContentViewer dispatches by subType first, then category.
  • AI: Google ADK with multi-provider LLM registry. See references/agent-system.md.

i18n Checklist

  • 8 namespaces: common, fileExplorer, chat, project, editor, agentBuilder, graph, agentDefinition
  • In components: const { t } = useTranslation("namespace")
  • Outside React: import i18n from "@/src/i18n/i18n"; i18n.t("ns:key")
  • Always add keys to BOTH en and zh-CN

Build, Lint & Test

npm run dev:electron     # Dev mode (Vite + Electron)
npm run build            # Production build
npm run check            # Lint + format + TypeScript check
npm run test:e2e         # Playwright E2E tests (headless)
npm run test:e2e:headed  # E2E with visible browser
  • Path alias: @/* maps to repo root
  • Formatting: Prettier (double quotes, 4-space indent, semicolons)
  • Always run E2E tests you wrote before committing

Pitfalls

  1. Any node can have children — not just folders
  2. parentId/siblingIndex are derived — never persist
  3. Tree mutations must be puretreeTransformations.ts returns new arrays, never mutate
  4. Always add i18n to BOTH localesen and zh-CN
  5. Toolbar renders via portal#file-toolbar-portal in TopBar, not inside editor DOM
  6. Input elements suppress keybindingsuseKeybindings checks event.target tag
  7. subType controls routing — checked before category in ContentViewer
  8. Binary files use base64 over IPC — text uses UTF-8
  9. STRUCTURAL_FILE_CHANGES control broadcasts — content "update" does NOT re-push tree
  10. Add Window.api types — update src/global.d.ts when adding IPC channels
  11. Shared code is process-agnosticsrc/shared/ cannot import browser or Node APIs
  12. Tool descriptors are sharedtoolDescriptors.ts serves both UI commands and LLM agents
  13. Every user-facing data element needs a tooltip

References

ReferenceUse when
references/architecture.mdUnderstanding layers, IPC channels, backend services, frontend providers
references/command-system.mdWorking with commands, keybindings, context keys, when clauses
references/workspace-structure.mdOn-disk file layout, metadata schema, storage guidelines
references/agent-system.mdAI features: providers, streaming, tools, planning mode, chat persistence
references/recipes.mdStep-by-step procedures for common development tasks

Files

6 total
Select a file
Select a file to preview.

Comments

Loading comments…