Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,039 changes: 72 additions & 967 deletions README.md

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Skiller docs

Start here if you want the short, accurate version.

- `docs/cli.md`: commands + flags
- `docs/config.md`: `skiller.toml` reference + precedence
- `docs/skills.md`: skills + propagation + Claude plugins/commands/agents sync
- `docs/agents.md`: supported agents + default paths
- `docs/mcp.md`: MCP server config + propagation
- `docs/troubleshooting.md`: common failures + fixes
- `docs/development.md`: dev workflow
- `docs/migration-from-ruler.md`: notes for `ruler` users

Notes and design history live in:

- `docs/plans/`
- `docs/brainstorms/`
44 changes: 44 additions & 0 deletions docs/agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Supported agents

This is the list in `src/agents/index.ts`.

Columns:

- Rules: instruction file(s) written by `skiller apply`
- MCP: native MCP config file updated (if supported)
- Skills: native skills directory (if supported)

| Identifier | Agent | Rules | MCP | Skills |
| ------------- | ----------------- | -------------------------------------------------------- | ------------------------------ | ----------------- |
| `agentsmd` | AgentsMd (pseudo) | `AGENTS.md` | - | - |
| `copilot` | GitHub Copilot | `AGENTS.md` | `.vscode/mcp.json` (`servers`) | `.claude/skills` |
| `claude` | Claude Code | `CLAUDE.md` (`@file` refs) | `.mcp.json` | `.claude/skills` |
| `codex` | OpenAI Codex CLI | `AGENTS.md`, `.codex/config.toml` | `.codex/config.toml` | `.codex/skills` |
| `cursor` | Cursor | `AGENTS.md` | `.cursor/mcp.json` | `.cursor/skills` |
| `windsurf` | Windsurf | `AGENTS.md` | `.windsurf/mcp_config.json` | - |
| `cline` | Cline | `.clinerules` | - | - |
| `aider` | Aider | `AGENTS.md`, `.aider.conf.yml` | `.mcp.json` | - |
| `firebase` | Firebase Studio | `.idx/airules.md` | `.idx/mcp.json` | - |
| `openhands` | Open Hands | `.openhands/microagents/repo.md` | `config.toml` | - |
| `gemini-cli` | Gemini CLI | `AGENTS.md`, `.gemini/settings.json` | `.gemini/settings.json` | `.gemini/skills` |
| `jules` | Jules | `AGENTS.md` | - | - |
| `junie` | Junie | `.junie/guidelines.md` | - | - |
| `augmentcode` | AugmentCode | `.augment/rules/skiller_augment_instructions.md` | - | - |
| `kilocode` | Kilo Code | `.kilocode/rules/skiller_kilocode_instructions.md` | `.kilocode/mcp.json` | `.claude/skills` |
| `opencode` | OpenCode | `AGENTS.md`, `opencode.json` | `opencode.json` | `.opencode/skill` |
| `goose` | Goose | `.goosehints` | - | `.agents/skills` |
| `crush` | Crush | `CRUSH.md`, `.crush.json` | `.crush.json` | - |
| `amp` | Amp | `AGENTS.md` | - | `.agents/skills` |
| `zed` | Zed | `AGENTS.md`, `.zed/settings.json` | `.zed/settings.json` | - |
| `qwen` | Qwen Code | `AGENTS.md`, `.qwen/settings.json` | `.qwen/settings.json` | - |
| `kiro` | Kiro | `.kiro/steering/skiller_kiro_instructions.md` | - | - |
| `warp` | Warp | `WARP.md` | - | - |
| `roo` | RooCode | `AGENTS.md`, `.roo/mcp.json` | `.roo/mcp.json` | `.roo/skills` |
| `trae` | Trae AI | `.trae/rules/project_rules.md` | - | - |
| `amazonqcli` | Amazon Q CLI | `.amazonq/rules/skiller_q_rules.md`, `.amazonq/mcp.json` | `.amazonq/mcp.json` | - |
| `firebender` | Firebender | `firebender.json` | `firebender.json` | - |

Notes:

- Some agents handle MCP inside their adapter (Codex CLI, Gemini CLI, OpenCode, Crush, Zed, RooCode, Firebender, Amazon Q CLI)
- Some agents use `AGENTS.md` but do not have native MCP or skills support
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ topic: skills-as-source-of-truth
Refactor skiller to make `.claude/skills/` the committed source of truth, eliminating the intermediate `.claude/rules/` → skills generation pipeline.

**New structure:**

```
.claude/skills/
api/
Expand All @@ -18,6 +19,7 @@ Refactor skiller to make `.claude/skills/` the committed source of truth, elimin
```

**Key changes:**

- `.claude/skills/` is committed (removed from gitignore)
- Drop `generate_from_rules` config option
- Drop `prune` config option
Expand All @@ -27,11 +29,13 @@ Refactor skiller to make `.claude/skills/` the committed source of truth, elimin
## Why This Approach

The current architecture has unnecessary complexity:

1. `.mdc` files in `.claude/rules/` generate skills in `.claude/skills/`
2. Skills are gitignored (regenerated on apply)
3. Skillz MCP provides skills to non-native agents

This creates a confusing indirection. By making `.claude/skills/` the source of truth:

- Users edit `.mdc` files directly in skills folder
- SKILL.md is auto-generated for Claude Code discovery
- No more generation/pruning/orphan detection complexity
Expand All @@ -40,6 +44,7 @@ This creates a confusing indirection. By making `.claude/skills/` the source of
## Key Decisions

### File Structure

- **SKILL.md**: Auto-generated thin wrapper containing:
- Frontmatter: `name`, `description`
- Body: `@.claude/skills/{name}.mdc` reference
Expand All @@ -52,6 +57,7 @@ This creates a confusing indirection. By making `.claude/skills/` the source of
Skiller adds `synced: true` to SKILL.md frontmatter when it syncs.

**Detection logic:**

1. If `SKILL.md` has NO `synced: true` → external install (e.g., from agentskills.io)
- Sync direction: `SKILL.md` → `.mdc`
- Extract body to sibling `.mdc`, add `synced: true` to SKILL.md
Expand All @@ -60,22 +66,26 @@ Skiller adds `synced: true` to SKILL.md frontmatter when it syncs.
- Regenerate SKILL.md from `.mdc` content

This handles:

- Fresh installs from skill registries (SKILL.md has body content, no marker)
- Reinstalls of the same skill (marker present, use local .mdc as source)
- Normal skiller workflow (edit .mdc, apply regenerates SKILL.md)

### Migration

- If `.claude/rules/` exists on apply:
1. Migrate each `.mdc` file to `.claude/skills/{name}/SKILL.md` + sibling `.mdc`
2. Delete `.claude/rules/` folder after successful migration

### Removed Features

- `generate_from_rules` config option (always migrate if rules exist)
- `prune` config option (no orphan concept anymore)
- Skillz MCP server support (full code removal)
- `.skillz/` directory handling

### Gitignore Changes

- Remove `.claude/skills/` from auto-added gitignore entries
- Keep `.skillz/` removal (won't exist anymore)

Expand Down
49 changes: 49 additions & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# CLI

Skiller is a Node CLI (Node >= 18).

## Install / run

- One-off: `npx skiller@latest apply`
- Global: `npm i -g skiller` then `skiller apply`

## `skiller init`

Scaffolds a `.claude/` folder.

- Creates `.claude/AGENTS.md`
- Creates `.claude/skiller.toml`
- `skiller init --global` writes to `$XDG_CONFIG_HOME/skiller` (default `~/.config/skiller`)

## `skiller apply`

Reads rules, selects agents, writes agent-specific files, then optionally syncs MCP, skills, and `.gitignore`.

Flags:

- `--project-root <path>`: project root (default: cwd)
- `--agents <csv>`: identifiers or name substrings (case-insensitive)
- `--config <path>`: TOML config path (default: `.claude/skiller.toml` or global)
- `--mcp` / `--no-mcp`: enable/disable MCP propagation (default: enabled)
- `--mcp-overwrite`: overwrite native MCP config instead of merging
- `--gitignore` / `--no-gitignore`: enable/disable `.gitignore` updates (default: enabled)
- `--backup` / `--no-backup`: enable/disable `.bak` backups (default: enabled)
- `--skills` / `--no-skills`: enable/disable skills (default: enabled)
- `--nested` / `--no-nested`: enable nested `.claude/` discovery (default: from TOML, otherwise off)
- `--local-only`: ignore global config
- `--dry-run`: show what would change, write nothing
- `--verbose` / `-v`: more logs

## `skiller revert`

Restores files from `.bak` when present, otherwise removes generated files.

Flags:

- `--project-root <path>`: project root (default: cwd)
- `--agents <csv>`: revert only some agents
- `--config <path>`: TOML config path
- `--keep-backups`: keep `.bak` after restoring
- `--local-only`: ignore global config
- `--dry-run`: show what would change, write nothing
- `--verbose` / `-v`: more logs
54 changes: 54 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Configuration (`skiller.toml`)

Skiller looks for `.claude/skiller.toml` by walking up from `--project-root`.

- If no local `.claude/skiller.toml` is found, it falls back to `$XDG_CONFIG_HOME/skiller/skiller.toml`.
- If `.claude/` exists but has no `skiller.toml`, Skiller keeps walking.

## Agent selection precedence

- `skiller apply --agents ...`
- `default_agents = [...]`
- `[agents.<id>].enabled = false` disables an agent
- Otherwise: all agents are enabled

## Rule discovery and ordering

Skiller reads `.md` and `.mdc` under `.claude/` recursively.

- Primary file: `.claude/AGENTS.md` if present
- Legacy fallback: `.claude/instructions.md` if `AGENTS.md` is missing
- Repository root `AGENTS.md` (outside `.claude/`) is prepended if it exists and does not look like a Skiller-generated blob
- Remaining files are appended in sorted path order

Filtering:

- `[rules].include` only keeps matching files
- `[rules].exclude` drops matches (wins over `include`)
- Bare directory patterns expand to `dir/**/*.{md,mdc}`

Cursor merge strategy:

- `rules.merge_strategy = "cursor"` keeps `AGENTS.md` plus Cursor-style `.mdc` rules under `rules/` and `skills/` with `alwaysApply: true`

## Schema

High level (see `docs/mcp.md` for MCP details):

- `default_agents = ["claude", "codex"]`
- `nested = true|false`
- `[rules] include = [...], exclude = [...], merge_strategy = "all"|"cursor"`
- `[backup] enabled = true|false`
- `[gitignore] enabled = true|false`
- `[skills] enabled = true|false`
- `[mcp] enabled = true|false, merge_strategy = "merge"|"overwrite"`
- `[mcp_servers.<name>]` server definitions
- `[agents.<id>] enabled, output_path, output_path_instructions, output_path_config, gitignore`
- `[agents.<id>.mcp] enabled, merge_strategy`

## MCP servers: TOML vs JSON

- Preferred: `skiller.toml` `[mcp_servers.*]`
- Legacy: `.claude/mcp.json` is still read, but deprecated
- Merge rule: TOML wins by server name
- `${VAR}` is expanded inside `mcp_servers.<name>.env` values
17 changes: 17 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Development

## Setup

- `pnpm install`

## Commands

- `pnpm test`
- `pnpm lint`
- `pnpm build`
- `pnpm format`

## Repo conventions

- Use feature branches
- When committing as the assistant, use `git commit --author="AI <skiller+ai@okigu.com>"`
56 changes: 56 additions & 0 deletions docs/mcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# MCP (Model Context Protocol)

Skiller can propagate MCP server configs to agents that support it.

## Define MCP servers

Preferred: `skiller.toml`.

```toml
[mcp]
enabled = true
merge_strategy = "merge" # or "overwrite"

[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "."]

[mcp_servers.remote_api]
url = "https://api.example.com/mcp"

[mcp_servers.remote_api.headers]
Authorization = "Bearer ${TOKEN}"
```

Legacy: `.claude/mcp.json` is still read, but deprecated.

## Filtering + transforms

Skiller filters servers per agent capability:

- Agents that support remote servers get `url` servers as-is
- Agents that only support stdio get remote servers transformed into stdio via `mcp-remote@latest`

Agent-specific transforms:

- Claude Code: `type = "remote"` is rewritten to `http` or `sse` based on the URL
- Kilo Code: `type = "remote"` is rewritten to `streamable-http`
- Firebase Studio: `type` fields are stripped before writing `.idx/mcp.json`

## Merge vs overwrite

- `merge` (default): shallow merge by server name
- `overwrite`: replace the whole server block for that agent

You can override per agent:

```toml
[agents.cursor.mcp]
enabled = true
merge_strategy = "overwrite"
```

## Where MCP is written

- External propagation writes to the agent's native MCP file (see `docs/agents.md`)
- Some agents manage MCP in their own config format inside the adapter (also listed in `docs/agents.md`)
10 changes: 10 additions & 0 deletions docs/migration-from-ruler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Coming from `ruler`

Skiller is a fork of `intellectronica/ruler`.

What changed:

- Root folder is `.claude/` (not `.ruler/`)
- Claude Code gets `CLAUDE.md` as `@file` references, not a concatenated blob
- Skills are first-class: `.claude/skills/` is the committed source of truth
- Claude plugins, commands, and agents can be synced into other agents' skills dirs on `skiller apply`
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ date: 2026-01-28
## Overview

Two changes:

1. Replace `synced: true` frontmatter flag with content-based detection - if body is just `@reference`, the referenced file is source of truth
2. Move `.mdc` files from `.claude/skills/name.mdc` to `.claude/skills/name/name.mdc` (sibling to SKILL.md)

Expand All @@ -17,6 +18,7 @@ This restores compatibility with the pre-0.7 pattern and creates a cleaner file
## Problem Statement

Current approach:

- Uses `synced: true` in frontmatter - extra metadata that can get out of sync
- Places `.mdc` at skills root (`.claude/skills/name.mdc`) - scattered files

Expand Down Expand Up @@ -46,12 +48,15 @@ Current approach:
/**
* Check if SKILL.md body is just a reference (single line starting with @).
*/
function isReferenceBody(body: string): { isReference: boolean; referencePath?: string } {
const lines = body.split('\n').filter(line => line.trim().length > 0);
function isReferenceBody(body: string): {
isReference: boolean;
referencePath?: string;
} {
const lines = body.split('\n').filter((line) => line.trim().length > 0);
if (lines.length === 1 && lines[0].trim().startsWith('@')) {
return {
isReference: true,
referencePath: lines[0].trim().slice(1) // Remove @ prefix
referencePath: lines[0].trim().slice(1), // Remove @ prefix
};
}
return { isReference: false };
Expand Down Expand Up @@ -117,7 +122,7 @@ description: My skill description
---

# My Skill Content
`
`,
);

// Create SKILL.md with @reference (pre-0.7 pattern)
Expand All @@ -129,7 +134,7 @@ description: My skill description
---

@.claude/rules/my-skill.mdc
`
`,
);

const result = await syncMdcToSkillMd(skillsDir, false, false);
Expand All @@ -156,7 +161,7 @@ description: My skill
---

# Skill Content
`
`,
);

const result = await syncMdcToSkillMd(skillsDir, false, false);
Expand All @@ -166,7 +171,7 @@ description: My skill
// Verify SKILL.md was created with @reference
const skillMd = await fs.readFile(
path.join(skillFolder, SKILL_MD_FILENAME),
'utf8'
'utf8',
);
expect(skillMd).toContain('@./my-skill.mdc');
});
Expand Down
Loading
Loading