synskill 0.1.5 → 0.1.6

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.
Files changed (3) hide show
  1. package/README.md +69 -69
  2. package/bin/synskill.js +76 -12
  3. package/package.json +33 -33
package/README.md CHANGED
@@ -1,69 +1,69 @@
1
- # synskill
2
-
3
- `synskill` is a public npm CLI that installs skills from a private Git repository you already have access to.
4
-
5
- ## Usage
6
-
7
- ```bash
8
- npx synskill
9
- ```
10
-
11
- ## Install A Skill
12
-
13
- Install one skill directly into the current repo:
14
-
15
- ```bash
16
- npx synskill <skill-name> --project
17
- ```
18
-
19
- Examples:
20
-
21
- ```bash
22
- npx synskill pr-review --project
23
- npx synskill bootstrap-device-repo --project
24
- npx synskill skill-creator --global
25
- ```
26
-
27
- Omit `--project` for a global install. Add `--copy` if you want copies instead of symlinks.
28
-
29
- ## Requirements
30
-
31
- - Node.js 18 or newer
32
- - Git available in `PATH`
33
- - Access to the private repository that contains your skills
34
-
35
- ## Common Commands
36
-
37
- ```bash
38
- npx synskill
39
- npx synskill pr-review --project
40
- npx synskill install pr-review --project
41
- npx synskill add pr-review --project
42
- npx synskill list
43
- npx synskill skill-creator --global
44
- npx synskill install --skills my-skill --project
45
- npx synskill install --skills my-skill --project --copy
46
- npx synskill update
47
- ```
48
-
49
- ## Private Repo Override
50
-
51
- ```bash
52
- npx synskill --repo-url <git-url>
53
- ```
54
-
55
- or:
56
-
57
- ```bash
58
- SKILLS_REPO_URL=<git-url> npx synskill
59
- ```
60
-
61
- ## Notes
62
-
63
- - The CLI keeps a local cache of the private skills repository to make repeated runs fast.
64
- - You can install a specific skill directly with `npx synskill install <skill-name>` or `npx synskill <skill-name>`.
65
- - `skill-creator` is fetched on demand from `https://github.com/anthropics/skills/tree/main/skills/skill-creator` so it stays on the upstream latest version without being stored in this repo.
66
- - `skill-creator` is explicit-install only and does not appear in the default interactive skills list.
67
- - By default it symlinks each selected target directly to the source skill directory; use `--copy` to write independent copies instead.
68
- - `update` forces a cache refresh.
69
- - `--no-pull` uses the existing cache without refreshing it.
1
+ # synskill
2
+
3
+ `synskill` is a public npm CLI that installs skills from a private Git repository you already have access to.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ npx synskill
9
+ ```
10
+
11
+ ## Install A Skill
12
+
13
+ Install one skill directly into the current repo:
14
+
15
+ ```bash
16
+ npx synskill <skill-name> --project
17
+ ```
18
+
19
+ Examples:
20
+
21
+ ```bash
22
+ npx synskill pr-review --project
23
+ npx synskill bootstrap-device-repo --project
24
+ npx synskill skill-creator --global
25
+ ```
26
+
27
+ Omit `--project` for a global install. Add `--copy` if you want copies instead of symlinks.
28
+
29
+ ## Requirements
30
+
31
+ - Node.js 18 or newer
32
+ - Git available in `PATH`
33
+ - Access to the private repository that contains your skills
34
+
35
+ ## Common Commands
36
+
37
+ ```bash
38
+ npx synskill
39
+ npx synskill pr-review --project
40
+ npx synskill install pr-review --project
41
+ npx synskill add pr-review --project
42
+ npx synskill list
43
+ npx synskill skill-creator --global
44
+ npx synskill install --skills my-skill --project
45
+ npx synskill install --skills my-skill --project --copy
46
+ npx synskill update
47
+ ```
48
+
49
+ ## Private Repo Override
50
+
51
+ ```bash
52
+ npx synskill --repo-url <git-url>
53
+ ```
54
+
55
+ or:
56
+
57
+ ```bash
58
+ SKILLS_REPO_URL=<git-url> npx synskill
59
+ ```
60
+
61
+ ## Notes
62
+
63
+ - The CLI keeps a local cache of the private skills repository to make repeated runs fast.
64
+ - You can install a specific skill directly with `npx synskill install <skill-name>` or `npx synskill <skill-name>`.
65
+ - `skill-creator` is fetched on demand from `https://github.com/anthropics/skills/tree/main/skills/skill-creator` so it stays on the upstream latest version without being stored in this repo.
66
+ - `skill-creator` is explicit-install only and does not appear in the default interactive skills list.
67
+ - By default it symlinks each selected target directly to the source skill directory; use `--copy` to write independent copies instead.
68
+ - `update` forces a cache refresh.
69
+ - `--no-pull` uses the existing cache without refreshing it.
package/bin/synskill.js CHANGED
@@ -419,6 +419,30 @@ var require_git = __commonJS({
419
419
  });
420
420
  }
421
421
  }
422
+ function sshToHttpsUrl(url) {
423
+ if (!url || typeof url !== "string") {
424
+ return null;
425
+ }
426
+ const scpMatch = url.match(/^git@([^:]+):(.+)$/);
427
+ if (scpMatch) {
428
+ const host = scpMatch[1];
429
+ const repoPath = scpMatch[2].replace(/\.git$/, "");
430
+ return `https://${host}/${repoPath}.git`;
431
+ }
432
+ const sshMatch = url.match(/^ssh:\/\/git@([^/]+)\/(.+)$/);
433
+ if (sshMatch) {
434
+ const host = sshMatch[1];
435
+ const repoPath = sshMatch[2].replace(/\.git$/, "");
436
+ return `https://${host}/${repoPath}.git`;
437
+ }
438
+ return null;
439
+ }
440
+ function isSshUrl(url) {
441
+ if (!url || typeof url !== "string") {
442
+ return false;
443
+ }
444
+ return url.startsWith("git@") || url.startsWith("ssh://");
445
+ }
422
446
  function formatGitAccessError2(repoUrl, error) {
423
447
  const repoLabel = repoUrl && repoUrl !== DEFAULT_REPO_URL2 ? repoUrl : "the private repository";
424
448
  if (!(error instanceof GitCommandError)) {
@@ -451,7 +475,9 @@ ${error.message}`;
451
475
  GitCommandError,
452
476
  formatGitAccessError: formatGitAccessError2,
453
477
  getInheritedGitConfigArgs,
478
+ isSshUrl,
454
479
  runGit,
480
+ sshToHttpsUrl,
455
481
  syncInheritedGitConfig
456
482
  };
457
483
  }
@@ -1618,7 +1644,7 @@ var require_repo_cache = __commonJS({
1618
1644
  LEGACY_REPO_PACKAGE_NAMES,
1619
1645
  PRIVATE_REPO_ENV_VAR: PRIVATE_REPO_ENV_VAR2
1620
1646
  } = require_constants();
1621
- var { GitCommandError, formatGitAccessError: formatGitAccessError2, runGit, syncInheritedGitConfig } = require_git();
1647
+ var { GitCommandError, formatGitAccessError: formatGitAccessError2, runGit, syncInheritedGitConfig, isSshUrl, sshToHttpsUrl } = require_git();
1622
1648
  function getConfiguredRepoUrl2(options = {}, env = process.env) {
1623
1649
  return options.repoUrl || env[PRIVATE_REPO_ENV_VAR2] || env[LEGACY_PRIVATE_REPO_ENV_VAR] || DEFAULT_REPO_URL2;
1624
1650
  }
@@ -1792,27 +1818,65 @@ Using the existing local cache at ${cacheDir}.`
1792
1818
  };
1793
1819
  }
1794
1820
  function cloneRepo(cacheDir, repoUrl, branch, gitConfigContextCwd) {
1795
- runGit(["clone", "--depth", "1", "--branch", branch, repoUrl, cacheDir], {
1796
- repoUrl,
1797
- gitConfigContextCwd
1798
- });
1821
+ try {
1822
+ runGit(["clone", "--depth", "1", "--branch", branch, repoUrl, cacheDir], {
1823
+ repoUrl,
1824
+ gitConfigContextCwd
1825
+ });
1826
+ } catch (error) {
1827
+ if (error instanceof GitCommandError && error.isAuthError && isSshUrl(repoUrl)) {
1828
+ const httpsUrl = sshToHttpsUrl(repoUrl);
1829
+ if (httpsUrl) {
1830
+ runGit(["clone", "--depth", "1", "--branch", branch, httpsUrl, cacheDir], {
1831
+ repoUrl: httpsUrl,
1832
+ gitConfigContextCwd
1833
+ });
1834
+ syncInheritedGitConfig(cacheDir, gitConfigContextCwd);
1835
+ return;
1836
+ }
1837
+ }
1838
+ throw error;
1839
+ }
1799
1840
  syncInheritedGitConfig(cacheDir, gitConfigContextCwd);
1800
1841
  }
1801
1842
  function refreshRepo(cacheDir, repoUrl, branch, gitConfigContextCwd) {
1802
1843
  syncInheritedGitConfig(cacheDir, gitConfigContextCwd);
1803
- runGit(["fetch", "--depth", "1", "origin", branch], {
1804
- cwd: cacheDir,
1805
- repoUrl,
1806
- gitConfigContextCwd
1807
- });
1844
+ const currentRemote = readOriginUrl(cacheDir);
1845
+ const effectiveUrl = currentRemote || repoUrl;
1846
+ try {
1847
+ runGit(["fetch", "--depth", "1", "origin", branch], {
1848
+ cwd: cacheDir,
1849
+ repoUrl: effectiveUrl,
1850
+ gitConfigContextCwd
1851
+ });
1852
+ } catch (error) {
1853
+ if (error instanceof GitCommandError && error.isAuthError && isSshUrl(effectiveUrl)) {
1854
+ const httpsUrl = sshToHttpsUrl(effectiveUrl);
1855
+ if (httpsUrl) {
1856
+ try {
1857
+ runGit(["remote", "set-url", "origin", httpsUrl], { cwd: cacheDir });
1858
+ } catch {
1859
+ }
1860
+ runGit(["fetch", "--depth", "1", "origin", branch], {
1861
+ cwd: cacheDir,
1862
+ repoUrl: httpsUrl,
1863
+ gitConfigContextCwd
1864
+ });
1865
+ } else {
1866
+ throw error;
1867
+ }
1868
+ } else {
1869
+ throw error;
1870
+ }
1871
+ }
1808
1872
  runGit(["reset", "--hard", "FETCH_HEAD"], {
1809
1873
  cwd: cacheDir,
1810
- repoUrl,
1874
+ repoUrl: effectiveUrl,
1811
1875
  gitConfigContextCwd
1812
1876
  });
1813
1877
  runGit(["clean", "-fd", "-e", path2.basename(getCacheMetadataPath(cacheDir))], {
1814
1878
  cwd: cacheDir,
1815
- repoUrl,
1879
+ repoUrl: effectiveUrl,
1816
1880
  gitConfigContextCwd
1817
1881
  });
1818
1882
  }
package/package.json CHANGED
@@ -1,33 +1,33 @@
1
- {
2
- "name": "synskill",
3
- "version": "0.1.5",
4
- "private": false,
5
- "description": "CLI installer for private agent skills.",
6
- "license": "UNLICENSED",
7
- "files": [
8
- "bin",
9
- "README.md"
10
- ],
11
- "scripts": {
12
- "build": "node scripts/bundle-cli.js",
13
- "synskill": "node src/synskill.js",
14
- "test": "node --test tests/*.test.js",
15
- "prepack": "node scripts/manage-pack-readme.js prepack",
16
- "postpack": "node scripts/manage-pack-readme.js postpack",
17
- "prepublishOnly": "npm run build && npm test"
18
- },
19
- "bin": {
20
- "synskill": "bin/synskill.js"
21
- },
22
- "engines": {
23
- "node": ">=18"
24
- },
25
- "devDependencies": {
26
- "@clack/prompts": "^0.11.0",
27
- "esbuild": "^0.20.2",
28
- "picocolors": "^1.1.1"
29
- },
30
- "dependencies": {
31
- "markdown-it": "^14.1.1"
32
- }
33
- }
1
+ {
2
+ "name": "synskill",
3
+ "version": "0.1.6",
4
+ "private": false,
5
+ "description": "CLI installer for private agent skills.",
6
+ "license": "UNLICENSED",
7
+ "files": [
8
+ "bin",
9
+ "README.md"
10
+ ],
11
+ "scripts": {
12
+ "build": "node scripts/bundle-cli.js",
13
+ "synskill": "node src/synskill.js",
14
+ "test": "node scripts/run-tests.js",
15
+ "prepack": "node scripts/manage-pack-readme.js prepack",
16
+ "postpack": "node scripts/manage-pack-readme.js postpack",
17
+ "prepublishOnly": "npm run build && npm test"
18
+ },
19
+ "bin": {
20
+ "synskill": "bin/synskill.js"
21
+ },
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "devDependencies": {
26
+ "@clack/prompts": "^0.11.0",
27
+ "esbuild": "^0.20.2",
28
+ "picocolors": "^1.1.1"
29
+ },
30
+ "dependencies": {
31
+ "markdown-it": "^14.1.1"
32
+ }
33
+ }