Agent skill

Platform Manifest Generate

by forcedotcom in forcedotcom/sf-skills

A skill your agent uses to generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir, a component list, or org introspection.

Apache-2.0Auto-check passedSales & Support

Install Platform Manifest Generate

skills CLI
$ npx skills add forcedotcom/sf-skills --skill platform-manifest-generate -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install forcedotcom/sf-skills platform-manifest-generate --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/forcedotcom/sf-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/builder/salesforce-development/skills/platform-manifest-generate .claude/skills/platform-manifest-generate && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
platform-manifest-generate
GitHub stars
1.1k
Token cost
~3.4k tokens
SKILL.md length
1,178 words
Files
2 (incl. references)
Skills in repo
251
Repo updated
First seen
Licence
Apache-2.0

At a glance

A skill your agent uses to generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir, a component list, or org introspection.

  • Works in 4 steps: Resolve the components yourself (e.g.… → Group by metadata type. → Emit the XML inline using the schema… → …
  • Generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir
  • SKILL.md covers Tool Restrictions, When This Skill Owns the Task, Two Generation Paths and API Version Handling, plus 5 more sections
  • Calls sf, git and jq; reaches soap.sforce.com

What it does

Platform Manifest Generate is an agent skill from forcedotcom/sf-skills. Use to generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir, a component list, or org introspection. Trigger on 'generate a package.xml from this folder', 'create a manifest for these classes', 'I need a deploy manifest', or 'destructiveChanges.xml for deletions'. Encodes wildcard-vs-explicit-member rules per metadata type. DO NOT TRIGGER to deploy (platform-metadata-deploy), delete (platform-destructive-deploy), or retrieve (platform-metadata-retrieve).

Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/wildcard-allowlist.md`).

It sits in Sales & Support. It works with Salesforce. The repository describes itself as: Salesforce's curated collection of agent skills for building applications. Optimized for Agentforce Vibes, compatible with all AI tools. The licence is Apache-2.0.

When your agent uses it

  • Generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir
  • A component list
  • Org introspection
  • Generate a package.xml from this folder

Example prompts

  • “generate a package.xml from this folder”
  • “create a manifest for these classes”
  • “I need a deploy manifest”
  • “/platform-manifest-generate”

Workflow steps

4 steps, taken from the first numbered list in SKILL.md.

  1. Resolve the components yourself (e.g. parse git diff --name-only and map paths back to metadata types).
  2. Group by metadata type.
  3. Emit the XML inline using the schema below.
  4. Always cross-check by running sf project deploy start --manifest --dry-run (hand off to platform-metadata-deploy).

What it can do on your machine

Read from SKILL.md and the folder at commit e5164d9. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • sf
    • git
    • jq

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • soap.sforce.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Platform Manifest Generate loads about 3.4k tokens when it runs, and up to ~4.7k if it reads all its reference files. Until then it costs about 132 tokens; SKILL.md has 1,178 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~132
When it runs · the whole SKILL.md, loaded when a task matches
~3.4k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~4.7k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from forcedotcom/sf-skills at commit e5164d9, republished under its Apache-2.0 licence (© forcedotcom). 1,178 words, ~3,387 tokens.

Download SKILL.mdSave it as .claude/skills/platform-manifest-generate/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
platform-manifest-generate
description
Use to generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir, a component list, or org introspection. Trigger on 'generate a package.xml from this folder', 'create a manifest for these classes', 'I need a deploy manifest', or 'destructiveChanges.xml for deletions'. Encodes wildcard-vs-explicit-member rules per metadata type. DO NOT TRIGGER to deploy (platform-metadata-deploy), delete (platform-destructive-deploy), or retrieve (platform-metadata-retrieve).
metadata.version
1.0
metadata.relatedSkills
platform-metadata-deploy, platform-metadata-retrieve, platform-destructive-deploy, platform-deploy-validate

platform-manifest-generate

Produce a Salesforce metadata manifest — package.xml (or one of the destructive variants) — from local source, an org, or an explicit component list. This skill is purely about authoring the manifest file. Hand off to platform-metadata-deploy or platform-destructive-deploy once the file exists.


Tool Restrictions

Use ONLY the Bash tool to run sf project generate manifest, and the Write tool for the hand-built fallback path. Do NOT use MCP tools.


When This Skill Owns the Task

Use platform-manifest-generate when the work involves any of:

  • Building a package.xml from a source directory (e.g. force-app/main/default/classes/)
  • Building a manifest from an explicit list of components (e.g. AccountService, ContactSelector, Account)
  • Building a manifest by introspecting an org via --from-org
  • Producing destructiveChanges.xml, destructiveChangesPre.xml, or destructiveChangesPost.xml for a deletion
  • Producing both a package.xml and a destructive manifest in one operation

Delegate elsewhere when the user is:

  • Running the deploy itself → platform-metadata-deploy
  • Validating before a prod release → platform-deploy-validate
  • Executing the destructive deploy → platform-destructive-deploy (that skill uses the manifest this skill generates)
  • Retrieving metadata to local → platform-metadata-retrieve

Two Generation Paths

Wrap sf project generate manifest. Always prefer this path; it knows about every metadata type and produces canonical XML — and never emits *, sidestepping the wildcard hazard entirely.

The CLI offers three input modes (mutually exclusive):

InputFlagUse when
Source directory--source-dir (-p)User points to a folder containing already-on-disk metadata
Component list--metadata (-m)User names specific components, e.g. ApexClass:AccountService CustomObject:Account
Org introspection--from-orgUser wants every component currently in an org (or a filtered subset)

You can specify either --source-dir or --metadata, not both. --from-org may be combined with --metadata (filter included types) or --excluded-metadata (filter out types).

Verified flags (do not invent flags — verify with sf project generate manifest --help if unsure):

FlagPurpose
--source-dir, -pLocal source paths to scan
--metadata, -mComponent names to include (e.g. ApexClass:AccountService)
--from-orgUsername or alias of org to introspect
--name, -nCustom output filename (mutually exclusive with --type)
--type, -tPredefined manifest kind: package | pre | post | destroy
--output-dir, -dDirectory to write the manifest into
--api-versionOverride the API version for the request
--include-packages, -cInclude managed and/or unlocked package metadata when using --from-org
--excluded-metadataTypes to exclude when using --from-org
--jsonMachine-readable output

Manifest filename by --type:

--typeOutput file
package (default)package.xml
predestructiveChangesPre.xml
postdestructiveChangesPost.xml
destroydestructiveChanges.xml

You can specify either --type or --name, not both.

Canonical CLI examples
bash
# Build package.xml from a source dir
sf project generate manifest \
  --source-dir force-app/main/default \
  --name package.xml \
  --output-dir manifest \
  --json

# Build package.xml from an explicit component list
sf project generate manifest \
  --metadata ApexClass:AccountService \
  --metadata ApexClass:ContactSelector \
  --metadata CustomObject:Account \
  --name package.xml \
  --output-dir manifest \
  --json

# Build destructiveChanges.xml from a component list
sf project generate manifest \
  --metadata CustomField:Account.OldField__c \
  --metadata CustomField:Account.OldStatus__c \
  --type destroy \
  --output-dir manifest \
  --json

# Build a manifest by introspecting an org (filtered)
sf project generate manifest \
  --from-org <alias> \
  --metadata ApexClass,CustomObject,CustomLabels \
  --output-dir manifest \
  --json

If both a package.xml and a destructive manifest are needed, run the CLI twice — once with --type package (or default), once with --type destroy / pre / post.

Path B — Hand-built fallback

Use this only when the CLI cannot express the user's intent — e.g. they want "just the Apex classes I changed today" and the change set is derived from git diff rather than a clean directory or component list. In that case:

  1. Resolve the components yourself (e.g. parse git diff --name-only and map paths back to metadata types).
  2. Group by metadata type.
  3. Emit the XML inline using the schema below.
  4. Always cross-check by running sf project deploy start --manifest <file> --dry-run (hand off to platform-metadata-deploy).
Manifest XML schema

Root element is <Package> in the metadata namespace. Each metadata type gets one <types> block containing one <members> per component plus a single <name>. The trailing <version> declares the API version for the manifest.

xml
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <types>
        <members>AccountService</members>
        <members>ContactSelector</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>Account</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>Account.Status__c</members>
        <name>CustomField</name>
    </types>
    <version>62.0</version>
</Package>

Notes:

  • For component-bound types like CustomField, BusinessProcess, RecordType, Layout, ListView, ValidationRule, WebLink, members use Object.Name notation.
  • destructiveChanges.xml, destructiveChangesPre.xml, and destructiveChangesPost.xml use the same XML structure — only the filename and intent differ.
  • An empty manifest (no <types> blocks) is legal and is sometimes paired with a destructive manifest:
xml
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <version>62.0</version>
</Package>

API Version Handling

The <version> element at the bottom of every manifest must reflect the project's API version.

Resolution order:

  1. Read sourceApiVersion from sfdx-project.json at the project root.
  2. If --api-version was passed by the user, use that instead.
  3. If neither is available, fall back to the value reported by sf --version (the CLI's bundled API version) — but warn the user and recommend they set sourceApiVersion in sfdx-project.json for reproducibility.
  4. Never silently hardcode a value (e.g. 62.0) into output without surfacing the source.
bash
# Quick read of sourceApiVersion
jq -r '.sourceApiVersion' sfdx-project.json

When using the CLI path, omit --api-version unless the user explicitly overrides — the CLI already reads sourceApiVersion.


Show full SKILL.md (475 more words)Show less

Wildcard Members (<members>*</members>)

A wildcard member matches every component of that metadata type. It is not legal for every type. Using * for a disallowed type causes deploy/retrieve errors like Wildcards are not supported for this metadata type.

Wildcard NOT allowed (must enumerate)

These types require explicit member names. Common examples: Profile, PermissionSet, PermissionSetGroup, CustomLabels, CustomObjectTranslation, Layout, Workflow (in some package configurations), SharingRules, StandardValueSet, ManagedTopics, and most "container" types whose contents are object-bound (CustomField, RecordType, BusinessProcess, ListView, ValidationRule, WebLink, CompactLayout).

For these, enumerate explicitly:

xml
<types>
    <members>Admin</members>
    <members>Standard User</members>
    <name>Profile</name>
</types>
Wildcard generally allowed

Most "self-contained" component types accept *. Examples: ApexClass, ApexTrigger, ApexComponent, ApexPage, AuraDefinitionBundle, LightningComponentBundle, CustomApplication, CustomTab, StaticResource, EmailTemplate, Report, Dashboard, Flow, FlexiPage, CustomMetadata. See references/wildcard-allowlist.md for the full enumeration and edge cases.

Rule of thumb: if you are not certain, list the components explicitly. The CLI path (--source-dir / --metadata) sidesteps this problem because it never emits *.


Examples

Example 1 — Build package.xml from a directory

"Generate package.xml from force-app/main/default/classes/"

bash
sf project generate manifest \
  --source-dir force-app/main/default/classes \
  --name package.xml \
  --output-dir manifest \
  --json

Result: manifest/package.xml listing every Apex class in that folder.

Example 2 — Build a manifest covering specific components

"Build a manifest covering AccountService, ContactSelector, and the Account custom object"

bash
sf project generate manifest \
  --metadata ApexClass:AccountService \
  --metadata ApexClass:ContactSelector \
  --metadata CustomObject:Account \
  --name package.xml \
  --output-dir manifest \
  --json

Result: manifest/package.xml containing exactly those three components.

Example 3 — Generate both package.xml and destructiveChanges.xml for deletions

"Create both package.xml and destructiveChanges.xml for these deletions: Account.OldField__c, Account.OldStatus__c"

bash
# Empty/minimal package.xml (deletion-only deploy still needs a package descriptor)
sf project generate manifest \
  --metadata CustomLabels \
  --name package.xml \
  --output-dir manifest \
  --json

# destructiveChanges.xml
sf project generate manifest \
  --metadata CustomField:Account.OldField__c \
  --metadata CustomField:Account.OldStatus__c \
  --type destroy \
  --output-dir manifest \
  --json

After generation, hand off to platform-destructive-deploy to validate and execute the deletion.


Failure Modes

SymptomLikely causeRecovery
Path does not exist: <dir>--source-dir points at a missing folderConfirm the path; use ls to verify; default to force-app/main/default if the user is vague
Generated manifest is emptySource dir contained no recognizable metadata, or all files were ignoredCheck .forceignore; verify the path actually contains metadata files (*.cls, *-meta.xml, etc.)
Wildcards are not supported for this metadata type at deploy timeHand-built manifest used * for a disallowed typeSee the wildcard allowlist above; enumerate the components explicitly
<version> missing or mismatchedsfdx-project.json lacks sourceApiVersionAdd sourceApiVersion to sfdx-project.json, or pass --api-version to the CLI
You can specify either --type or --name, but not bothCLI invocation passed both flagsDrop one; use --type for predefined names, --name for a custom one
You can specify either --source-dir or --metadata, but not bothCLI invocation passed bothPick one input mode
Components missing from --from-org outputOrg introspection batched too aggressively, or the type is in a managed packageSet SF_LIST_METADATA_BATCH_SIZE lower; add --include-packages managed if intended

Cross-Skill Integration

NeedDelegate toReason
Run a deploy with the generated manifestplatform-metadata-deployThis skill stops at file generation
Validate before a prod releaseplatform-deploy-validatePre-flight test against prod
Actually delete the components in the destructive manifestplatform-destructive-deployThat skill validates and executes the destructive deploy
Retrieve metadata listed in the manifestplatform-metadata-retrievePulls org metadata to local
Author the metadata being listed in the manifestOther platform-* generators (e.g. platform-custom-object-generate)The manifest just lists what already exists on disk

Completion Format

text
Manifest goal: <package | pre | post | destroy>
Input mode: <source-dir | metadata list | from-org | hand-built>
Output: <path/to/manifest.xml>
API version: <value> (source: sfdx-project.json | --api-version | CLI default)
Component count: <N> across <M> metadata types
Next step: <platform-metadata-deploy | platform-deploy-validate | platform-destructive-deploy>

© forcedotcom, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in plugins/builder/salesforce-development/skills/platform-manifest-generate of forcedotcom/sf-skills.

  • SKILL.md
  • references/wildcard-allowlist.md

Open the folder on GitHubat commit e5164d9

Compare with similar skills

Platform Manifest Generate next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Platform Manifest Generate compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Platform Manifest Generate this skillforcedotcom/sf-skills1.1k—~3.4kAutomated safety check: PassApache-2.0
Services Extension Consumptionforcedotcom/salesforcedx-vscode1k—~5kAutomated safety check: PassBSD-3-Clause
Soql Lib Query Builderbeyond-the-cloud-dev/soql-lib154—~4.3kAutomated safety check: PassMIT
Sf DatacloudJaganpro/sf-skills424—~2.7kAutomated safety check: PassMIT
Soql Lib Selectorbeyond-the-cloud-dev/soql-lib154—~2kAutomated safety check: PassMIT
Core Extension APIforcedotcom/salesforcedx-vscode1k—~842Automated safety check: PassBSD-3-Clause

Similar skills

  • Services Extension Consumption

    forcedotcom/salesforcedx-vscode

    Consume the salesforcedx-vscode-services extension API. An agent skill from forcedotcom/salesforcedx-vscode.

    1k GitHub stars~5k tokensUpdated today
    Sales & SupportAuto-check passed
  • Soql Lib Query Builder

    beyond-the-cloud-dev/soql-lib

    Builds Salesforce SOQL queries using the SOQL Lib fluent builder API (SOQL.cls).

    154 GitHub stars~4.3k tokensUpdated 6 days ago
    Sales & SupportAuto-check passed
  • Sf Datacloud

    Jaganpro/sf-skills

    Salesforce Data Cloud product orchestrator for connect→prepare→harmonize→segment→act workflows.

    424 GitHub stars~2.7k tokensUpdated 5 mo ago
    Sales & SupportAuto-check passed
  • Soql Lib Selector

    beyond-the-cloud-dev/soql-lib

    Creates Salesforce Apex selector classes using the SOQL Lib selector pattern.

    154 GitHub stars~2k tokensUpdated 6 days ago
    Sales & SupportAuto-check passed
  • Core Extension API

    forcedotcom/salesforcedx-vscode

    Public API exported by salesforcedx-vscode-core activate(). An agent skill from forcedotcom/salesforcedx-vscode.

    1k GitHub stars~842 tokensUpdated today
    Sales & SupportAuto-check passed
  • Dev Setup

    Portwood-Global-Solutions/Portwood

    Get from a fresh clone of Portwood to a working, fully-tested Salesforce org.

    126 GitHub stars~1.1k tokensUpdated today
    Sales & SupportAuto-check passed

More from forcedotcom/sf-skills

All 251 skills in this repo
  • Agentforce Architecture Analyze

    forcedotcom/sf-skills

    Declared architecture snapshot for one Agentforce agent: planner, topics, actions, flows, Apex, prompt templates, and NGA plugins.

    1.1k GitHub stars~4.5k tokensUpdated 2 days ago
    Auto-check passed
  • Agentforce D360 Analyze

    forcedotcom/sf-skills

    Data Cloud 360° view of a single Agentforce session. An agent skill from forcedotcom/sf-skills.

    1.1k GitHub stars~3.4k tokensUpdated 2 days ago
    Auto-check passed
  • Apply a Salesforce sandbox post-copy automation JSON config against a target org.

    1.1k GitHub stars~5.3k tokensUpdated 2 days ago
    Auto-check: notes
  • Apply a Salesforce sandbox post-copy automation JSON config against a target org.

    1.1k GitHub stars~5.4k tokensUpdated 2 days ago
    Auto-check: notes
  • Design Systems Slds Apply

    forcedotcom/sf-skills

    Apply SLDS-compliant UI using the correct blueprints, styling hooks, utility classes, and icons.

    1.1k GitHub stars~3.7k tokensUpdated 2 days ago
    Auto-check passed
  • Experience Lwc Generate

    forcedotcom/sf-skills

    Lightning Web Components with PICKLES methodology and 165-point scoring.

    1.1k GitHub stars~2.4k tokensUpdated 2 days ago
    Auto-check passed

Works with

Categories

Questions about Platform Manifest Generate

What does Platform Manifest Generate do?

A skill your agent uses to generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir, a component list, or org introspection. Platform Manifest Generate is an agent skill from forcedotcom/sf-skills.xml / Pre / Post) from a source dir, a component list, or org introspection.

When should I use Platform Manifest Generate?

Platform Manifest Generate fits situations like: generate a package.xml (and optionally destructiveChanges.xml / Pre / Post) from a source dir; A component list; org introspection; generate a package.xml from this folder.

How do I install Platform Manifest Generate in Claude Code?

Run `npx skills add forcedotcom/sf-skills --skill platform-manifest-generate -a claude-code`. Or copy the skill folder (plugins/builder/salesforce-development/skills/platform-manifest-generate in forcedotcom/sf-skills) into .claude/skills/platform-manifest-generate in your project. Claude Code loads it when a task matches its description.

How do I install Platform Manifest Generate in Codex?

Run `npx skills add forcedotcom/sf-skills --skill platform-manifest-generate -a codex`. Or copy the skill folder (plugins/builder/salesforce-development/skills/platform-manifest-generate in forcedotcom/sf-skills) into .agents/skills/platform-manifest-generate in your project. Codex loads it when a task matches its description.

Can I use Platform Manifest Generate in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add forcedotcom/sf-skills --skill platform-manifest-generate -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/platform-manifest-generate, .gemini/skills/platform-manifest-generate, .github/skills/platform-manifest-generate and .opencode/skills/platform-manifest-generate in your project.

What does Platform Manifest Generate need to run?

Going by SKILL.md and its folder, Platform Manifest Generate needs the command-line tools its instructions call (sf, git and jq).

Does Platform Manifest Generate access the network?

SKILL.md names 1 domain. In commands or code: soap.sforce.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Platform Manifest Generate safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Platform Manifest Generate use?

Platform Manifest Generate is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Platform Manifest Generate use?

About 3.4k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.3k tokens, read only when the agent opens those files.

What are the alternatives to Platform Manifest Generate?

Skills that share tags, products or a category with Platform Manifest Generate: Services Extension Consumption (forcedotcom/salesforcedx-vscode, 1k stars), Soql Lib Query Builder (beyond-the-cloud-dev/soql-lib, 154 stars), Sf Datacloud (Jaganpro/sf-skills, 424 stars) and Soql Lib Selector (beyond-the-cloud-dev/soql-lib, 154 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Platform Manifest Generate?

forcedotcom (a GitHub organization) maintains it in forcedotcom/sf-skills, which has 1,065 GitHub stars. The repository holds 251 skills in this directory. The repository was last updated on October 7, 2026.

Source: forcedotcom/sf-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.