🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@limrun/cli

Package Overview
Dependencies
Maintainers
4
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@limrun/cli - npm Package Compare versions

Comparing version
0.8.6
to
0.9.0
+47
dist/lib/remote-skills.d.ts
export declare const DEFAULT_SKILLS_OWNER = "limrun-inc";
export declare const DEFAULT_SKILLS_REPO = "skills";
export declare const DEFAULT_SKILLS_REF = "main";
export interface RemoteSkill {
name: string;
description: string;
defaultSelected: boolean;
sourceDir: string;
}
export interface LoadedRemoteSkills {
owner: string;
repo: string;
ref: string;
commit: string;
rootDir: string;
skillsRoot: string;
skills: RemoteSkill[];
cleanup(): void;
}
export interface LoadRemoteSkillsOptions {
owner?: string;
repo?: string;
ref?: string;
cloneImpl?: (owner: string, repo: string, ref: string) => Promise<ClonedSkillsRepo>;
}
export declare class RemoteSkillsError extends Error {
constructor(message: string);
}
export interface ClonedSkillsRepo {
rootDir: string;
commit: string;
}
declare function cleanupSkillsTempDir(rootDir: string): void;
declare function loadSkillsFromCheckout(params: {
owner: string;
repo: string;
ref: string;
commit: string;
rootDir: string;
}): LoadedRemoteSkills;
export declare function loadRemoteSkills(options?: LoadRemoteSkillsOptions): Promise<LoadedRemoteSkills>;
export declare const __remoteSkillsTestUtils: {
cleanupSkillsTempDir: typeof cleanupSkillsTempDir;
loadSkillsFromCheckout: typeof loadSkillsFromCheckout;
};
export {};
//# sourceMappingURL=remote-skills.d.ts.map
{"version":3,"file":"remote-skills.d.ts","sourceRoot":"","sources":["../../src/lib/remote-skills.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,oBAAoB,eAAe,CAAC;AACjD,eAAO,MAAM,mBAAmB,WAAW,CAAC;AAC5C,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAkBzC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACrF;AAED,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAoBD,iBAAS,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAOnD;AA0ID,iBAAS,sBAAsB,CAAC,MAAM,EAAE;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG,kBAAkB,CA+CrB;AAED,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkBzG;AAED,eAAO,MAAM,uBAAuB;;;CAGnC,CAAC"}
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.__remoteSkillsTestUtils = exports.RemoteSkillsError = exports.DEFAULT_SKILLS_REF = exports.DEFAULT_SKILLS_REPO = exports.DEFAULT_SKILLS_OWNER = void 0;
exports.loadRemoteSkills = loadRemoteSkills;
const fs_1 = __importDefault(require("fs"));
const os_1 = __importDefault(require("os"));
const path_1 = __importDefault(require("path"));
const child_process_1 = require("child_process");
const util_1 = require("util");
const yaml = require('js-yaml');
exports.DEFAULT_SKILLS_OWNER = 'limrun-inc';
exports.DEFAULT_SKILLS_REPO = 'skills';
exports.DEFAULT_SKILLS_REF = 'main';
const DEFAULT_CLONE_TIMEOUT_MS = 300000;
const CLONE_TIMEOUT_MS = (() => {
const raw = process.env['LIM_SKILLS_CLONE_TIMEOUT_MS'];
if (!raw)
return DEFAULT_CLONE_TIMEOUT_MS;
const parsed = Number.parseInt(raw, 10);
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_CLONE_TIMEOUT_MS;
})();
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
class RemoteSkillsError extends Error {
constructor(message) {
super(message);
this.name = 'RemoteSkillsError';
}
}
exports.RemoteSkillsError = RemoteSkillsError;
function assertString(value, label) {
if (typeof value !== 'string' || value.trim() === '') {
throw new RemoteSkillsError(`${label} must be a non-empty string`);
}
}
function isPathInside(basePath, targetPath) {
const normalizedBase = path_1.default.normalize(path_1.default.resolve(basePath));
const normalizedTarget = path_1.default.normalize(path_1.default.resolve(targetPath));
return normalizedTarget === normalizedBase || normalizedTarget.startsWith(normalizedBase + path_1.default.sep);
}
function assertSafeSkillName(value, label) {
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(value)) {
throw new RemoteSkillsError(`${label} must be a lowercase hyphenated skill name`);
}
}
function cleanupSkillsTempDir(rootDir) {
const tmpRoot = os_1.default.tmpdir();
if (!isPathInside(tmpRoot, rootDir) || path_1.default.resolve(rootDir) === path_1.default.resolve(tmpRoot)) {
throw new RemoteSkillsError(`Refusing to clean up non-temporary skills directory: ${rootDir}`);
}
fs_1.default.rmSync(rootDir, { recursive: true, force: true });
}
function parseCatalog(text) {
let catalog;
try {
catalog = JSON.parse(text);
}
catch (err) {
throw new RemoteSkillsError(`catalog.json is invalid JSON: ${err instanceof Error ? err.message : String(err)}`);
}
if (!catalog || typeof catalog !== 'object' || Array.isArray(catalog)) {
throw new RemoteSkillsError('catalog.json must be an object');
}
const parsed = catalog;
if (parsed.schemaVersion !== 1) {
throw new RemoteSkillsError('catalog.json schemaVersion must be 1');
}
if (!Array.isArray(parsed.skills)) {
throw new RemoteSkillsError('catalog.json skills must be an array');
}
for (const [index, skill] of parsed.skills.entries()) {
if (!skill || typeof skill !== 'object' || Array.isArray(skill)) {
throw new RemoteSkillsError(`catalog.json skills[${index}] must be an object`);
}
assertString(skill.name, `catalog.json skills[${index}].name`);
assertSafeSkillName(skill.name, `catalog.json skills[${index}].name`);
if (typeof skill.defaultSelected !== 'boolean') {
throw new RemoteSkillsError(`catalog.json skills[${index}].defaultSelected must be a boolean`);
}
}
return parsed;
}
function parseSkillFrontmatter(skillName, text) {
const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
if (!match) {
throw new RemoteSkillsError(`skills/${skillName}/SKILL.md is missing YAML frontmatter`);
}
const frontmatterText = match[1];
if (frontmatterText === undefined) {
throw new RemoteSkillsError(`skills/${skillName}/SKILL.md is missing YAML frontmatter`);
}
let frontmatter;
try {
frontmatter = yaml.load(frontmatterText);
}
catch (err) {
throw new RemoteSkillsError(`skills/${skillName}/SKILL.md has invalid YAML frontmatter: ${err instanceof Error ? err.message : String(err)}`);
}
if (!frontmatter || typeof frontmatter !== 'object' || Array.isArray(frontmatter)) {
throw new RemoteSkillsError(`skills/${skillName}/SKILL.md frontmatter must be an object`);
}
const parsed = frontmatter;
assertString(parsed.name, `skills/${skillName}/SKILL.md frontmatter name`);
assertSafeSkillName(parsed.name, `skills/${skillName}/SKILL.md frontmatter name`);
assertString(parsed.description, `skills/${skillName}/SKILL.md frontmatter description`);
if (parsed.name !== skillName) {
throw new RemoteSkillsError(`skills/${skillName}/SKILL.md frontmatter name must match directory name`);
}
return { name: parsed.name, description: parsed.description };
}
function readJsonFile(filePath) {
try {
return fs_1.default.readFileSync(filePath, 'utf8');
}
catch (err) {
throw new RemoteSkillsError(`Failed to read ${path_1.default.basename(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
}
}
async function cloneSkillsRepo(owner, repo, ref) {
const rootDir = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'limrun-skills-'));
const repoUrl = `https://github.com/${owner}/${repo}.git`;
const cloneArgs = [
'-c',
'filter.lfs.required=false',
'-c',
'filter.lfs.smudge=',
'-c',
'filter.lfs.clean=',
'-c',
'filter.lfs.process=',
'clone',
'--depth',
'1',
'--branch',
ref,
repoUrl,
rootDir,
];
const env = {
...process.env,
GIT_TERMINAL_PROMPT: '0',
GIT_LFS_SKIP_SMUDGE: '1',
};
try {
await execFileAsync('git', cloneArgs, { env, timeout: CLONE_TIMEOUT_MS });
const { stdout } = await execFileAsync('git', ['-C', rootDir, 'rev-parse', 'HEAD'], {
env,
timeout: 30000,
});
return { rootDir, commit: stdout.trim() };
}
catch (err) {
cleanupSkillsTempDir(rootDir);
const message = err instanceof Error ? err.message : String(err);
const code = typeof err === 'object' && err && 'code' in err ? String(err.code) : '';
if (code === 'ENOENT') {
throw new RemoteSkillsError('Failed to clone Limrun skills: git executable was not found');
}
if (message.includes('timed out') || message.includes('ETIMEDOUT')) {
throw new RemoteSkillsError(`Failed to clone Limrun skills: clone timed out after ${Math.round(CLONE_TIMEOUT_MS / 1000)}s`);
}
if (message.includes('Authentication failed') ||
message.includes('could not read Username') ||
message.includes('Permission denied') ||
message.includes('Repository not found')) {
throw new RemoteSkillsError(`Failed to clone Limrun skills: authentication failed for ${repoUrl}`);
}
throw new RemoteSkillsError(`Failed to clone Limrun skills: ${message}`);
}
}
function loadSkillsFromCheckout(params) {
const { owner, repo, ref, commit, rootDir } = params;
const skillsRoot = path_1.default.join(rootDir, 'skills');
const catalogPath = path_1.default.join(rootDir, 'catalog.json');
const catalog = parseCatalog(readJsonFile(catalogPath));
const catalogNames = catalog.skills.map((skill) => skill.name);
const duplicateCatalogNames = catalogNames.filter((name, index) => catalogNames.indexOf(name) !== index);
if (duplicateCatalogNames.length > 0) {
throw new RemoteSkillsError(`catalog.json has duplicate skill names: ${[...new Set(duplicateCatalogNames)].join(', ')}`);
}
if (!catalog.skills.some((skill) => skill.defaultSelected)) {
throw new RemoteSkillsError('catalog.json must mark at least one skill as defaultSelected');
}
const skills = catalog.skills.map((catalogSkill) => {
const sourceDir = path_1.default.join(skillsRoot, catalogSkill.name);
if (!isPathInside(skillsRoot, sourceDir)) {
throw new RemoteSkillsError(`catalog.json skill escapes skills directory: ${catalogSkill.name}`);
}
if (!fs_1.default.existsSync(sourceDir) || !fs_1.default.statSync(sourceDir).isDirectory()) {
throw new RemoteSkillsError(`catalog.json entries missing from skills/: ${catalogSkill.name}`);
}
const skillMdPath = path_1.default.join(sourceDir, 'SKILL.md');
if (!fs_1.default.existsSync(skillMdPath)) {
throw new RemoteSkillsError(`Downloaded skill is missing skills/${catalogSkill.name}/SKILL.md`);
}
const frontmatter = parseSkillFrontmatter(catalogSkill.name, fs_1.default.readFileSync(skillMdPath, 'utf8'));
return {
name: frontmatter.name,
description: frontmatter.description,
defaultSelected: catalogSkill.defaultSelected,
sourceDir,
};
});
return {
owner,
repo,
ref,
commit,
rootDir,
skillsRoot,
skills,
cleanup: () => cleanupSkillsTempDir(rootDir),
};
}
async function loadRemoteSkills(options = {}) {
const owner = options.owner ?? exports.DEFAULT_SKILLS_OWNER;
const repo = options.repo ?? exports.DEFAULT_SKILLS_REPO;
const ref = options.ref ?? exports.DEFAULT_SKILLS_REF;
const cloneImpl = options.cloneImpl ?? cloneSkillsRepo;
const cloned = await cloneImpl(owner, repo, ref);
try {
return loadSkillsFromCheckout({
owner,
repo,
ref,
commit: cloned.commit,
rootDir: cloned.rootDir,
});
}
catch (err) {
cleanupSkillsTempDir(cloned.rootDir);
throw err;
}
}
exports.__remoteSkillsTestUtils = {
cleanupSkillsTempDir,
loadSkillsFromCheckout,
};
//# sourceMappingURL=remote-skills.js.map
{"version":3,"file":"remote-skills.js","sourceRoot":"","sources":["../../src/lib/remote-skills.ts"],"names":[],"mappings":"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"}
+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/commands/skills/install.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAsR7C,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,OAAO;IAChD,MAAM,CAAC,OAAO,SAAgD;IAC9D,MAAM,CAAC,WAAW,SAC0K;IAC5L,MAAM,CAAC,QAAQ,WAKb;IACF,MAAM,CAAC,KAAK;;;;;;;MA2BV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;YAWZ,QAAQ;IA8HtB,OAAO,CAAC,UAAU;CAwCnB"}
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../src/commands/skills/install.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAyS7C,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,OAAO;IAChD,MAAM,CAAC,OAAO,SAAgD;IAC9D,MAAM,CAAC,WAAW,SACsN;IACxO,MAAM,CAAC,QAAQ,WAKb;IACF,MAAM,CAAC,KAAK;;;;;;;MA2BV;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;YAWZ,QAAQ;IA6JtB,OAAO,CAAC,UAAU;CA8CnB"}

@@ -11,27 +11,12 @@ "use strict";

const skills_1 = require("../../lib/skills");
const SKILL_CATALOG = [
{
name: 'limrun-ios',
description: 'Build, launch, and control iOS apps with remote Xcode and Simulators',
defaultSelected: true,
},
{
name: 'limrun-detox',
description: 'Run Detox tests on Limrun iOS with remote simulator launch and networking',
defaultSelected: false,
},
];
const SKILL_NAMES = SKILL_CATALOG.map((skill) => skill.name);
const DEFAULT_SKILL_NAMES = SKILL_CATALOG.filter((skill) => skill.defaultSelected).map((skill) => skill.name);
const SKIPPED_REASON_CONFLICT = 'existing content differs; re-run with --force to overwrite';
const remote_skills_1 = require("../../lib/remote-skills");
const SKIPPED_REASON_CONFLICT = 'existing skill directory differs; re-run with --force to overwrite';
const SKIPPED_REASON_BLOCKED = 'blocked: another target requires --force to proceed';
const SKIPPED_REASON_DECLINED = 'user declined overwrite confirmation';
function isSkillName(value) {
return SKILL_NAMES.includes(value);
}
function uniqueSkillNames(values) {
function uniqueSkillNames(values, availableSkills) {
const validNames = availableSkills.map((skill) => skill.name);
const skills = [];
for (const value of values) {
if (!isSkillName(value)) {
throw new Error(`Unknown skill "${value}". Valid skills: ${SKILL_NAMES.join(', ')}`);
if (!validNames.includes(value)) {
throw new Error(`Unknown skill "${value}". Valid skills: ${validNames.join(', ')}`);
}

@@ -44,41 +29,12 @@ if (!skills.includes(value)) {

}
class PromptCancelled extends Error {
constructor() {
super('cancelled');
this.name = 'PromptCancelled';
}
}
function detectAgentsForScope(scope) {
const detected = new Set();
for (const id of skills_1.AGENT_IDS) {
const agent = skills_1.AGENTS[id];
for (const p of agent.detectionPaths(scope)) {
if (fs_1.default.existsSync(p)) {
detected.add(id);
break;
}
}
}
return detected;
}
async function promptAgents(preselected) {
// Loop to enforce "at least one agent" without crashing.
while (true) {
// `prompts` does not expose the multiselect cursor in onState - the state
// event only carries {value, aborted, exited}. Track cursor ourselves by
// listening to keypress events on stdin and mirror prompts' own dispatch
// (see prompts/lib/util/action.js and multiselect.js):
// - up / k : wrap (cursor === 0 ? last : cursor - 1)
// - down / j / tab : wrap (cursor === last ? 0 : cursor + 1)
// - ctrl+a : first
// - ctrl+e : last
// Anything else (page nav, home/end) is rare for a 3-row list and not
// tracked here; the worst case is the same as the previous clamp bug.
let cursor = 0;
const onKeypress = (_str, key) => {
if (!key || !key.name)
function createPromptCursorTracker(itemCount) {
let cursor = 0;
return {
current: () => cursor,
onKeypress: (_str, key) => {
if (!key || !key.name || itemCount === 0)
return;
if (key.meta && key.name !== 'escape')
return;
const last = skills_1.AGENT_IDS.length - 1;
const last = itemCount - 1;
if (key.ctrl) {

@@ -97,97 +53,142 @@ if (key.name === 'a')

}
};
process.stdin.on('keypress', onKeypress);
let response;
try {
response = await (0, prompts_1.default)({
type: 'multiselect',
name: 'agents',
message: 'Which agents do you want to set up?',
instructions: false,
choices: skills_1.AGENT_IDS.map((id) => ({
title: skills_1.AGENTS[id].displayName,
value: id,
selected: preselected.has(id),
})),
hint: 'Space to toggle, Enter to confirm (Enter alone picks the highlighted agent)',
}, {
onCancel: () => {
throw new PromptCancelled();
},
});
},
};
}
function wrapDescription(value, width, indentSize = 2) {
const indent = ' '.repeat(indentSize);
const words = value.replace(/\s+/g, ' ').trim().split(' ').filter(Boolean);
const lines = [];
let line = indent;
for (const word of words) {
if (line === indent) {
line += word;
}
finally {
process.stdin.off('keypress', onKeypress);
else if (line.length + 1 + word.length <= width) {
line += ` ${word}`;
}
let picked = (response.agents ?? []);
// If the user hit Enter without toggling anything, treat the highlighted
// row as their pick. Saves a Space keystroke for the common single-agent case.
if (picked.length === 0 && cursor >= 0 && cursor < skills_1.AGENT_IDS.length) {
picked = [skills_1.AGENT_IDS[cursor]];
else {
lines.push(line);
line = `${indent}${word}`;
}
if (picked.length > 0) {
process.stderr.write(` Selected: ${picked.map((id) => skills_1.AGENTS[id].displayName).join(', ')}\n`);
return picked;
}
if (line !== indent) {
lines.push(line);
}
return lines.join('\n');
}
function installCompactMultiselectDescriptionRenderer() {
// prompts only exposes description text through its default renderer, whose
// wrap indent is too deep for long skill descriptions. Patch just this prompt
// and restore immediately after it completes.
const MultiselectPrompt = require('prompts/lib/elements/multiselect');
const color = require('kleur');
const { figures } = require('prompts/lib/util');
const originalRenderOption = MultiselectPrompt.prototype.renderOption;
MultiselectPrompt.prototype.renderOption = function renderOption(cursor, choice, index, arrowIndicator) {
const prefix = (choice.selected ? color.green(figures.radioOn) : figures.radioOff) + ' ' + arrowIndicator + ' ';
let title;
if (choice.disabled) {
title =
cursor === index ? color.gray().underline(choice.title) : color.strikethrough().gray(choice.title);
}
// Re-prompt with a visible inline warning (should not be reachable now).
process.stderr.write('Select at least one agent.\n');
else {
title = cursor === index ? color.cyan().underline(choice.title) : choice.title;
}
const description = !choice.disabled && cursor === index && choice.description ?
`\n${wrapDescription(choice.description, this.out.columns ?? 100, 4)}`
: '';
return prefix + title + color.gray(description);
};
return () => {
MultiselectPrompt.prototype.renderOption = originalRenderOption;
};
}
class PromptCancelled extends Error {
constructor() {
super('cancelled');
this.name = 'PromptCancelled';
}
}
async function promptSkills() {
while (true) {
let cursor = 0;
const onKeypress = (_str, key) => {
if (!key || !key.name)
return;
if (key.meta && key.name !== 'escape')
return;
const last = SKILL_CATALOG.length - 1;
if (key.ctrl) {
if (key.name === 'a')
cursor = 0;
else if (key.name === 'e')
cursor = last;
return;
function detectAgentsForScope(scope) {
const detected = new Set();
for (const id of skills_1.AGENT_IDS) {
const agent = skills_1.AGENTS[id];
for (const p of agent.detectionPaths(scope)) {
if (fs_1.default.existsSync(p)) {
detected.add(id);
break;
}
if (key.name === 'up' || key.name === 'k') {
cursor = cursor === 0 ? last : cursor - 1;
}
else if (key.name === 'down' || key.name === 'j' || key.name === 'tab') {
cursor = cursor === last ? 0 : cursor + 1;
}
};
process.stdin.on('keypress', onKeypress);
let response;
try {
response = await (0, prompts_1.default)({
type: 'multiselect',
name: 'skills',
message: 'Which Limrun skills do you want to install?',
instructions: false,
choices: SKILL_CATALOG.map((skill) => ({
title: `${skill.name} (${skill.description})`,
value: skill.name,
selected: skill.defaultSelected,
})),
hint: 'Space to toggle, Enter to confirm (Enter alone picks the highlighted skill)',
}, {
onCancel: () => {
throw new PromptCancelled();
},
});
}
finally {
process.stdin.off('keypress', onKeypress);
}
let picked = uniqueSkillNames((response.skills ?? []));
if (picked.length === 0 && cursor >= 0 && cursor < SKILL_CATALOG.length) {
picked = [SKILL_CATALOG[cursor].name];
}
if (picked.length > 0) {
process.stderr.write(` Selected skills: ${picked.join(', ')}\n`);
return picked;
}
process.stderr.write('Select at least one skill.\n');
}
return detected;
}
async function promptAgents(preselected) {
const cursor = createPromptCursorTracker(skills_1.AGENT_IDS.length);
process.stdin.on('keypress', cursor.onKeypress);
let response;
try {
response = await (0, prompts_1.default)({
type: 'multiselect',
name: 'agents',
message: 'Which agents do you want to set up?',
instructions: false,
choices: skills_1.AGENT_IDS.map((id) => ({
title: skills_1.AGENTS[id].displayName,
value: id,
selected: preselected.has(id),
})),
hint: 'Space to toggle, Enter to confirm (Enter alone picks the highlighted agent)',
}, {
onCancel: () => {
throw new PromptCancelled();
},
});
}
finally {
process.stdin.off('keypress', cursor.onKeypress);
}
let picked = (response.agents ?? []);
const highlightedAgent = skills_1.AGENT_IDS[cursor.current()];
if (picked.length === 0 && highlightedAgent) {
picked = [highlightedAgent];
}
process.stderr.write(` Selected: ${picked.map((id) => skills_1.AGENTS[id].displayName).join(', ')}\n`);
return picked;
}
async function promptSkills(availableSkills) {
const cursor = createPromptCursorTracker(availableSkills.length);
let response;
const restoreMultiselectRenderer = installCompactMultiselectDescriptionRenderer();
process.stdin.on('keypress', cursor.onKeypress);
try {
response = await (0, prompts_1.default)({
type: 'multiselect',
name: 'skills',
message: 'Which Limrun skills do you want to install?',
instructions: false,
choices: availableSkills.map((skill) => ({
title: skill.name,
description: skill.description.replace(/\s+/g, ' ').trim(),
value: skill.name,
selected: skill.defaultSelected,
})),
hint: 'Catalog defaults selected. Space toggles, Enter confirms.',
}, {
onCancel: () => {
throw new PromptCancelled();
},
});
}
finally {
restoreMultiselectRenderer();
process.stdin.off('keypress', cursor.onKeypress);
}
let picked = uniqueSkillNames((response.skills ?? []), availableSkills);
const highlightedSkill = availableSkills[cursor.current()];
if (picked.length === 0 && highlightedSkill) {
picked = [highlightedSkill.name];
}
process.stderr.write(` Selected skills: ${picked.join(', ')}\n`);
return picked;
}
async function promptScope() {

@@ -261,120 +262,149 @@ const response = await (0, prompts_1.default)({

let agents;
let skills;
let skills = [];
let scope;
if (flags.agents && flags.agents.length > 0) {
agents = Array.from(new Set(flags.agents));
}
else if (interactive) {
// Pre-check based on project-local presence only. Global installs of
// agents (e.g. ~/.claude on a dev machine) are too weak a signal to
// auto-select them for this specific project's install.
agents = await promptAgents(detectAgentsForScope('project'));
}
else {
this.error('--agents requires at least one of: claude, cursor, codex.', { exit: 2 });
}
if (flags.skills && flags.skills.length > 0) {
skills = uniqueSkillNames(flags.skills);
}
else if (interactive) {
skills = await promptSkills();
}
else {
skills = [...DEFAULT_SKILL_NAMES];
}
if (flags.scope) {
scope = flags.scope;
}
else if (interactive) {
scope = await promptScope();
}
else {
this.error('Specify --agents and --scope in non-interactive mode.', { exit: 2 });
}
const sources = new Map();
for (const skill of skills) {
const source = (0, skills_1.sourceSkillMd)(this.config, skill);
if (!fs_1.default.existsSync(source)) {
this.error(`Bundled skill source missing at ${source}.`, { exit: 1 });
let source;
try {
if (!interactive) {
if (!flags.agents || flags.agents.length === 0) {
this.error(`--agents requires at least one of: ${skills_1.AGENT_IDS.join(', ')}.`, { exit: 2 });
}
if (!flags.scope) {
this.error('Specify --agents and --scope in non-interactive mode.', { exit: 2 });
}
}
sources.set(skill, source);
}
// Phase 1: Plan.
const planned = [];
for (const skill of skills) {
const source = sources.get(skill);
for (const id of agents) {
const agent = skills_1.AGENTS[id];
const target = (0, skills_1.targetSkillMd)(agent, scope, skill);
const { kind } = (0, skills_1.planSkillFileCopy)(source, target);
planned.push({ skill, agent, scope, source, target, kind });
if (interactive) {
process.stderr.write('Fetching latest Limrun skills...\n');
}
}
// Phase 2: Confirm.
const results = [];
const anyConflict = planned.some((t) => t.kind === 'conflict');
if (anyConflict && !flags.force && !interactive) {
// Non-interactive + conflict + no force: all-or-nothing. Skip all targets.
for (const t of planned) {
results.push({
skill: t.skill,
agent: t.agent.id,
scope: t.scope,
path: t.target,
status: 'skipped',
reason: t.kind === 'conflict' ? SKIPPED_REASON_CONFLICT : SKIPPED_REASON_BLOCKED,
source = await (0, remote_skills_1.loadRemoteSkills)();
const availableSkills = source.skills;
if (availableSkills.length === 0) {
this.error(`No Limrun skills found in ${source.owner}/${source.repo}@${source.commit}.`, {
exit: 1,
});
}
if (!flags.json) {
// --quiet still suppresses the human summary, but a hard refusal needs to be visible.
process.stderr.write('Existing skill files would be overwritten. Re-run with --force, or run interactively to confirm per target.\n');
if (flags.skills && flags.skills.length > 0) {
skills = uniqueSkillNames(flags.skills, availableSkills);
}
this.emitOutput(results, flags, skills);
this.exit(1);
}
// Decide final status per target (no writes yet).
const finalDecisions = [];
for (const t of planned) {
if (t.kind === 'install') {
finalDecisions.push({ target: t, status: 'installed' });
else if (interactive) {
skills = await promptSkills(availableSkills);
}
else if (t.kind === 'unchanged') {
finalDecisions.push({ target: t, status: 'unchanged' });
else {
skills = availableSkills.filter((skill) => skill.defaultSelected).map((skill) => skill.name);
}
else if (flags.force) {
finalDecisions.push({ target: t, status: 'updated' });
if (skills.length === 0) {
this.error(`No default Limrun skills found in ${source.owner}/${source.repo}@${source.commit}.`, {
exit: 1,
});
}
if (flags.agents && flags.agents.length > 0) {
agents = Array.from(new Set(flags.agents));
}
else if (interactive) {
// Pre-check based on project-local presence only. Global installs of
// agents (e.g. ~/.claude on a dev machine) are too weak a signal to
// auto-select them for this specific project's install.
agents = await promptAgents(detectAgentsForScope('project'));
}
else {
// Interactive conflict without --force: prompt per target.
const displayPath = humanPath(t.target, t.scope);
const ok = await promptOverwrite(displayPath);
if (ok) {
finalDecisions.push({ target: t, status: 'updated' });
this.error(`--agents requires at least one of: ${skills_1.AGENT_IDS.join(', ')}.`, { exit: 2 });
}
if (flags.scope) {
scope = flags.scope;
}
else if (interactive) {
scope = await promptScope();
}
else {
this.error('Specify --agents and --scope in non-interactive mode.', { exit: 2 });
}
const sources = new Map();
for (const skill of skills) {
const sourceSkill = availableSkills.find((availableSkill) => availableSkill.name === skill);
if (!sourceSkill || !fs_1.default.existsSync(sourceSkill.sourceDir)) {
this.error(`Fetched skill source missing for "${skill}".`, { exit: 1 });
}
else {
finalDecisions.push({
target: t,
sources.set(skill, sourceSkill.sourceDir);
}
// Phase 1: Plan.
const planned = [];
for (const skill of skills) {
const sourceDir = sources.get(skill);
for (const id of agents) {
const agent = skills_1.AGENTS[id];
const target = (0, skills_1.targetSkillDir)(agent, scope, skill);
const { kind } = (0, skills_1.planSkillDirectoryCopy)(sourceDir, target);
planned.push({ skill, agent, scope, source: sourceDir, target, kind });
}
}
// Phase 2: Confirm.
const results = [];
const anyConflict = planned.some((t) => t.kind === 'conflict');
if (anyConflict && !flags.force && !interactive) {
// Non-interactive + conflict + no force: all-or-nothing. Skip all targets.
for (const t of planned) {
results.push({
skill: t.skill,
agent: t.agent.id,
scope: t.scope,
path: t.target,
status: 'skipped',
reason: SKIPPED_REASON_DECLINED,
reason: t.kind === 'conflict' ? SKIPPED_REASON_CONFLICT : SKIPPED_REASON_BLOCKED,
});
}
if (!flags.json) {
// --quiet still suppresses the human summary, but a hard refusal needs to be visible.
process.stderr.write('Existing skill directories would be overwritten. Re-run with --force, or run interactively to confirm per target.\n');
}
this.emitOutput(results, flags, skills, source);
this.exit(1);
}
}
// Phase 3: Apply.
for (const decision of finalDecisions) {
if (decision.status === 'installed' || decision.status === 'updated') {
(0, skills_1.applySkillFileCopy)(decision.target.source, decision.target.target);
// Decide final status per target (no writes yet).
const finalDecisions = [];
for (const t of planned) {
if (t.kind === 'install') {
finalDecisions.push({ target: t, status: 'installed' });
}
else if (t.kind === 'unchanged') {
finalDecisions.push({ target: t, status: 'unchanged' });
}
else if (flags.force) {
finalDecisions.push({ target: t, status: 'updated' });
}
else {
// Interactive conflict without --force: prompt per target.
const displayPath = humanPath(t.target, t.scope);
const ok = await promptOverwrite(displayPath);
if (ok) {
finalDecisions.push({ target: t, status: 'updated' });
}
else {
finalDecisions.push({
target: t,
status: 'skipped',
reason: SKIPPED_REASON_DECLINED,
});
}
}
}
results.push({
skill: decision.target.skill,
agent: decision.target.agent.id,
scope: decision.target.scope,
path: decision.target.target,
status: decision.status,
...(decision.reason ? { reason: decision.reason } : {}),
});
// Phase 3: Apply.
for (const decision of finalDecisions) {
if (decision.status === 'installed' || decision.status === 'updated') {
(0, skills_1.applySkillDirectoryCopy)(decision.target.source, decision.target.target);
}
results.push({
skill: decision.target.skill,
agent: decision.target.agent.id,
scope: decision.target.scope,
path: decision.target.target,
status: decision.status,
...(decision.reason ? { reason: decision.reason } : {}),
});
}
this.emitOutput(results, flags, skills, source);
}
this.emitOutput(results, flags, skills);
finally {
source?.cleanup();
}
}
emitOutput(results, flags, skills) {
emitOutput(results, flags, skills, source) {
if (flags.json) {

@@ -384,2 +414,7 @@ this.log(JSON.stringify({

skills,
source: {
repository: `${source.owner}/${source.repo}`,
ref: source.ref,
commit: source.commit,
},
results,

@@ -408,7 +443,7 @@ }, null, 2));

SkillsInstall.summary = 'Install Limrun skills for AI coding agents';
SkillsInstall.description = 'Copy bundled Limrun skills into the native skills directory for each selected agent (Claude Code, Cursor, Codex). Pre-checks detected agents and lets you pick project or global scope.';
SkillsInstall.description = 'Fetch the latest Limrun skills from limrun-inc/skills and install them into the native skills directory for each selected agent (Claude Code, Cursor, Codex). Pre-checks detected agents and lets you pick project or global scope.';
SkillsInstall.examples = [
'<%= config.bin %> skills install',
'<%= config.bin %> skills install --agents claude --agents cursor --scope project',
'<%= config.bin %> skills install --agents cursor --scope project --skills limrun-ios --skills limrun-detox',
'<%= config.bin %> skills install --agents cursor --scope project --skills limrun-xcode-and-ios-simulator --skills limrun-detox-testing',
'<%= config.bin %> skills install --agents codex --scope global --force',

@@ -420,8 +455,7 @@ ];

multiple: true,
options: ['claude', 'cursor', 'codex'],
options: skills_1.AGENT_IDS,
}),
skills: core_1.Flags.string({
description: 'Limrun skill to install. Repeat to pick multiple. Defaults to limrun-ios.',
description: 'Limrun skill to install. Repeat to pick multiple. Defaults to the remote catalog default.',
multiple: true,
options: [...SKILL_NAMES],
}),

@@ -433,3 +467,3 @@ scope: core_1.Flags.string({

force: core_1.Flags.boolean({
description: 'Overwrite existing skill files without confirmation.',
description: 'Overwrite existing skill directories without confirmation.',
default: false,

@@ -436,0 +470,0 @@ }),

@@ -1,1 +0,1 @@

{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/commands/skills/install.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/commands/skills/install.ts"],"names":[],"mappings":"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"}

@@ -1,2 +0,1 @@

import { type Config } from '@oclif/core';
export type AgentId = 'claude' | 'cursor' | 'codex';

@@ -12,10 +11,8 @@ export type Scope = 'project' | 'global';

export declare const AGENTS: Record<AgentId, AgentSpec>;
export declare function skillsRoot(config: Config): string;
export declare function sourceSkillMd(config: Config, skillName: string): string;
export declare function targetSkillMd(agent: AgentSpec, scope: Scope, skillName: string): string;
export declare function targetSkillDir(agent: AgentSpec, scope: Scope, skillName: string): string;
export type PlanKind = 'install' | 'unchanged' | 'conflict';
export declare function planSkillFileCopy(sourceFile: string, targetFile: string): {
export declare function planSkillDirectoryCopy(sourceDir: string, targetDir: string): {
kind: PlanKind;
};
export declare function applySkillFileCopy(sourceFile: string, targetFile: string): void;
export declare function applySkillDirectoryCopy(sourceDir: string, targetDir: string): void;
//# sourceMappingURL=skills.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AACpD,MAAM,MAAM,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEzC,eAAO,MAAM,SAAS,EAAE,OAAO,EAAkC,CAAC;AAElE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;IAChC,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;CACxC;AAcD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,CAsC7C,CAAC;AAEF,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvF;AAED,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AAE5D,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAO5F;AAED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAG/E"}
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AACpD,MAAM,MAAM,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEzC,eAAO,MAAM,SAAS,EAAE,OAAO,EAAkC,CAAC;AAElE,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;IAChC,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,EAAE,CAAC;CACxC;AAcD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,CAsC7C,CAAC;AAEF,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAExF;AAED,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AAgD5D,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAQ/F;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAqClF"}

@@ -7,7 +7,5 @@ "use strict";

exports.AGENTS = exports.AGENT_IDS = void 0;
exports.skillsRoot = skillsRoot;
exports.sourceSkillMd = sourceSkillMd;
exports.targetSkillMd = targetSkillMd;
exports.planSkillFileCopy = planSkillFileCopy;
exports.applySkillFileCopy = applySkillFileCopy;
exports.targetSkillDir = targetSkillDir;
exports.planSkillDirectoryCopy = planSkillDirectoryCopy;
exports.applySkillDirectoryCopy = applySkillDirectoryCopy;
const fs_1 = __importDefault(require("fs"));

@@ -18,3 +16,3 @@ const path_1 = __importDefault(require("path"));

function claudeGlobalRoot() {
const override = process.env.CLAUDE_CONFIG_DIR;
const override = process.env['CLAUDE_CONFIG_DIR'];
if (override)

@@ -25,3 +23,3 @@ return path_1.default.resolve(override);

function codexGlobalRoot() {
const override = process.env.CODEX_HOME;
const override = process.env['CODEX_HOME'];
if (override)

@@ -64,23 +62,96 @@ return path_1.default.resolve(override);

};
function skillsRoot(config) {
return path_1.default.join(config.root, 'skills');
function targetSkillDir(agent, scope, skillName) {
return path_1.default.join(agent.skillsDir(scope), skillName);
}
function sourceSkillMd(config, skillName) {
return path_1.default.join(skillsRoot(config), skillName, 'SKILL.md');
function listRelativeFiles(root) {
const files = [];
function walk(current, relativePrefix) {
for (const entry of fs_1.default.readdirSync(current, { withFileTypes: true })) {
const relativePath = path_1.default.join(relativePrefix, entry.name);
const fullPath = path_1.default.join(current, entry.name);
if (entry.isDirectory()) {
walk(fullPath, relativePath);
}
else if (entry.isFile()) {
files.push(relativePath);
}
else {
files.push(relativePath);
}
}
}
walk(root, '');
return files.sort();
}
function targetSkillMd(agent, scope, skillName) {
return path_1.default.join(agent.skillsDir(scope), skillName, 'SKILL.md');
function directoriesEqual(sourceDir, targetDir) {
const sourceFiles = listRelativeFiles(sourceDir);
const targetFiles = listRelativeFiles(targetDir);
if (sourceFiles.length !== targetFiles.length)
return false;
for (let i = 0; i < sourceFiles.length; i += 1) {
const sourceFile = sourceFiles[i];
const targetFile = targetFiles[i];
if (sourceFile === undefined || targetFile === undefined || sourceFile !== targetFile)
return false;
const sourcePath = path_1.default.join(sourceDir, sourceFile);
const targetPath = path_1.default.join(targetDir, targetFile);
const sourceStat = fs_1.default.lstatSync(sourcePath);
const targetStat = fs_1.default.lstatSync(targetPath);
if (!sourceStat.isFile() || !targetStat.isFile())
return false;
if (sourceStat.size !== targetStat.size)
return false;
const sourceBuf = fs_1.default.readFileSync(sourcePath);
const targetBuf = fs_1.default.readFileSync(targetPath);
if (!sourceBuf.equals(targetBuf))
return false;
}
return true;
}
function planSkillFileCopy(sourceFile, targetFile) {
if (!fs_1.default.existsSync(targetFile)) {
function planSkillDirectoryCopy(sourceDir, targetDir) {
if (!fs_1.default.existsSync(targetDir)) {
return { kind: 'install' };
}
const sourceBuf = fs_1.default.readFileSync(sourceFile);
const targetBuf = fs_1.default.readFileSync(targetFile);
return { kind: sourceBuf.equals(targetBuf) ? 'unchanged' : 'conflict' };
if (!fs_1.default.lstatSync(targetDir).isDirectory()) {
return { kind: 'conflict' };
}
return { kind: directoriesEqual(sourceDir, targetDir) ? 'unchanged' : 'conflict' };
}
function applySkillFileCopy(sourceFile, targetFile) {
fs_1.default.mkdirSync(path_1.default.dirname(targetFile), { recursive: true });
fs_1.default.copyFileSync(sourceFile, targetFile);
function applySkillDirectoryCopy(sourceDir, targetDir) {
const parentDir = path_1.default.dirname(targetDir);
const baseName = path_1.default.basename(targetDir);
const suffix = `${process.pid}-${Date.now()}`;
const tempDir = path_1.default.join(parentDir, `.${baseName}.tmp-${suffix}`);
const backupDir = path_1.default.join(parentDir, `.${baseName}.backup-${suffix}`);
let backedUp = false;
let installed = false;
fs_1.default.mkdirSync(parentDir, { recursive: true });
try {
fs_1.default.cpSync(sourceDir, tempDir, { recursive: true });
if (fs_1.default.existsSync(targetDir)) {
fs_1.default.renameSync(targetDir, backupDir);
backedUp = true;
}
fs_1.default.renameSync(tempDir, targetDir);
installed = true;
}
catch (err) {
if (backedUp && !installed && !fs_1.default.existsSync(targetDir) && fs_1.default.existsSync(backupDir)) {
try {
fs_1.default.renameSync(backupDir, targetDir);
backedUp = false;
}
catch {
// Preserve the original error; rollback failure leaves the backup for manual recovery.
}
}
throw err;
}
finally {
fs_1.default.rmSync(tempDir, { recursive: true, force: true });
if (installed || !backedUp) {
fs_1.default.rmSync(backupDir, { recursive: true, force: true });
}
}
}
//# sourceMappingURL=skills.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
{
"name": "@limrun/cli",
"version": "0.8.6",
"version": "0.9.0",
"description": "Use remote XCode, iOS Simulator, Android Emulator and more to build and test apps from Linux, Windows or macOS.",

@@ -76,5 +76,4 @@ "bin": {

"bin",
"skills",
"README.md"
]
}

@@ -619,3 +619,3 @@ # @limrun/cli

Install Limrun skills into the native skills directory of AI coding agents (Claude Code, Cursor, Codex). After installation, the agent auto-discovers the skill and triggers it when you ask things like "build the iOS app" or "show me a screenshot."
Fetch the latest Limrun skills from `limrun-inc/skills@main` and install them into the native skills directory of AI coding agents (Claude Code, Cursor, Codex). After installation, the agent auto-discovers the skill and triggers it when you ask things like "build the iOS app" or "show me a screenshot."

@@ -630,4 +630,5 @@ ```bash

lim skills install --agents codex --scope global
lim skills install --agents cursor --scope project --skills limrun-expo-development
# Overwrite existing skill files (otherwise the command refuses on non-interactive runs)
# Overwrite existing skill directories (otherwise the command refuses on non-interactive runs)
lim skills install --agents claude --scope project --force

@@ -644,7 +645,14 @@

| `--agents <id>` | Target agent. Repeat to select multiple. One of: `claude`, `cursor`, `codex`. |
| `--skills <name>` | Limrun skill to install. Repeat to select multiple. Defaults to the remote catalog default. |
| `--scope <project\|global>` | `project` writes into the current directory; `global` writes into the user's home directory. |
| `--force` | Overwrite existing skill files without confirmation. |
| `--force` | Overwrite existing skill directories without confirmation. |
| `--json` | Emit structured JSON instead of the human summary. |
| `--quiet` | Suppress non-result output. |
**Available skills:**
- `limrun-xcode-and-ios-simulator` (default): Build, launch, and control iOS apps with remote XCode and Simulators.
- `limrun-expo-development`: Iterate on Expo / React Native apps with remote iOS dev-client workflows.
- `limrun-detox-testing`: Configure, run, and debug Detox against Limrun iOS simulators.
**Install paths:**

@@ -660,3 +668,4 @@

- The command compares bundled vs existing content byte-for-byte. Identical content is reported as `Unchanged` (no writes).
- The command fetches `limrun-inc/skills@main` at runtime, so skill updates do not require a new `@limrun/cli` release.
- The command compares fetched vs existing skill directories byte-for-byte. Identical content is reported as `Unchanged` (no writes).
- Different content: in interactive mode you are asked to confirm each overwrite; in non-interactive mode the command refuses unless `--force` is passed.

@@ -663,0 +672,0 @@ - Non-interactive runs are all-or-nothing: if any selected target conflicts and `--force` is not set, no files are written for any target, and the command exits with status 1.

---
name: limrun-detox
description: Configure, run, or debug Detox on Limrun iOS simulators. Use when attaching the Limrun Detox runtime to an app, wiring Detox mediator connectivity, or validating app/tester connections over reverse tunnels.
---
# Limrun Detox
Use this for Detox runtime work on Limrun iOS. Keep build concerns separate unless the user explicitly asks for a native build.
## Components
- Tester: local Node/Jest/Detox process.
- Mediator: `detox run-server`, usually local to the agent machine.
- App client: injected by limulator through `lim ios launch-app --runtime detox`.
## CLI Flow
Check current help before running commands you have not used in this session:
```bash
lim ios reverse --help
lim ios launch-app --help
```
Typical sequence:
```bash
# Start the Detox mediator locally.
npx detox run-server -p 8099 -l verbose
# Expose the mediator to the simulator.
lim ios reverse 57091:8099 --id <ios-id>
# Relaunch the app with the managed Detox runtime. Use the remote endpoint
# printed by `lim ios reverse`, not 127.0.0.1 on the user machine.
# --detox-version is optional when running from the project with node_modules/detox.
lim ios launch-app <bundle-id> \
--id <ios-id> \
--runtime detox \
--detox-server-url ws://<reverse-remote-host>:57091 \
--detox-session-id <session-id> \
--detox-version <detox-version>
# Run the tester with the same server/session.
npx detox test --no-start
```
Prefer starting the tester before the app connects, or use the maintained orchestration in `examples/detox-ios`, to avoid benign mediator "cannot forward" noise.
If you manually launch the app before `npx detox test --no-start`, that mediator message is expected until the tester connects.
## Detox Test Setup
`npx detox test --no-start` still needs the normal Detox project configuration:
- Pass the Detox config file and configuration name from your project (see `examples/detox-ios/.detoxrc.cjs` for a reference layout).
- Use the Limrun third-party driver: `type: '@limrun/detox/driver'`.
- Keep `DETOX_SERVER` and `DETOX_SESSION_ID` aligned with the mediator and launch command.
- Provide Limrun driver env such as `LIMRUN_IOS_ID`, `LIMRUN_IOS_API_URL`, and `LIMRUN_IOS_TOKEN` when screenshots or driver calls need the instance API.
Use `examples/detox-ios` as the maintained happy path for exact config/env wiring. Use `-l trace` on `detox run-server` only when verbose logs are not enough.
For native SwiftUI apps, a minimal Detox configuration usually looks like:
```js
module.exports = {
testRunner: { args: { $0: 'jest' }, jest: { setupTimeout: 120000 } },
apps: { ios: { type: 'ios.app', binaryPath: 'unused-by-limrun' } },
devices: {
limrun: {
type: '@limrun/detox/driver',
device: { id: process.env.LIMRUN_IOS_ID },
},
},
configurations: {
'ios.limrun': {
device: 'limrun',
app: 'ios',
behavior: { init: { reinstallApp: false }, cleanup: { shutdownDevice: false } },
},
},
};
```
Then launch with `lim ios launch-app <bundle-id> --runtime detox ...` and run `npx detox test --no-start`.
## Validation Signals
- App connected: `detox run-server` logs `role:"app"` and `appConnected:true`.
- Tester connected: the same session reaches `testerConnected:true, appConnected:true`.
- Runtime loaded: the app connects to the mediator after the `--runtime detox` launch.
- UI visible: `lim ios element-tree --id <ios-id>` shows the expected app screen.
## Gotchas
- Do not pass arbitrary env vars, app args, or injectable paths. Use `--runtime detox`.
- `--detox-version` should match the local `detox` package version used by the tester. If omitted, `lim ios launch-app` resolves it from the current working directory; pass it explicitly when running outside the Detox project.
- Unsupported bundled Detox versions should fail with a clear supported-version list.
- `Cannot forward the message to the Detox client` can simply mean the app connected before the tester did.
- For SwiftUI, prefer stable accessibility identifiers, e.g. `.accessibilityIdentifier("greetingText")` with `by.id('greetingText')`; `by.text(...)` can miss labels that appear in `lim ios element-tree`.
- Debug failures by checking `lim ios element-tree --id <ios-id>` first, then mediator logs for app/tester connection state.
- Cleanup manual runs by stopping `detox run-server`, stopping `lim ios reverse`, and deleting the instance with `lim ios delete <ios-id>` (`--id` is not valid for delete).
- This does not make Detox own the iOS lifecycle; prepare or reuse the Limrun instance separately.
---
name: limrun-skill
description: "Replaces xcodebuild with remote XCode and Simulators. Use when the user wants to build or run an iOS app, test iOS UI, see their app on a simulator, or says 'run it', 'build it', 'test it', 'show me a screenshot', or 'launch on simulator'."
user-invocable: true
effort: high
---
# Remote XCode & iOS Simulator
You are an iOS build-and-test operator. Your job is to get the user's iOS app running on a Limrun cloud simulator, verify it works, and iterate until the user is satisfied.
All builds and simulator operations run on Limrun and that's why you can build iOS
apps from any environments; linux, windows, macos, VM, container etc. Never try to
use local Xcode, local simulators, or local macOS build tools.
If `lim` CLI is not installed, you can install it with the following:
```bash
npm install --global @limrun/cli
```
## Check the CLI for current commands and flags
The CLI is the source of truth for command names, flags, and behavior. Before invoking any `lim` command you have not already used in this session, MUST run its `--help` first. Use:
```bash
lim ios --help # list all iOS subcommands
lim ios <subcommand> --help # flags and examples for one iOS subcommand
lim xcode --help # list all xcode subcommands
lim xcode <subcommand> --help # flags and examples for one xcode subcommand
lim session --help # list all session subcommands
lim session <subcommand> --help # flags and examples for one session subcommand
```
## Build and Reload
First, create an XCode & iOS Simulator pair:
```bash
# Add label selector depending on your identifiers. For example, Linear issue, repo name etc.
lim ios create --xcode \
--reuse-if-exists \
--label issue=<ISSUE ID> \
--label repo=<Repo Name> \
--label agent=<Your Agent Name>
# Example call: lim xcode create --reuse-if-exists --label issue=LIM-34 --label repo=sample-native-app --label agent=cursor
```
In the command output, there will be a signed stream URL. Share that with user so that they can watch the simulator while you are working.
If you have a browser that user can see, open the signed stream URL in that browser and notify the user.
### Build
Instead of `xcodebuild` command, you MUST use the following to build the iOS app.
```bash
lim xcode build .
```
Use `--scheme` and `--workspace` flags if the project has multiple schemes or uses a workspace file. This makes sure the files are synced with the remote xcode and triggers
a build where the build logs are streamed through stdout and stderr.
Use `--configuration Debug` or `--configuration Release` when the app needs a specific Xcode build configuration:
```bash
lim xcode build . --configuration Debug
```
If omitted, Limrun uses limbuild's project-type default: `Debug` for native Xcode builds and `Release` for React Native / Expo builds. `--dev-server-url` is only supported with `--configuration Debug` for React Native / Expo builds. It is a post-install launch URL: limbuild validates that it is a parseable absolute URL, then opens it unchanged after installing on the attached simulator.
For Expo dev-client builds, do not use plain `exp://`; Expo Go may intercept it. Use the app scheme: `expo.scheme` from `app.json` when present, otherwise Expo dev-client's generated default `exp+{expo.slug}`.
When Metro runs locally, prefer a same-port reverse tunnel. Expo dev-client can derive or rediscover Metro URLs, so matching the remote tunnel port and local Metro port avoids stale or unreachable advertised ports. Use the simulator-facing host printed by `lim ios reverse` in both `REACT_NATIVE_PACKAGER_HOSTNAME` and the encoded dev-client URL.
```bash
# app.json: "scheme": "myapp" or fallback "slug": "myapp" -> exp+myapp
lim ios reverse 57090:57090 --id <ios-instance-id>
REACT_NATIVE_PACKAGER_HOSTNAME=<reverse-host> \
npx expo start --dev-client --host lan --port 57090
lim xcode build . --configuration Debug \
--dev-server-url 'myapp://expo-development-client/?url=http%3A%2F%2F<reverse-host>%3A57090'
```
If the app launches without connecting to Metro, open the same URL explicitly to separate build/install issues from dev-client URL issues:
```bash
lim ios open-url --id <ios-instance-id> \
'myapp://expo-development-client/?url=http%3A%2F%2F<reverse-host>%3A57090'
```
Mismatched tunnels such as `57090:8081` can work for plain TCP, but Expo dev-client is stricter because multiple URLs may be derived or advertised. Only use mismatched ports after verifying every dev-client URL points to the remote tunnel port, not the local Metro port.
Every successful build will automatically re-install the app in iOS Simulator and re-launch it.
## Interacting with the App
Prefer tapping by accessibility identifier, then by label, then by coordinates as a last resort:
```bash
lim ios tap-element --ax-unique-id startButton
lim ios tap-element --ax-label "Save"
lim ios tap 201 450
```
After every interaction, re-run `element-tree` to confirm the UI transitioned correctly. No sleep is needed between a tap and element-tree.
For text input:
```bash
lim ios type "hello world"
```
## Testing Changes
After every build, test new or changed functionality by using interaction commands. Focus on what changed plus a quick smoke test of core flows.
Use element tree for functional assertions (element existence, labels, state changes). Use screenshots only for visual-only properties.
Use video recording for most accurate interaction tests such as animations, gameplay,
real experience etc.
Generally, start with getting an element tree:
```bash
lim ios element-tree
```
Then if a single action will be taken, just call it. For example:
```bash
lim ios tap-element --ax-label Continue
```
If you will take multiple actions, you can create a chain of actions to be executed
with precise timing.
Some examples:
```bash
lim ios perform --action type=tap,x=100,y=200 --action "type=typeText,text=Hello World"
lim ios perform --action type=wait,durationMs=1000 --action type=pressKey,key=enter
```
You can write to a file and execute that too:
```bash
lim ios perform --file ./actions.yaml
```
Use `lim ios perform --help` for more details on how to use it.
Video recording is available so you can review what the user sees while you are taking actions. For
any testing involving motion prefer video over screenshots for review.
Always include a demo video in the pull request so that user can see how it works.
Start recording (non-blocking):
```bash
lim ios record start
```
Stop and save recording:
```bash
lim ios record stop -o /tmp/recording.mp4
```
## Finalize
When you are done with the changes and present to the user, you should provide a
preview link to the user so they can test it.
If you will open a PR, make sure to do this and add the preview link to PR.
First build and make remote xcode upload the build:
```
ASSET_NAME="<bundle id/pr number/ or any session identifier>.zip"
lim xcode build . --upload ${ASSET_NAME}
# For a debug preview build:
lim xcode build . --configuration Debug --upload ${ASSET_NAME}
```
And construct this link for preview:
```
# Change ${ASSET_NAME} with asset name given above
https://console.limrun.com/preview?asset=${ASSET_NAME}&platform=ios
```
Always provide this in your last message.
## Cleanup
When the user is satisfied or the conversation is ending, always clean up:
```bash
lim ios delete
```
## Gotchas
These are common failure points. Check here first when something goes wrong.
- **Instance ID is optional.** The CLI remembers the last created instance. You only need to pass an ID explicitly when controlling multiple instances.
- **No sleep needed between `tap-element` and `element-tree`.** The tap blocks until complete.
- **`element-tree` can be large.** Pipe through `grep` or `jq` to extract what you need rather than dumping the full tree into context.
- **Build errors are your job to fix.** If a build fails, read the error output, fix the code, and rebuild. Do not ask the user to fix build errors.
- **Bundle ID discovery.** If you don't know the bundle ID, check the Xcode project files or run `lim ios list-apps` after a successful build.
- **Expo dev-client redbox `Operation not permitted` usually means the simulator cannot reach the advertised Metro URL.** First use same-port reverse mapping such as `57090:57090`; do not add iOS ATS/local-network Info.plist exceptions unless a same-port tunnel still fails.
- **Monorepos need the workspace root.** Build from the repo root and pass `--expo-app-dir <app-path>` so the remote resolver sees the lockfile and workspace metadata.