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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .opencode/plugin/strray-codex-injection.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 20 additions & 17 deletions src/cli/commands/skill-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,25 @@ function cloneRepo(url: string, targetDir: string): string {

const errors: string[] = [];

// Prefer gh repo clone when authenticated (faster, handles auth seamlessly)
let hasGh = false;
try {
execSync("gh auth status --hostname github.com", { stdio: "pipe", timeout: 5000 });
hasGh = true;
} catch { /* gh not installed or not authenticated */ }

if (hasGh) {
try {
console.log(` Cloning via gh...`);
execSync(`gh repo clone ${slug.owner}/${slug.repo} "${extracted}" -- --depth 1`, { stdio: "pipe", timeout: 60000 });
return extracted;
} catch (ghErr: unknown) {
const stderr = (ghErr as { stderr?: Buffer })?.stderr?.toString("utf-8") || "";
errors.push(` gh repo clone: ${stderr.split("\n").filter((l: string) => l.includes("Error:"))[0]?.trim() || (ghErr as Error).message.split("\n")[0]}`);
}
}

// Fallback: tarball download (public repos)
for (const branch of ["main", "master"]) {
const archiveUrl = `https://codeload.github.com/${slug.owner}/${slug.repo}/tar.gz/${branch}`;
try {
Expand Down Expand Up @@ -123,26 +142,10 @@ function cloneRepo(url: string, targetDir: string): string {
}
}

// Last resort: git clone (HTTPS then SSH)
const httpsUrl = url;
const sshUrl = url.replace(/^https:\/\/github\.com\//, "git@github.com:");

let hasGh = false;
try {
execSync("gh auth status --hostname github.com", { stdio: "pipe", timeout: 5000 });
hasGh = true;
} catch { /* gh not installed or not authenticated */ }

if (hasGh && slug) {
try {
console.log(` Trying gh repo clone...`);
execSync(`gh repo clone ${slug.owner}/${slug.repo} "${extracted}" -- --depth 1`, { stdio: "pipe", timeout: 60000 });
return extracted;
} catch (ghErr: unknown) {
const stderr = (ghErr as { stderr?: Buffer })?.stderr?.toString("utf-8") || "";
errors.push(` gh repo clone: ${stderr.split("\n").filter((l: string) => l.includes("Error:"))[0]?.trim() || (ghErr as Error).message.split("\n")[0]}`);
}
}

for (const [proto, gitUrl] of [["HTTPS", httpsUrl], ["SSH", sshUrl]] as const) {
try {
execSync(`git clone --depth 1 ${gitUrl} "${extracted}"`, { stdio: "pipe", timeout: 30000 });
Expand Down
8 changes: 7 additions & 1 deletion src/plugin/strray-codex-injection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1004,7 +1004,13 @@ export default async function strrayCodexPlugin(input: {
);

// Initialize StrRay framework
const initScriptPath = path.join(directory, ".opencode", "init.sh");
// Primary: project .opencode/init.sh (copied by postinstall)
// Fallback: package .opencode/init.sh (works when postinstall skips for Hermes consumers)
let initScriptPath = path.join(directory, ".opencode", "init.sh");
const pkgInitPath = path.join(directory, "node_modules", "strray-ai", ".opencode", "init.sh");
if (!fs.existsSync(initScriptPath) && fs.existsSync(pkgInitPath)) {
initScriptPath = pkgInitPath;
}
if (fs.existsSync(initScriptPath)) {
try {
const { stderr } = await spawnPromise(
Expand Down
Loading