sklz lets you cherry-pick skills from multiple folders into each agent's folder. List and sync them by copy or symlink—interactively or through agent-friendly commands.
F# makes sklz concise, reliable, and practical to maintain while retaining the mature .NET ecosystem.
-
Strong domain modelling — F# records, discriminated unions, pattern matching, and type inference let the code describe the application’s concepts directly. This makes invalid states harder to represent and shifts many integration mistakes from runtime into compiler errors, so a change that builds and passes tests has stronger correctness guarantees.
-
Efficient for AI context — An exploratory Rosetta Code comparison found F# and Haskell among the more token-efficient typed languages, close to the best dynamic languages tested. F# gains much of this from type inference: it avoids repetitive declarations while preserving compiler and language-server feedback, keeping code, diffs, and AI-agent context more compact.
-
Pragmatic platform choice — F# runs on .NET, providing established cross-platform build, test, packaging, and deployment tooling alongside libraries such as Spectre.Console for the terminal interface. Go and Rust were considered, but F# gives this project a more direct implementation and maintenance path without giving up performance or ecosystem support.
Install the latest release on macOS or Linux with:
curl -fsSL https://raw.githubusercontent.com/rodsfreitas/sklz/main/install.sh | shThis detects your OS and architecture, downloads the matching self-contained
binary from the latest GitHub release, and installs it to ~/.local/bin (falling
back to /usr/local/bin). Pin a specific version with
SKLZ_VERSION=v0.5.0.
Every push to main can produce a release automatically based on Conventional
Commits (feat → minor, fix → patch, BREAKING CHANGE → major); GitHub
Actions builds and attaches binaries for macOS (arm64/x64), Linux (x64/arm64),
and Windows (x64).
The project supports syncing skills for Claude, Codex, and Pi.
# Create the default sklz configuration.
sklz init
# Add another existing folder that contains skills (optional).
sklz source add personal ~/Developer/personal-skills
# See skills discovered across configured source folders.
sklz list
# Interactively choose skills and agent targets to sync.
sklz sync
# Or sync every skill to Claude without prompts (useful for agents).
sklz sync --all --to claudeThis project is licensed under the MIT License. See LICENSE for details.
See CONTRIBUTING.md for setup, testing, commit, and pull-request guidance.
Requires .NET 10 SDK. This is also the path for contributors, or for running straight from a checkout without waiting on a release.
dotnet build src/Sklz/Sklz.fsproj
# create ~/.sklz/config.toml with sensible defaults
dotnet run --project src/Sklz/Sklz.fsproj -- init
# list source skills + per-target install state
dotnet run --project src/Sklz/Sklz.fsproj -- list
# add Pi's global skills folder as a named source
dotnet run --project src/Sklz/Sklz.fsproj -- source add pi ~/.pi/agent/skills
# interactively pick skills (grouped by source folder) + targets to sync
dotnet run --project src/Sklz/Sklz.fsproj -- sync
# sync one skill by name; qualify as <source>/<name> if the name is ambiguous
dotnet run --project src/Sklz/Sklz.fsproj -- sync my-skill --to claude
# batch: several skills, several targets, or everything
dotnet run --project src/Sklz/Sklz.fsproj -- sync pp iterate commit --to claude
dotnet run --project src/Sklz/Sklz.fsproj -- sync my-skill --to claude,codex,pi
dotnet run --project src/Sklz/Sklz.fsproj -- sync --all --to claude~/.sklz/config.toml (override the location with the SKLZ_CONFIG
environment variable). Skills can live in more than one folder, declared as
named [sources.<name>] sections:
[sources.personal]
path = "~/notes/skills"
[sources.work]
path = "~/Developer/work-skills"
[targets.claude]
path = "~/.claude/skills"
[targets.codex]
path = "~/.codex/skills"
[targets.pi]
path = "~/.pi/agent/skills"
[sync]
# "copy" (default) or "symlink"
strategy = "copy"Add a named source without editing TOML with sklz source add <name> <path>.
The folder must already exist; for Pi global skills, use
sklz source add pi ~/.pi/agent/skills.
The legacy single-source form still works and is treated as one source named
default:
[skills]
source = "~/ai-skills"init— writes~/.sklz/config.tomlwith default paths if it doesn't already exist.source add <name> <path>— adds an existing folder as a named source while preserving the rest of the config file.list— scans each configured source folder for{skill}/SKILL.md, parses optional YAML frontmatter (name,description,dateAdded), and renders one table per source showing whether each skill is also present under the configured Claude, Codex, and Pi skill folders. Skill names that appear in more than one source are flagged.sync— interactive picker grouped by source folder:<space>on a folder header toggles the whole folder,<space>on a skill toggles just that skill, then choose targets.sync <name>... --to <targets>— installs the named skills into the named targets, searching every source.<targets>isclaude,codex,pi, or a comma-separated list (claude,codex,pi). Pi defaults to~/.pi/agent/skills. If a name exists in more than one source the command lists the candidates; disambiguate withsync <source>/<name> --to …. The[sync] strategycontrols whether skills are copied (the default) or directory-symlinked.sync --all --to <targets>— installs every skill from every source.
The whole batch is validated before anything is copied: an ambiguous name, an
unknown skill, or an invalid target aborts with nothing written, and every
offending name is reported rather than just the first. Each copy prints
name → target (created|overwritten), followed by a summary count. The command
exits non-zero if any copy failed.
Drift detection, doctor, symlink strategy, etc. come in later iterations.
src/Sklz/
Domain.fs types (Skill, Target, …)
Frontmatter.fs tiny YAML frontmatter reader
Config.fs load/write ~/.sklz/config.toml (multi-source aware)
Scanner.fs discover {skill}/SKILL.md under a source folder
Inventory.fs join source skills with per-target install state, per source
Sync.fs copy a skill folder into a target
Table.fs ASCII table renderer
Commands.fs init + list + sync
Program.fs arg dispatch