fito-plugin

Fito Plugin — fetch web content, extract knowledge components (execution facts, domain concepts, usage scenarios) from API/tool documentation, and generate content for social networks.

Packages

Package details

extensionskillprompt

Install fito-plugin from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:fito-plugin
Package
fito-plugin
Version
0.1.1
Published
Jun 24, 2026
Downloads
185/mo · 21/wk
Author
pasemes
License
unknown
Types
extension, skill, prompt
Size
251.2 KB
Dependencies
0 dependencies · 0 peers
Pi manifest JSON
{
  "extensions": [
    "./extensions"
  ],
  "prompts": [
    "./prompts"
  ],
  "skills": [
    "./skills"
  ],
  "agents": [
    "./agents"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

Fito Plugin

A pi package that turns documentation about a software development subject — a tool, library, framework, API, language, technique, or methodology — into structured, instructional knowledge.

It is built on the Theory of Robust Knowledge of APIs: the idea that to truly know an API (or any development tool) you need three distinct kinds of knowledge — what it is, what it does at runtime, and how to use it. Fito extracts each kind from source documents and expands it into rich, standalone content.

The plugin runs a three-stage pipeline:

  1. Ingest — fetch and clean web pages and YouTube transcripts into raw markdown.
  2. Identify — extract three kinds of knowledge components from the ingested docs.
  3. Generate — expand each identified component into a detailed, audience-calibrated document.

On purpose and scope. The package.json describes the end goal as producing content for social networks. What the plugin builds today is instructional/reference content (concept explainers, execution-fact references, and cookbook recipes) — the structured raw material such social content would be derived from. This README documents the current behavior.

Table of Contents

The Knowledge Model

Everything in this plugin is organized around three knowledge-component types. Keeping them distinct is the central design principle — each identifier and generator agent is specialized for exactly one, and each one carefully draws boundaries against the other two.

Component Captures Form Quick test
Execution Fact What the tool does at runtime Declarative claim: "when X, then Y" / "X causes/requires Y" Can a developer use it to predict behavior without running the code?
Domain Concept What an idea is, independent of the tool Definitional: the real-world concept the tool models Would the idea still exist if this tool had never been created?
Usage Scenario How to accomplish a goal with the tool Procedural: ordered steps + code + rationale Would a developer search "how do I do X with this tool?"

The three interlock: a usage scenario's steps are justified by the execution facts they rely on (or work around) and the domain concepts they are organized around. The identifier agents are explicitly instructed to extract the right type and exclude the other two — for example, a shininess parameter is an execution fact, but the "specular reflection" it encodes is a domain concept.

Examples (Three.js / Spring Boot):

  • Execution Fact — "Changes to object properties become visible only on the next rendered frame." @Service registers the annotated class as a managed bean in the application context.
  • Domain Concept — "A torus is a doughnut-shaped 3D surface." "Dependency Injection." "Specular highlight."
  • Usage Scenario — "Persisting entity data to a relational table using the Data Mapper pattern." "Handling file uploads securely in a Spring Boot service."

Pipeline & Architecture

                 ┌──────────────────────────────────────────────────────────┐
                 │                      1. INGEST                            │
  urls.txt  ───▶ │  /fetch-urls-content                                      │
                 │  (url-content-fetcher skill: web pages + YouTube)         │
                 └───────────────────────────┬──────────────────────────────┘
                                             │  cleaned markdown docs
                 ┌───────────────────────────▼──────────────────────────────┐
                 │                     2. IDENTIFY                           │
                 │  /identify-execution-facts   → execution-fact-identifier  │
                 │  /identify-domain-concepts   → domain-concept-identifier  │
                 │  /identify-usage-scenarios   → usage-scenario-identifier  │
                 │  (catalog components → .json + .md)                       │
                 └───────────────────────────┬──────────────────────────────┘
                                             │  *.json catalogs
                 ┌───────────────────────────▼──────────────────────────────┐
                 │                     3. GENERATE                           │
                 │  /generate-execution-facts → execution-fact-content-gen   │
                 │  /generate-domain-concepts → domain-concept-content-gen   │
                 │  /generate-usage-scenarios → usage-scenario-content-gen   │
                 │  (one rich .json + .md document per component)            │
                 └──────────────────────────────────────────────────────────┘

Each stage consumes the previous stage's output. The generate-* commands can optionally run the identify-* step first (--identify), which can in turn run the fetch step first (--fetch), so the whole pipeline can be triggered from a single command when needed.

A key design note from the generator agents: the Generate stage uses the agent's own training knowledge to author content — the ingested documents serve the Identify stage only. This knowledge source is intentionally isolated so it can later be replaced (e.g., by an MCP-backed knowledge service or retrieval over official docs).

Output Directory Layout

All output is written under ./output/ in the working directory, organized by stage:

output/
├── 1-ingest/
│   └── extracted_links_content/
│       ├── {slugified-title}.md        ← one cleaned doc per URL (with frontmatter)
│       └── _errors.md                  ← log of URLs that failed to fetch
├── 2-identify/
│   ├── execution_facts/
│   │   ├── execution_facts.json        ← structured catalog (primary)
│   │   └── execution_facts.md          ← human-readable summary
│   ├── domain_concepts/
│   │   ├── domain_concepts.json
│   │   └── domain_concepts.md
│   └── usage_scenarios/
│       ├── usage_scenarios.json
│       └── usage_scenarios.md
└── 3-generate/
    ├── execution_fact_content/         ← one {nnn}-{slug}.json + .md per fact
    ├── concept_content/                ← one {id}-{slug}.json + .md per concept
    └── usage_scenario_content/         ← one {id}-{slug}.json + .md per scenario

Components

The plugin registers four kinds of resources via the pi manifest in package.json:

"pi": {
  "extensions": ["./extensions"],
  "prompts": ["./prompts"],
  "skills": ["./skills"],
  "agents": ["./agents"]
}

Prompts (Slash Commands)

Thin orchestrators that parse arguments, validate prerequisites, and invoke the appropriate agent. See Command Reference for full arguments.

Command Stage Invokes
/fetch-urls-content Ingest url-content-fetcher skill
/identify-execution-facts Identify execution-fact-identifier
/identify-domain-concepts Identify domain-concept-identifier
/identify-usage-scenarios Identify usage-scenario-identifier
/generate-execution-facts Generate execution-fact-content-generator
/generate-domain-concepts Generate domain-concept-content-generator
/generate-usage-scenarios Generate usage-scenario-content-generator

Agents

Six subagents — an identifier and a content-generator per knowledge type. The full extraction/generation processes, classification tables, JSON schemas, and quality criteria live in each agent file (agents/*.md).

Agent Role
execution-fact-identifier Reads docs and catalogs execution facts. Classifies each into one or more of 15 categories (property-effect, constructor-output, parameter-semantics, return-value, side-effect, state-transition, prerequisite, ordering-constraint, environment-dependency, default-behavior, error-condition, performance-characteristic, limitation-or-bug, interaction, metadata-semantics), with abstraction level, confidence, sources, and related constructs.
domain-concept-identifier Surfaces real-world concepts the subject models, organized by domain, marked primary/supporting, with terminology mapping (standard term vs. the subject's term) and prerequisite_knowledge the subject depends on but does not model.
usage-scenario-identifier Identifies goal-oriented scenarios (goal + overview only; details come later). Enforces action-oriented goals (no "understand X") and consolidates sub-steps into meaningful developer problems.
execution-fact-content-generator Expands each fact into a document: TL;DR, Definition, Primitives Involved, optional Formal Signature / Observable Effects, Code Example, Related Facts, Misconceptions.
domain-concept-content-generator Expands each concept into a 9-section document: TL;DR, Definition, Contextualization, Terminology Mapping, Code Example, Practical Relevance, Misconceptions, Key Characteristics, Related Concepts.
usage-scenario-content-generator Expands each scenario into a cookbook recipe: TL;DR, Problem/Motivation, How It Works, ordered Steps (each with description, code, rationale), optional Alternative Flows, Consolidated Example, Related Scenarios, Misconceptions.

Templates

The content-generator agents follow a strict section template per knowledge type. The templates define section order, per-section guidance, quality gates, and explicit "forbidden patterns" (e.g., generic filler, slug-style titles, restating the source statement). Full detail in templates/*.md.

Template Used by
concept-content-template.md domain-concept-content-generator
execution-fact-content-template.md execution-fact-content-generator
usage-scenario-content-template.md usage-scenario-content-generator

Skill

Skill Purpose
url-content-fetcher Fetches and cleans content from a list of URLs (web pages and YouTube transcripts) by writing and running Python in the VM. See The url-content-fetcher Skill.

Extension

Extension Purpose
install-agents.ts On session start, symlinks the package's agents into the project's .pi/agents/ directory when they are missing or stale. See The install-agents Extension.

Command Reference

All commands take the subject name (a tool, technique, or methodology) as the first positional argument. If it is omitted, the command stops and prints usage.

/fetch-urls-content

/fetch-urls-content <URL list file path>

Reads a URL file (one URL per line; blank lines and # comments skipped), installs any needed Python packages, fetches each URL via the url-content-fetcher skill, and reports how many succeeded/failed. Defaults to urls.txt in the working directory if no path is given.

/identify-execution-facts · /identify-domain-concepts · /identify-usage-scenarios

/identify-<type> <tool-name> [--description "<text>"] [--fetch [<url-file>]] [--urls <file>] [--docs <path>] [--output <path>]
Flag Meaning Default
--description "<text>" Brief description of the subject; helps the agent infer relevant domains before reading
--fetch Run /fetch-urls-content first off
--urls <file> URL list passed to the fetch step (only with --fetch) urls.txt
--docs <path> Directory of fetched markdown docs to analyze ./output/1-ingest/extracted_links_content/
--output <path> Where to save results ./output/2-identify/<type>/

Each command verifies the docs directory contains at least one .md file (otherwise it tells you to run /fetch-urls-content first), then invokes the matching identifier agent.

/generate-execution-facts · /generate-domain-concepts · /generate-usage-scenarios

/generate-<type> <tool-name> [--version <ver>] [--<input> <path>] [--output <path>]
                 [--mode one|batch|all] [--select <ids-or-names-or-ranges>]
                 [--audience beginner|intermediate|advanced] [--language <lang>]
                 [--identify] [--docs <path>] [--urls <file>]
Flag Meaning Default
--version <ver> Target tool version, so code/API/terminology are accurate for it (generators can infer it when omitted) inferred
--facts / --concepts / --scenarios <path> Path to the stage-2 *.json catalog to expand ./output/2-identify/<type>/<type>.json
--output <path> Where to save generated documents ./output/3-generate/<type>_content/
--mode one|batch|all Process a single component, a selected subset, or all of them all
--select <…> IDs, names/fragments, or numeric ranges to process (required for one/batch). Ranges like 5-10 and mixed lists like "1-3, 10, Bean" are expanded before generation
--audience beginner|intermediate|advanced Depth and assumed knowledge intermediate
--language <lang> Natural language for all generated prose (code stays in its language) English
--identify Run the matching /identify-* step first (use when the catalog does not exist yet) off
--docs <path> Fetched-docs path, passed through to --identify ./output/1-ingest/extracted_links_content/
--urls <file> URL list, passed through to --identify urls.txt

The command resolves the catalog path and the content template, verifies both exist, creates the output directory, and invokes the matching content-generator agent with the resolved arguments.

Data Contracts

Stage 2 (Identify) writes one *.json catalog (machine-readable, the primary artifact) plus a companion *.md summary per knowledge type. Stage 3 (Generate) reads that catalog and writes one {id}-{slug}.json + .md document per component. The generator agents are constrained to write only these per-component files — no index, manifest, report, or summary files (the run summary is returned in chat).

Each catalog carries a metadata block (subject/tool name, version, documents analyzed, extraction date, totals) and a summary block (counts by category/domain/confidence and key insights). The component arrays carry:

Catalog Per-item key fields
execution_facts.json id (EF-001…), statement, categories[], abstraction_level (low/mid/high), confidence, sources[], related_constructs (types/methods/properties/parameters), preconditions[], notes
domain_concepts.json id, name, domain, relevance (primary/supporting), confidence, description, subject_terminology, standard_terminology, parent_concept, related_concepts[], sources[] — plus a separate prerequisite_knowledge[] list
usage_scenarios.json id, title, goal, overview, confidence, sources[], related_scenarios[], notes

Generated documents mirror their template's sections as JSON fields under content, with a metadata block recording tool, version (and version_inferred), audience level, language, generation date, and the source component's carried-over fields. See the agent files for the complete schemas.

The url-content-fetcher Skill

Processes a list of URLs by writing and executing Python in the VM (it deliberately does not use the built-in WebFetch tool, which can't batch from a file).

  • URL detectionyoutube.com/watch, youtu.be/, youtube.com/shorts/ are treated as YouTube; everything else as a web page.
  • YouTube — uses youtube-transcript-api; accepts transcripts in any language (prefers manual captions over auto-generated); falls back to yt-dlp --write-auto-sub --skip-download and .vtt cleanup if no transcript is available.
  • Web pages — uses a content-extraction library (trafilatura, readability-lxml). Validates the result is substantive (>200 chars); for JS-rendered pages, falls back in order to requests-html, then playwright/selenium, and only finally to requests + beautifulsoup4.
  • Cleaning — strips the extraction library's own metadata block, removes nav/footer/ads/social/related/signup boilerplate, keeps headings/links/lists/code, and breaks YouTube transcripts into natural paragraphs. No language/transcript-type disclaimers are added.
  • Output — one file per URL at ./output/1-ingest/extracted_links_content/{slugified-title}.md, each with frontmatter (source_url, title, type, fetched_at, author, and an original ≤50-word summary). Failures are logged to _errors.md; duplicate URLs are skipped; web requests use a 15s timeout.

The install-agents Extension

extensions/install-agents.ts keeps the project's agents in sync with the package's agents/ directory so the subagents are available to pi.

  • Runs on session_start with reason startup or reload.
  • Computes a SHA-256 hash of the package's agents/*.md and compares it to a .install-agents-manifest file in the project's .pi/agents/. If nothing changed, it does no work (zero cost on normal startups).
  • When it does sync, it symlinks each package agent into .pi/agents/, removes stale entries (deleted/renamed agents and plain non-symlink files), and rewrites the manifest. The manifest file itself is preserved.

Installation

Install the published package from npm:

# Global (adds to your user settings)
pi install npm:fito-plugin

# Project-local (adds to ./.pi/settings.json in the current repo)
pi install npm:fito-plugin -l

fito-plugin is unscoped, so the source is npm:fito-plugin (the npm:@scope/name form is only for scoped packages).

Once installed, manage it with:

pi list                       # confirm it's installed
pi config                     # enable/disable its prompts, agents, and skills
pi update npm:fito-plugin     # pull a newer published version
pi remove npm:fito-plugin     # uninstall (add -l for the project-local install)

From source (development)

To install a local checkout instead of the published package:

pi install ./fito-plugin       # global
pi install -l ./fito-plugin    # project-local

Typical Workflow

# 1. Ingest documentation listed in urls.txt
/fetch-urls-content urls.txt

# 2. Identify each kind of knowledge component
/identify-execution-facts <tool-name> --description "what it does"
/identify-domain-concepts <tool-name>
/identify-usage-scenarios <tool-name>

# 3. Generate detailed content for each
/generate-execution-facts <tool-name> --audience intermediate
/generate-domain-concepts <tool-name>
/generate-usage-scenarios <tool-name>

Shortcuts:

# Run identify (and fetch) automatically, then generate everything in one go
/generate-domain-concepts <tool-name> --identify --urls urls.txt

# Generate content for just a subset, at a specific version and audience
/generate-execution-facts <tool-name> --version 3.3 --mode batch --select "1-3, EF-010" --audience advanced

File Structure

fito-plugin/
├── package.json                          ← pi manifest (extensions, prompts, skills, agents)
├── extensions/
│   └── install-agents.ts                 ← syncs agents into .pi/agents/ on session start
├── prompts/
│   ├── fetch-urls-content.md
│   ├── identify-execution-facts.md
│   ├── identify-domain-concepts.md
│   ├── identify-usage-scenarios.md
│   ├── generate-execution-facts.md
│   ├── generate-domain-concepts.md
│   └── generate-usage-scenarios.md
├── skills/
│   └── url-content-fetcher/
│       └── SKILL.md
├── agents/
│   ├── execution-fact-identifier.md
│   ├── domain-concept-identifier.md
│   ├── usage-scenario-identifier.md
│   ├── execution-fact-content-generator.md
│   ├── domain-concept-content-generator.md
│   └── usage-scenario-content-generator.md
├── templates/
│   ├── concept-content-template.md
│   ├── execution-fact-content-template.md
│   └── usage-scenario-content-template.md
└── README.md

Publishing to npm

This package is published to npm as fito-plugin — unscoped and public. Publishing is a maintainer task; end users install with pi install npm:fito-plugin.

Prerequisites

  • An npm account with publish rights on the fito-plugin name (npm owner ls fito-plugin to check).
  • A clean git working tree — npm version creates a release commit and tag.

Release steps

# 1. Authenticate with npm
npm login

# 2. Bump the version. npm refuses to overwrite an already-published
#    version, so every release must increment it. This also creates a
#    commit and a git tag.
npm version patch        # 0.1.0 -> 0.1.1 (use minor/major as appropriate)

# 3. Preview exactly which files will be published
npm publish --dry-run

# 4. Publish (the package is public and unscoped, so no --access flag is needed)
npm publish

# 5. Push the version commit and its tag
git push --follow-tags

# 6. Verify
npm view fito-plugin version

What gets published

There is no files allowlist or .npmignore, so npm falls back to .gitignore. Everything needed at runtime ships: prompts/, agents/, skills/, templates/, extensions/, plus package.json and README.md. Two things to keep in mind:

  • templates/ ships as plain data, not as a pi resource. The generate-* commands read the template files directly from the installed package's templates/ directory, so the files must be present in the published tarball. They are not declared in the pi manifest — and need not be, since the manifest only registers extensions, prompts, skills, and agents. With the current .gitignore-based file selection they are published automatically. Caveat: if you later add an explicit files allowlist to package.json, include templates/ or generation will break for installed users.
  • extensions/install-agents.ts ships as raw TypeScript. There is no build step (and .gitignore excludes dist/), consistent with pi loading .ts directly — no compile step is required before publishing.