dryai 0.2.1

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/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # Share AI config CLI
2
+
3
+ Installs command, rule, and skill sources from `~/.config/agents` by default into Copilot and Cursor targets.
4
+
5
+ Pass `--input <path>` to read configs from a different root such as `./config`.
6
+
7
+ Pass `--output <path>` to write generated output somewhere other than your home directory.
8
+
9
+ `--test` is a shortcut for `--output ./output-test`, and if both are provided, `--output` wins.
10
+
11
+ ## Input
12
+
13
+ Input config files live under the selected input root:
14
+
15
+ - `commands`
16
+ - `rules`
17
+ - `skills`
18
+
19
+ Live output is written to:
20
+
21
+ - `~/.copilot/prompts`
22
+ - `~/.copilot/instructions`
23
+ - `~/.copilot/skills`
24
+ - `~/.cursor/rules`
25
+ - `~/.cursor/skills`
26
+
27
+ ## Commands
28
+
29
+ ```sh
30
+ dryai install
31
+ dryai skills list List local skills
32
+ dryai skills add [options] <repo> Add managed skills from a remote repository
33
+ dryai skills remove <name> Remove a managed skill
34
+ dryai skills update <name> Update a managed skill from its tracked source
35
+ dryai skills update-all Update all managed skills from their tracked sources
36
+ ```
37
+
38
+ `<repo>` may be a full git remote URL or a GitHub `owner/repo` shorthand such as `anthropics/skills`.
39
+
40
+ ## Managed Skills
41
+
42
+ Imported skills are copied into `config/skills/<name>/` and tracked in `skills.lock.json`.
43
+
44
+ `skills add` requires at least one `--skill <name>` value. Each requested skill is always resolved from `<repo root>/skills/<name>`.
45
+
46
+ Use `--as <name>` to choose a different local managed skill name when importing exactly one skill.
47
+
48
+ Examples:
49
+
50
+ ```sh
51
+ dryai skills add anthropics/skills --skill skill-creator
52
+ dryai skills add vercel-labs/agent-skills --skill pr-review commit
53
+ dryai skills add https://github.com/vercel-labs/agent-skills.git --skill pr-review commit
54
+ ```
55
+
56
+ By default, imports track the requested ref. With no `--ref`, that means the remote default branch `HEAD` is tracked. Use `--pin` to store the currently resolved commit instead, so later `skills update` operations stay pinned to that commit.
57
+
58
+ The lockfile records:
59
+
60
+ - the local skill name
61
+ - the source repository
62
+ - the source path within that repository
63
+ - the requested git ref, when one was provided
64
+ - the resolved commit that was imported
65
+
66
+ `skills update` and `skills update-all` re-fetch the tracked repository snapshot and replace the local copied skill directory.
67
+
68
+ `skills remove` deletes the local copied skill directory and removes its lockfile entry.
69
+
70
+ `skills list` reports local skill directories, annotating managed entries from the lockfile and flagging managed entries whose local directory is missing.
71
+
72
+ ## Development
73
+
74
+ For development, use `pnpm dev` to rebuild into `dest/` on change and `pnpm dev:dryai --test install` to run the built CLI.
75
+
76
+ Run `pnpm run setup:editor` after installing dependencies if you want the Effect language service workspace patch applied locally.
77
+
78
+ ```sh
79
+ pnpm run setup:editor
80
+ pnpm run build
81
+ pnpm run dev
82
+ pnpm run test
83
+ pnpm run test:watch
84
+
85
+ pnpm dev:dryai install
86
+ pnpm dev:dryai --test install
87
+ pnpm dev:dryai --output ./tmp/install-root install
88
+ pnpm dev:dryai --input ./config install
89
+ ```
90
+
91
+ ## CI and Release
92
+
93
+ - On pull request open or update
94
+ - Run CI validation with build, test, and `npm pack --dry-run`.
95
+ - On changes landing on `main`
96
+ - Run the same CI validation with build, test, and `npm pack --dry-run`.
97
+ - On `v*` tag pushed to `main`
98
+ - Verify the tag matches the checked-in `package.json` version.
99
+ - Verify the tagged commit is on `main`.
100
+ - Build and test the CLI.
101
+ - Create a tarball with `npm pack`.
102
+ - Publish the package to npm using the repository `NPM_TOKEN` secret.
103
+ - Create or update the matching GitHub Release.
104
+ - Upload the tarball as a release asset.
105
+
106
+ Example release flow:
107
+
108
+ ```sh
109
+ git tag v0.1.0
110
+ git push origin v0.1.0
111
+ ```
112
+
113
+ Install from the release tarball with:
114
+
115
+ ```sh
116
+ npm install -g https://github.com/willmruzek/share-ai-config/releases/download/v0.1.0/share-ai-config-0.1.0.tgz
117
+ ```
@@ -0,0 +1,3 @@
1
+ import type { AgentsContext } from '../lib/context.js';
2
+ export declare function runInstallCommand(context: AgentsContext): Promise<void>;
3
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { installToTargets } from '../lib/install.js';
2
+ export async function runInstallCommand(context) {
3
+ await installToTargets(context, { targetRoots: context.targetRoots });
4
+ }
@@ -0,0 +1,12 @@
1
+ import type { AgentsContext } from '../../lib/context.js';
2
+ /**
3
+ * Imports one or more managed skills from a remote repository `skills/` directory into the local skills directory.
4
+ */
5
+ export declare function runSkillsAddCommand(context: AgentsContext, input: {
6
+ repo: string;
7
+ skillNames: string[];
8
+ asName: string | undefined;
9
+ pin: boolean;
10
+ ref: string | undefined;
11
+ }): Promise<void>;
12
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1,99 @@
1
+ import fs from 'fs-extra';
2
+ import { cloneRemoteRepo, createImportedSkillRecord, ensureSkillsLockfile, ensureSkillsRoot, findManagedSkill, formatManagedSkillSummary, getManagedSkillDirectory, loadSkillsLockfile, normalizeRemoteRepo, replaceManagedSkillDirectory, resolveManagedSkillImportPath, resolveSkillSourceDir, saveSkillsLockfile, timestampNow, upsertManagedSkill, } from '../../lib/skills.js';
3
+ /**
4
+ * Normalizes and de-duplicates requested skill names while preserving their input order.
5
+ */
6
+ function normalizeRequestedSkillNames(skillNames) {
7
+ const uniqueSkillNames = [];
8
+ const seenSkillNames = new Set();
9
+ for (const rawSkillName of skillNames) {
10
+ const normalizedSkillPath = resolveManagedSkillImportPath({
11
+ skillName: rawSkillName,
12
+ });
13
+ const skillName = normalizedSkillPath.slice('skills/'.length);
14
+ if (seenSkillNames.has(skillName)) {
15
+ continue;
16
+ }
17
+ seenSkillNames.add(skillName);
18
+ uniqueSkillNames.push(skillName);
19
+ }
20
+ return uniqueSkillNames;
21
+ }
22
+ /**
23
+ * Imports one or more managed skills from a remote repository `skills/` directory into the local skills directory.
24
+ */
25
+ export async function runSkillsAddCommand(context, input) {
26
+ const repo = normalizeRemoteRepo(input.repo);
27
+ if (input.skillNames.length === 0) {
28
+ throw new Error('At least one skill name must be provided with --skill');
29
+ }
30
+ const requestedSkillNames = normalizeRequestedSkillNames(input.skillNames);
31
+ if (requestedSkillNames.length === 0) {
32
+ throw new Error('At least one skill name must be provided with --skill');
33
+ }
34
+ if (input.asName && requestedSkillNames.length !== 1) {
35
+ throw new Error('--as may only be used when importing exactly one skill');
36
+ }
37
+ await ensureSkillsRoot(context);
38
+ await ensureSkillsLockfile(context);
39
+ let lockfile = await loadSkillsLockfile(context);
40
+ const checkout = await cloneRemoteRepo({
41
+ ref: input.ref,
42
+ repo,
43
+ });
44
+ const skippedSkillNames = [];
45
+ const importedSkillSummaries = [];
46
+ try {
47
+ for (const requestedSkillName of requestedSkillNames) {
48
+ const skillName = input.asName ?? requestedSkillName;
49
+ const importedSkillPath = resolveManagedSkillImportPath({
50
+ skillName: requestedSkillName,
51
+ });
52
+ const existingManagedSkill = findManagedSkill(lockfile, {
53
+ name: skillName,
54
+ });
55
+ if (existingManagedSkill) {
56
+ skippedSkillNames.push(skillName);
57
+ continue;
58
+ }
59
+ const targetDir = getManagedSkillDirectory(context, { skillName });
60
+ if (await fs.pathExists(targetDir)) {
61
+ throw new Error(`A local skill directory already exists: ${targetDir}`);
62
+ }
63
+ const sourceDir = await resolveSkillSourceDir({
64
+ checkoutDir: checkout.checkoutDir,
65
+ repo,
66
+ skillName: requestedSkillName,
67
+ });
68
+ await replaceManagedSkillDirectory({
69
+ targetDir,
70
+ sourceDir,
71
+ });
72
+ const importedSkill = createImportedSkillRecord({
73
+ commit: checkout.commit,
74
+ importedAt: timestampNow(),
75
+ name: skillName,
76
+ path: importedSkillPath,
77
+ ref: input.pin ? checkout.commit : input.ref,
78
+ repo,
79
+ });
80
+ lockfile = upsertManagedSkill(lockfile, {
81
+ updatedSkill: importedSkill,
82
+ });
83
+ await saveSkillsLockfile(context, { lockfile });
84
+ importedSkillSummaries.push(formatManagedSkillSummary(importedSkill));
85
+ }
86
+ }
87
+ finally {
88
+ await checkout.cleanup();
89
+ }
90
+ for (const importedSkillSummary of importedSkillSummaries) {
91
+ console.log(`Imported ${importedSkillSummary}`);
92
+ }
93
+ if (skippedSkillNames.length > 0) {
94
+ console.warn(`Skipped already-imported skills: ${skippedSkillNames.join(', ')}`);
95
+ }
96
+ if (importedSkillSummaries.length === 0) {
97
+ console.log('No skills were imported.');
98
+ }
99
+ }
@@ -0,0 +1,11 @@
1
+ import { Command } from 'commander';
2
+ import { type AgentsContext } from '../../lib/context.js';
3
+ /**
4
+ * Registers the managed skills command tree on the parent CLI program.
5
+ */
6
+ export declare function addSkillsCommand(input: {
7
+ parent: Command;
8
+ commandName: string;
9
+ resolveContext: () => AgentsContext;
10
+ }): Command;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,90 @@
1
+ import { Command } from 'commander';
2
+ import dedent from 'dedent';
3
+ import { z } from 'zod';
4
+ import { nonEmptyOptionStringSchema, parseOptionsObject, parseOptionValue, } from '../../lib/command-options.js';
5
+ import {} from '../../lib/context.js';
6
+ import { runSkillsAddCommand } from './add.js';
7
+ import { runSkillsListCommand } from './list.js';
8
+ import { runSkillsRemoveCommand } from './remove.js';
9
+ import { runSkillsUpdateAllCommand } from './update-all.js';
10
+ import { runSkillsUpdateCommand } from './update.js';
11
+ const skillsImportOptionsSchema = z.object({
12
+ skill: z.array(z.string()).optional(),
13
+ as: nonEmptyOptionStringSchema.optional(),
14
+ pin: z.boolean().optional().default(false),
15
+ ref: nonEmptyOptionStringSchema.optional(),
16
+ });
17
+ /**
18
+ * Registers the managed skills command tree on the parent CLI program.
19
+ */
20
+ export function addSkillsCommand(input) {
21
+ const { parent, commandName, resolveContext } = input;
22
+ const skills = parent
23
+ .command('skills')
24
+ .description('Manage imported skills')
25
+ .usage('<subcommand> [args]')
26
+ .helpOption('-h, --help', 'Display this message')
27
+ .helpCommand(false)
28
+ .addHelpText('after', dedent `
29
+ Examples:
30
+ ${commandName} list
31
+ ${commandName} add anthropics/skills --skill skill-creator
32
+ ${commandName} add vercel-labs/agent-skills --skill pr-review commit
33
+ ${commandName} update skill-creator
34
+ `)
35
+ .action(() => {
36
+ skills.outputHelp();
37
+ });
38
+ skills
39
+ .command('list')
40
+ .description('List local skills')
41
+ .action(async () => {
42
+ await runSkillsListCommand(resolveContext());
43
+ });
44
+ skills
45
+ .command('add <repo>')
46
+ .description('Add managed skills from a remote repository')
47
+ .option('--skill <names...>', 'Import one or more skills from the repository root skills/ directory')
48
+ .option('--as <name>', 'Store the imported skill under a different local managed name', parseOptionValue({
49
+ schema: nonEmptyOptionStringSchema,
50
+ optionLabel: '--as',
51
+ }))
52
+ .option('--pin', 'Pin the import to the currently resolved commit instead of tracking a moving ref')
53
+ .option('--ref <gitRef>', 'Fetch a specific git ref instead of the remote default', parseOptionValue({
54
+ schema: nonEmptyOptionStringSchema,
55
+ optionLabel: '--ref',
56
+ }))
57
+ .action(async (repo, options) => {
58
+ const parsedOptions = parseOptionsObject({
59
+ schema: skillsImportOptionsSchema,
60
+ options,
61
+ optionsLabel: 'skills add options',
62
+ });
63
+ await runSkillsAddCommand(resolveContext(), {
64
+ repo,
65
+ skillNames: parsedOptions.skill ?? [],
66
+ asName: parsedOptions.as,
67
+ pin: parsedOptions.pin,
68
+ ref: parsedOptions.ref,
69
+ });
70
+ });
71
+ skills
72
+ .command('remove <name>')
73
+ .description('Remove a managed skill')
74
+ .action(async (skillName) => {
75
+ await runSkillsRemoveCommand(resolveContext(), { skillName });
76
+ });
77
+ skills
78
+ .command('update <name>')
79
+ .description('Update a managed skill from its tracked source')
80
+ .action(async (skillName) => {
81
+ await runSkillsUpdateCommand(resolveContext(), { skillName });
82
+ });
83
+ skills
84
+ .command('update-all')
85
+ .description('Update all managed skills from their tracked sources')
86
+ .action(async () => {
87
+ await runSkillsUpdateAllCommand(resolveContext());
88
+ });
89
+ return skills;
90
+ }
@@ -0,0 +1,6 @@
1
+ import type { AgentsContext } from '../../lib/context.js';
2
+ /**
3
+ * Lists local skills and annotates which ones are managed by the lockfile.
4
+ */
5
+ export declare function runSkillsListCommand(context: AgentsContext): Promise<void>;
6
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1,26 @@
1
+ import { ensureSkillsRoot, findManagedSkill, formatManagedSkillSummary, listLocalSkillDirectories, loadSkillsLockfile, } from '../../lib/skills.js';
2
+ /**
3
+ * Lists local skills and annotates which ones are managed by the lockfile.
4
+ */
5
+ export async function runSkillsListCommand(context) {
6
+ await ensureSkillsRoot(context);
7
+ const [localSkillDirectories, lockfile] = await Promise.all([
8
+ listLocalSkillDirectories(context),
9
+ loadSkillsLockfile(context),
10
+ ]);
11
+ const localSkillLines = localSkillDirectories.map((skillName) => {
12
+ const managedSkill = findManagedSkill(lockfile, { name: skillName });
13
+ return managedSkill
14
+ ? `- ${formatManagedSkillSummary(managedSkill)}`
15
+ : `- ${skillName} unmanaged`;
16
+ });
17
+ const missingManagedLines = lockfile.skills
18
+ .filter((managedSkill) => !localSkillDirectories.includes(managedSkill.name))
19
+ .map((managedSkill) => `- ${formatManagedSkillSummary(managedSkill)} missing-local-directory`);
20
+ const outputLines = [...localSkillLines, ...missingManagedLines];
21
+ if (outputLines.length === 0) {
22
+ console.log('No local skills found.');
23
+ return;
24
+ }
25
+ console.log(outputLines.join('\n'));
26
+ }
@@ -0,0 +1,8 @@
1
+ import type { AgentsContext } from '../../lib/context.js';
2
+ /**
3
+ * Removes a managed skill from the local directory and updates the lockfile.
4
+ */
5
+ export declare function runSkillsRemoveCommand(context: AgentsContext, input: {
6
+ skillName: string;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=remove.d.ts.map
@@ -0,0 +1,17 @@
1
+ import { findManagedSkill, formatManagedSkillSummary, loadSkillsLockfile, removeManagedSkill, removeManagedSkillDirectory, saveSkillsLockfile, } from '../../lib/skills.js';
2
+ /**
3
+ * Removes a managed skill from the local directory and updates the lockfile.
4
+ */
5
+ export async function runSkillsRemoveCommand(context, input) {
6
+ const { skillName } = input;
7
+ const lockfile = await loadSkillsLockfile(context);
8
+ const managedSkill = findManagedSkill(lockfile, { name: skillName });
9
+ if (!managedSkill) {
10
+ throw new Error(`Managed skill not found: ${skillName}`);
11
+ }
12
+ await removeManagedSkillDirectory(context, { skillName });
13
+ await saveSkillsLockfile(context, {
14
+ lockfile: removeManagedSkill(lockfile, { name: skillName }),
15
+ });
16
+ console.log(`Removed ${formatManagedSkillSummary(managedSkill)}`);
17
+ }
@@ -0,0 +1,6 @@
1
+ import type { AgentsContext } from '../../lib/context.js';
2
+ /**
3
+ * Updates every managed skill from its tracked remote source and saves the refreshed lockfile.
4
+ */
5
+ export declare function runSkillsUpdateAllCommand(context: AgentsContext): Promise<void>;
6
+ //# sourceMappingURL=update-all.d.ts.map
@@ -0,0 +1,39 @@
1
+ import { createUpdatedSkillRecord, fetchRemoteSkillSnapshot, formatManagedSkillSummary, getManagedSkillDirectory, loadSkillsLockfile, replaceManagedSkillDirectory, saveSkillsLockfile, timestampNow, upsertManagedSkill, } from '../../lib/skills.js';
2
+ /**
3
+ * Updates every managed skill from its tracked remote source and saves the refreshed lockfile.
4
+ */
5
+ export async function runSkillsUpdateAllCommand(context) {
6
+ let lockfile = await loadSkillsLockfile(context);
7
+ if (lockfile.skills.length === 0) {
8
+ console.log('No managed skills to update.');
9
+ return;
10
+ }
11
+ const updatedLines = [];
12
+ for (const managedSkill of lockfile.skills) {
13
+ const snapshot = await fetchRemoteSkillSnapshot({
14
+ ref: managedSkill.ref,
15
+ repo: managedSkill.repo,
16
+ skillPath: managedSkill.path,
17
+ });
18
+ try {
19
+ await replaceManagedSkillDirectory({
20
+ targetDir: getManagedSkillDirectory(context, {
21
+ skillName: managedSkill.name,
22
+ }),
23
+ sourceDir: snapshot.sourceDir,
24
+ });
25
+ }
26
+ finally {
27
+ await snapshot.cleanup();
28
+ }
29
+ const updatedSkill = createUpdatedSkillRecord({
30
+ commit: snapshot.commit,
31
+ existingSkill: managedSkill,
32
+ updatedAt: timestampNow(),
33
+ });
34
+ lockfile = upsertManagedSkill(lockfile, { updatedSkill });
35
+ updatedLines.push(`- ${formatManagedSkillSummary(updatedSkill)}`);
36
+ }
37
+ await saveSkillsLockfile(context, { lockfile });
38
+ console.log(`Updated ${updatedLines.length} managed skills:\n${updatedLines.join('\n')}`);
39
+ }
@@ -0,0 +1,8 @@
1
+ import type { AgentsContext } from '../../lib/context.js';
2
+ /**
3
+ * Updates one managed skill from its tracked remote source and refreshes the lockfile.
4
+ */
5
+ export declare function runSkillsUpdateCommand(context: AgentsContext, input: {
6
+ skillName: string;
7
+ }): Promise<void>;
8
+ //# sourceMappingURL=update.d.ts.map
@@ -0,0 +1,35 @@
1
+ import { createUpdatedSkillRecord, fetchRemoteSkillSnapshot, findManagedSkill, formatManagedSkillSummary, getManagedSkillDirectory, loadSkillsLockfile, replaceManagedSkillDirectory, saveSkillsLockfile, timestampNow, upsertManagedSkill, } from '../../lib/skills.js';
2
+ /**
3
+ * Updates one managed skill from its tracked remote source and refreshes the lockfile.
4
+ */
5
+ export async function runSkillsUpdateCommand(context, input) {
6
+ const { skillName } = input;
7
+ const lockfile = await loadSkillsLockfile(context);
8
+ const managedSkill = findManagedSkill(lockfile, { name: skillName });
9
+ if (!managedSkill) {
10
+ throw new Error(`Managed skill not found: ${skillName}`);
11
+ }
12
+ const snapshot = await fetchRemoteSkillSnapshot({
13
+ ref: managedSkill.ref,
14
+ repo: managedSkill.repo,
15
+ skillPath: managedSkill.path,
16
+ });
17
+ try {
18
+ await replaceManagedSkillDirectory({
19
+ targetDir: getManagedSkillDirectory(context, { skillName }),
20
+ sourceDir: snapshot.sourceDir,
21
+ });
22
+ }
23
+ finally {
24
+ await snapshot.cleanup();
25
+ }
26
+ const updatedSkill = createUpdatedSkillRecord({
27
+ commit: snapshot.commit,
28
+ existingSkill: managedSkill,
29
+ updatedAt: timestampNow(),
30
+ });
31
+ await saveSkillsLockfile(context, {
32
+ lockfile: upsertManagedSkill(lockfile, { updatedSkill }),
33
+ });
34
+ console.log(`Updated ${formatManagedSkillSummary(updatedSkill)}`);
35
+ }
@@ -0,0 +1,18 @@
1
+ import { z } from 'zod';
2
+ export declare const nonEmptyOptionStringSchema: z.ZodString;
3
+ /**
4
+ * Parses one Commander option value with a Zod schema.
5
+ */
6
+ export declare function parseOptionValue<TSchema extends z.ZodTypeAny>({ schema, optionLabel, }: {
7
+ schema: TSchema;
8
+ optionLabel: string;
9
+ }): (value: z.input<TSchema>) => z.output<TSchema>;
10
+ /**
11
+ * Parses a Commander options object with a Zod schema.
12
+ */
13
+ export declare function parseOptionsObject<TSchema extends z.ZodTypeAny>({ schema, options, optionsLabel, }: {
14
+ schema: TSchema;
15
+ options: unknown;
16
+ optionsLabel: string;
17
+ }): z.output<TSchema>;
18
+ //# sourceMappingURL=command-options.d.ts.map
@@ -0,0 +1,31 @@
1
+ import { InvalidArgumentError } from 'commander';
2
+ import { z } from 'zod';
3
+ export const nonEmptyOptionStringSchema = z.string().trim().min(1);
4
+ /**
5
+ * Parses a value with a Zod schema, throwing a Commander InvalidArgumentError on failure.
6
+ */
7
+ function parseWithSchema({ schema, value, label, }) {
8
+ const result = schema.safeParse(value);
9
+ if (result.success) {
10
+ return result.data;
11
+ }
12
+ const issues = result.error.issues
13
+ .map((issue) => {
14
+ const issuePath = issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';
15
+ return `${issuePath}${issue.message}`;
16
+ })
17
+ .join('; ');
18
+ throw new InvalidArgumentError(`${label}: ${issues}`);
19
+ }
20
+ /**
21
+ * Parses one Commander option value with a Zod schema.
22
+ */
23
+ export function parseOptionValue({ schema, optionLabel, }) {
24
+ return (value) => parseWithSchema({ schema, value, label: optionLabel });
25
+ }
26
+ /**
27
+ * Parses a Commander options object with a Zod schema.
28
+ */
29
+ export function parseOptionsObject({ schema, options, optionsLabel, }) {
30
+ return parseWithSchema({ schema, value: options, label: optionsLabel });
31
+ }
@@ -0,0 +1,73 @@
1
+ export type TargetRoots = {
2
+ copilotPrompts: string;
3
+ copilotInstructions: string;
4
+ copilotSkills: string;
5
+ cursorRules: string;
6
+ cursorSkills: string;
7
+ };
8
+ export type SourceRoots = {
9
+ commands: string;
10
+ rules: string;
11
+ skills: string;
12
+ };
13
+ export type AgentsContext = {
14
+ inputRoot: string;
15
+ outputRoot: string;
16
+ skillsLockfilePath: string;
17
+ sourceRoots: SourceRoots;
18
+ targetRoots: TargetRoots;
19
+ };
20
+ export declare const DEFAULT_INPUT_ROOT_SEGMENTS: readonly [".config", "agents"];
21
+ export declare const DEFAULT_TEST_OUTPUT_DIR_NAME = "output-test";
22
+ export declare const DEFAULT_SOURCE_ROOT_NAMES: {
23
+ readonly commands: "commands";
24
+ readonly rules: "rules";
25
+ readonly skills: "skills";
26
+ };
27
+ export declare const DEFAULT_TARGET_ROOT_SEGMENTS: {
28
+ readonly copilotPrompts: readonly [".copilot", "prompts"];
29
+ readonly copilotInstructions: readonly [".copilot", "instructions"];
30
+ readonly copilotSkills: readonly [".copilot", "skills"];
31
+ readonly cursorRules: readonly [".cursor", "rules"];
32
+ readonly cursorSkills: readonly [".cursor", "skills"];
33
+ };
34
+ /**
35
+ * Creates the Copilot and Cursor output root paths under one base directory.
36
+ */
37
+ export declare function createTargetRoots(baseDir: string): TargetRoots;
38
+ /**
39
+ * Creates the commands, rules, and skills input roots under one base directory.
40
+ */
41
+ export declare function createSourceRoots(baseDir: string): SourceRoots;
42
+ /**
43
+ * Expands a leading `~` in a path to the current user's home directory.
44
+ */
45
+ export declare function expandHomePath(inputPath: string, homeDir: string): string;
46
+ /**
47
+ * Returns the requested output-root override derived from CLI-style options.
48
+ */
49
+ export declare function resolveRequestedOutputRoot(input: {
50
+ test: boolean;
51
+ outputRoot?: string;
52
+ }): string | undefined;
53
+ /**
54
+ * Returns the filesystem path to use for generated output.
55
+ */
56
+ export declare function resolveOutputRoot(input: {
57
+ homeDir: string;
58
+ outputRoot?: string;
59
+ }): string;
60
+ /**
61
+ * Returns a copy of the context with generated output redirected under one
62
+ * explicit output root.
63
+ */
64
+ export declare function resolveOutputContext(context: AgentsContext, outputRoot: string): AgentsContext;
65
+ /**
66
+ * Creates the base CLI context with repository, input, and output paths
67
+ * resolved.
68
+ */
69
+ export declare function createAgentsContext(options?: {
70
+ inputRoot?: string;
71
+ outputRoot?: string;
72
+ }): AgentsContext;
73
+ //# sourceMappingURL=context.d.ts.map