skiller 0.8.2 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands.js +60 -1
- package/dist/cli/handlers.js +240 -5
- package/dist/cli/skills-cli.js +72 -0
- package/dist/constants.js +2 -1
- package/dist/core/ClaudePluginMigration.js +229 -0
- package/dist/core/ClaudePluginSync.js +1 -34
- package/dist/core/ClaudeProjectSync.js +37 -58
- package/dist/core/ConfigLoader.js +4 -4
- package/dist/core/FileSystemUtils.js +19 -48
- package/dist/core/FrontmatterParser.js +11 -1
- package/dist/core/LegacyClaudePluginState.js +123 -0
- package/dist/core/RulesToSkillsMigration.js +173 -0
- package/dist/core/SkillOwnership.js +397 -0
- package/dist/core/SkillsManifest.js +79 -23
- package/dist/core/SkillsProcessor.js +565 -317
- package/dist/core/SkillsUtils.js +6 -11
- package/dist/core/UnifiedConfigLoader.js +6 -5
- package/dist/core/project-paths.js +8 -0
- package/dist/lib.js +10 -16
- package/package.json +8 -8
package/dist/core/SkillsUtils.js
CHANGED
|
@@ -161,17 +161,12 @@ async function walkSkillsTree(root) {
|
|
|
161
161
|
await walk(entryPath, entryRelativePath, depth + 1);
|
|
162
162
|
}
|
|
163
163
|
else {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
deleted.push(entryRelativePath);
|
|
171
|
-
}
|
|
172
|
-
catch {
|
|
173
|
-
warnings.push(`Failed to delete empty directory '${entryRelativePath}'`);
|
|
174
|
-
}
|
|
164
|
+
try {
|
|
165
|
+
await fs.rm(entryPath, { recursive: true, force: true });
|
|
166
|
+
deleted.push(entryRelativePath);
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
warnings.push(`Failed to delete empty directory '${entryRelativePath}'`);
|
|
175
170
|
}
|
|
176
171
|
}
|
|
177
172
|
}
|
|
@@ -41,6 +41,7 @@ const FileSystemUtils = __importStar(require("./FileSystemUtils"));
|
|
|
41
41
|
const FileSystemUtils_1 = require("./FileSystemUtils");
|
|
42
42
|
const hash_1 = require("./hash");
|
|
43
43
|
const RuleProcessor_1 = require("./RuleProcessor");
|
|
44
|
+
const project_paths_1 = require("./project-paths");
|
|
44
45
|
/**
|
|
45
46
|
* Expand environment variables in a string.
|
|
46
47
|
* Supports ${VAR} syntax, replacing with process.env[VAR] or empty string if not found.
|
|
@@ -55,9 +56,9 @@ function expandEnvRecord(record) {
|
|
|
55
56
|
return Object.fromEntries(Object.entries(record).map(([k, v]) => [k, expandEnvVars(v)]));
|
|
56
57
|
}
|
|
57
58
|
async function loadUnifiedConfig(options) {
|
|
58
|
-
// Resolve the effective .
|
|
59
|
+
// Resolve the effective .agents directory (local or global), mirroring the main loader behavior
|
|
59
60
|
const resolvedSkillerDir = (await FileSystemUtils.findSkillerDir(options.projectRoot, true)) ||
|
|
60
|
-
path.join(options.projectRoot,
|
|
61
|
+
path.join(options.projectRoot, project_paths_1.CANONICAL_SKILLER_DIR);
|
|
61
62
|
const meta = {
|
|
62
63
|
projectRoot: options.projectRoot,
|
|
63
64
|
skillerDir: resolvedSkillerDir,
|
|
@@ -69,7 +70,7 @@ async function loadUnifiedConfig(options) {
|
|
|
69
70
|
let tomlRaw = {};
|
|
70
71
|
const tomlFile = options.configPath
|
|
71
72
|
? path.resolve(options.configPath)
|
|
72
|
-
: path.join(meta.skillerDir,
|
|
73
|
+
: path.join(meta.skillerDir, project_paths_1.SKILLER_CONFIG_FILE);
|
|
73
74
|
try {
|
|
74
75
|
const text = await fs_1.promises.readFile(tomlFile, 'utf8');
|
|
75
76
|
tomlRaw = text.trim() ? (0, toml_1.parse)(text) : {};
|
|
@@ -114,7 +115,7 @@ async function loadUnifiedConfig(options) {
|
|
|
114
115
|
diagnostics.push({
|
|
115
116
|
severity: 'warning',
|
|
116
117
|
code: 'SKILLS_DEPRECATED_OPTION',
|
|
117
|
-
message: 'skills.generate_from_rules is deprecated and has no effect.
|
|
118
|
+
message: 'skills.generate_from_rules is deprecated and has no effect. Local rule sources in .agents/rules/ compile automatically into .agents/skills/.',
|
|
118
119
|
file: tomlFile,
|
|
119
120
|
});
|
|
120
121
|
}
|
|
@@ -122,7 +123,7 @@ async function loadUnifiedConfig(options) {
|
|
|
122
123
|
diagnostics.push({
|
|
123
124
|
severity: 'warning',
|
|
124
125
|
code: 'SKILLS_DEPRECATED_OPTION',
|
|
125
|
-
message: 'skills.prune is deprecated and has no effect. Skills in .
|
|
126
|
+
message: 'skills.prune is deprecated and has no effect. Skills in .agents/skills/ are never auto-deleted.',
|
|
126
127
|
file: tomlFile,
|
|
127
128
|
});
|
|
128
129
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SKILLER_CONFIG_FILE = exports.LEGACY_INSTRUCTIONS_FILE = exports.PROJECT_AGENTS_FILE = exports.LEGACY_SKILLER_DIR = exports.CANONICAL_SKILLER_DIR = void 0;
|
|
4
|
+
exports.CANONICAL_SKILLER_DIR = '.agents';
|
|
5
|
+
exports.LEGACY_SKILLER_DIR = '.claude';
|
|
6
|
+
exports.PROJECT_AGENTS_FILE = 'AGENTS.md';
|
|
7
|
+
exports.LEGACY_INSTRUCTIONS_FILE = 'instructions.md';
|
|
8
|
+
exports.SKILLER_CONFIG_FILE = 'skiller.toml';
|
package/dist/lib.js
CHANGED
|
@@ -42,6 +42,8 @@ const constants_1 = require("./constants");
|
|
|
42
42
|
const agent_selection_1 = require("./core/agent-selection");
|
|
43
43
|
const apply_engine_1 = require("./core/apply-engine");
|
|
44
44
|
const config_utils_1 = require("./core/config-utils");
|
|
45
|
+
const SkillOwnership_1 = require("./core/SkillOwnership");
|
|
46
|
+
const LegacyClaudePluginState_1 = require("./core/LegacyClaudePluginState");
|
|
45
47
|
const agents = agents_1.allAgents;
|
|
46
48
|
/**
|
|
47
49
|
* Resolves skills enabled state based on precedence: CLI flag > skiller.toml > default (enabled)
|
|
@@ -74,6 +76,8 @@ function resolveBackupEnabled(cliFlag, configSetting) {
|
|
|
74
76
|
* @param includedAgents Optional list of agent name filters (case-insensitive substrings)
|
|
75
77
|
*/
|
|
76
78
|
async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cliMcpEnabled = true, cliMcpStrategy, cliGitignoreEnabled, verbose = false, dryRun = false, localOnly = false, nested = false, cliBackupEnabled, skillsEnabled) {
|
|
79
|
+
await (0, LegacyClaudePluginState_1.assertNoLegacyClaudePluginState)(projectRoot);
|
|
80
|
+
await (0, SkillOwnership_1.migrateLegacyProjectState)(projectRoot, dryRun);
|
|
77
81
|
// Load configuration and rules
|
|
78
82
|
(0, constants_1.logVerbose)(`Loading configuration from project root: ${projectRoot}`, verbose);
|
|
79
83
|
if (configPath) {
|
|
@@ -85,7 +89,7 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
|
|
|
85
89
|
if (nested) {
|
|
86
90
|
const hierarchicalConfigs = await (0, apply_engine_1.loadNestedConfigurations)(projectRoot, configPath, localOnly, nested);
|
|
87
91
|
if (hierarchicalConfigs.length === 0) {
|
|
88
|
-
throw new Error('No .
|
|
92
|
+
throw new Error('No .agents directories found');
|
|
89
93
|
}
|
|
90
94
|
(0, constants_1.logWarn)('Nested mode is experimental and may change in future releases.', dryRun);
|
|
91
95
|
// Use the root config for agent selection (all levels share the same agent settings)
|
|
@@ -93,7 +97,7 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
|
|
|
93
97
|
const rootConfig = rootConfigEntry.config;
|
|
94
98
|
loadedConfig = rootConfig;
|
|
95
99
|
rootConfig.cliAgents = includedAgents;
|
|
96
|
-
(0, constants_1.logVerbose)(`Loaded ${hierarchicalConfigs.length} .
|
|
100
|
+
(0, constants_1.logVerbose)(`Loaded ${hierarchicalConfigs.length} .agents directory configurations`, verbose);
|
|
97
101
|
(0, constants_1.logVerbose)(`Root configuration has ${Object.keys(rootConfig.agentConfigs).length} agent configs`, verbose);
|
|
98
102
|
for (const configEntry of hierarchicalConfigs) {
|
|
99
103
|
normalizeAgentConfigs(configEntry.config, agents);
|
|
@@ -102,14 +106,8 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
|
|
|
102
106
|
(0, constants_1.logVerbose)(`Selected ${selectedAgents.length} agents: ${selectedAgents.map((a) => a.getName()).join(', ')}`, verbose);
|
|
103
107
|
// Propagate skills (or cleanup if disabled) - do this for each nested directory
|
|
104
108
|
const skillsEnabledResolved = resolveSkillsEnabled(skillsEnabled, rootConfig.skills?.enabled);
|
|
105
|
-
const { propagateSkills
|
|
106
|
-
//
|
|
107
|
-
if (skillsEnabledResolved) {
|
|
108
|
-
for (const configEntry of hierarchicalConfigs) {
|
|
109
|
-
await migrateRulesToSkills(configEntry.skillerDir, verbose, dryRun);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
// Propagate skills for each nested .claude directory (or cleanup if disabled)
|
|
109
|
+
const { propagateSkills } = await Promise.resolve().then(() => __importStar(require('./core/SkillsProcessor')));
|
|
110
|
+
// Propagate skills for each nested .agents directory (or cleanup if disabled)
|
|
113
111
|
for (const configEntry of hierarchicalConfigs) {
|
|
114
112
|
const nestedRoot = path.dirname(configEntry.skillerDir);
|
|
115
113
|
(0, constants_1.logVerbose)(`Propagating skills for nested directory: ${nestedRoot}`, verbose);
|
|
@@ -124,17 +122,13 @@ async function applyAllAgentConfigs(projectRoot, includedAgents, configPath, cli
|
|
|
124
122
|
loadedConfig = singleConfig.config;
|
|
125
123
|
singleConfig.config.cliAgents = includedAgents;
|
|
126
124
|
(0, constants_1.logVerbose)(`Loaded configuration with ${Object.keys(singleConfig.config.agentConfigs).length} agent configs`, verbose);
|
|
127
|
-
(0, constants_1.logVerbose)(`Found .
|
|
125
|
+
(0, constants_1.logVerbose)(`Found .agents directory with ${singleConfig.concatenatedRules.length} characters of rules`, verbose);
|
|
128
126
|
normalizeAgentConfigs(singleConfig.config, agents);
|
|
129
127
|
selectedAgents = (0, agent_selection_1.resolveSelectedAgents)(singleConfig.config, agents);
|
|
130
128
|
(0, constants_1.logVerbose)(`Selected ${selectedAgents.length} agents: ${selectedAgents.map((a) => a.getName()).join(', ')}`, verbose);
|
|
131
129
|
// Propagate skills (or cleanup if disabled)
|
|
132
130
|
const skillsEnabledResolved = resolveSkillsEnabled(skillsEnabled, singleConfig.config.skills?.enabled);
|
|
133
|
-
const { propagateSkills
|
|
134
|
-
// Migrate content from .claude/rules to .claude/skills (only if rules exists)
|
|
135
|
-
if (skillsEnabledResolved) {
|
|
136
|
-
await migrateRulesToSkills(singleConfig.skillerDir, verbose, dryRun);
|
|
137
|
-
}
|
|
131
|
+
const { propagateSkills } = await Promise.resolve().then(() => __importStar(require('./core/SkillsProcessor')));
|
|
138
132
|
// Always call propagateSkills - it handles cleanup when disabled
|
|
139
133
|
await propagateSkills(projectRoot, selectedAgents, skillsEnabledResolved, verbose, dryRun, singleConfig.skillerDir);
|
|
140
134
|
// Resolve backup setting: CLI > Config > Default (true)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skiller",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Skiller — apply the same rules to all coding agents",
|
|
5
5
|
"main": "dist/lib.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -50,6 +50,13 @@
|
|
|
50
50
|
"bin": {
|
|
51
51
|
"skiller": "dist/cli/index.js"
|
|
52
52
|
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@iarna/toml": "^2.2.5",
|
|
55
|
+
"js-yaml": "^4.1.0",
|
|
56
|
+
"skills": "1.4.6",
|
|
57
|
+
"yargs": "^18.0.0",
|
|
58
|
+
"zod": "^4.1.12"
|
|
59
|
+
},
|
|
53
60
|
"devDependencies": {
|
|
54
61
|
"@changesets/changelog-github": "^0.5.2",
|
|
55
62
|
"@changesets/cli": "2.29.8",
|
|
@@ -66,15 +73,8 @@
|
|
|
66
73
|
"eslint-plugin-prettier": "^5.5.4",
|
|
67
74
|
"jest": "^29.7.0",
|
|
68
75
|
"prettier": "^3.6.2",
|
|
69
|
-
"skills": "1.4.6",
|
|
70
76
|
"ts-jest": "^29.4.5",
|
|
71
77
|
"typescript": "^5.9.3",
|
|
72
78
|
"typescript-eslint": "^8.46.2"
|
|
73
|
-
},
|
|
74
|
-
"dependencies": {
|
|
75
|
-
"@iarna/toml": "^2.2.5",
|
|
76
|
-
"js-yaml": "^4.1.0",
|
|
77
|
-
"yargs": "^18.0.0",
|
|
78
|
-
"zod": "^4.1.12"
|
|
79
79
|
}
|
|
80
80
|
}
|