allagents 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +21 -0
  2. package/dist/index.js +154 -45
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -60,6 +60,9 @@ bunx allagents
60
60
  allagents workspace init my-workspace
61
61
  cd my-workspace
62
62
 
63
+ # Or initialize from a remote GitHub template
64
+ allagents workspace init my-workspace --from owner/repo/path/to/template
65
+
63
66
  # Add a marketplace (or let auto-registration handle it)
64
67
  allagents plugin marketplace add anthropics/claude-plugins-official
65
68
 
@@ -71,6 +74,23 @@ allagents workspace plugin add my-plugin@someuser/their-repo
71
74
  allagents workspace sync
72
75
  ```
73
76
 
77
+ ### Initialize from Remote Template
78
+
79
+ Start a new workspace instantly from any GitHub repository containing a `workspace.yaml`:
80
+
81
+ ```bash
82
+ # From GitHub URL
83
+ allagents workspace init ~/my-project --from https://github.com/myorg/templates/tree/main/nodejs
84
+
85
+ # From shorthand
86
+ allagents workspace init ~/my-project --from myorg/templates/nodejs
87
+
88
+ # From repo root (looks for .allagents/workspace.yaml or workspace.yaml)
89
+ allagents workspace init ~/my-project --from myorg/templates
90
+ ```
91
+
92
+ This fetches the workspace configuration directly from GitHub - no cloning required.
93
+
74
94
  ## Commands
75
95
 
76
96
  ### Workspace Commands
@@ -78,6 +98,7 @@ allagents workspace sync
78
98
  ```bash
79
99
  # Initialize a new workspace from template
80
100
  allagents workspace init <path>
101
+ allagents workspace init <path> --from <source> # From local path or GitHub URL
81
102
 
82
103
  # Sync all plugins to workspace (non-destructive)
83
104
  allagents workspace sync [options]
package/dist/index.js CHANGED
@@ -11054,9 +11054,9 @@ var {
11054
11054
  } = import__.default;
11055
11055
 
11056
11056
  // src/cli/index.ts
11057
- import { readFileSync as readFileSync2 } from "node:fs";
11058
- import { dirname as dirname6, join as join11 } from "node:path";
11059
- import { fileURLToPath as fileURLToPath3 } from "node:url";
11057
+ import { readFileSync as readFileSync3 } from "node:fs";
11058
+ import { dirname as dirname7, join as join12 } from "node:path";
11059
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
11060
11060
 
11061
11061
  // src/core/workspace.ts
11062
11062
  import { mkdir as mkdir5, readFile as readFile6, writeFile as writeFile4, copyFile as copyFile2 } from "node:fs/promises";
@@ -21060,6 +21060,88 @@ async function autoRegisterMarketplace(name) {
21060
21060
  };
21061
21061
  }
21062
21062
 
21063
+ // src/core/github-fetch.ts
21064
+ async function fetchFileFromGitHub(owner, repo, path3) {
21065
+ try {
21066
+ const result = await execa("gh", [
21067
+ "api",
21068
+ `repos/${owner}/${repo}/contents/${path3}`,
21069
+ "--jq",
21070
+ ".content"
21071
+ ]);
21072
+ if (result.stdout) {
21073
+ const content = Buffer.from(result.stdout, "base64").toString("utf-8");
21074
+ return content;
21075
+ }
21076
+ return null;
21077
+ } catch {
21078
+ return null;
21079
+ }
21080
+ }
21081
+ async function fetchWorkspaceFromGitHub(url) {
21082
+ const parsed = parseGitHubUrl(url);
21083
+ if (!parsed) {
21084
+ return {
21085
+ success: false,
21086
+ error: "Invalid GitHub URL format. Expected: https://github.com/owner/repo"
21087
+ };
21088
+ }
21089
+ const { owner, repo, subpath } = parsed;
21090
+ try {
21091
+ await execa("gh", ["--version"]);
21092
+ } catch {
21093
+ return {
21094
+ success: false,
21095
+ error: "gh CLI not installed. Install from: https://cli.github.com"
21096
+ };
21097
+ }
21098
+ try {
21099
+ await execa("gh", ["repo", "view", `${owner}/${repo}`, "--json", "name"]);
21100
+ } catch (error) {
21101
+ if (error instanceof Error) {
21102
+ const errorMessage = error.message.toLowerCase();
21103
+ if (errorMessage.includes("not found") || errorMessage.includes("404") || errorMessage.includes("could not resolve to a repository")) {
21104
+ return {
21105
+ success: false,
21106
+ error: `Repository not found: ${owner}/${repo}`
21107
+ };
21108
+ }
21109
+ if (errorMessage.includes("auth") || errorMessage.includes("authentication")) {
21110
+ return {
21111
+ success: false,
21112
+ error: "GitHub authentication required. Run: gh auth login"
21113
+ };
21114
+ }
21115
+ }
21116
+ return {
21117
+ success: false,
21118
+ error: `Failed to access repository: ${error instanceof Error ? error.message : String(error)}`
21119
+ };
21120
+ }
21121
+ const basePath = subpath || "";
21122
+ const pathsToTry = basePath ? [
21123
+ `${basePath}/${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE}`,
21124
+ `${basePath}/${WORKSPACE_CONFIG_FILE}`
21125
+ ] : [
21126
+ `${CONFIG_DIR}/${WORKSPACE_CONFIG_FILE}`,
21127
+ WORKSPACE_CONFIG_FILE
21128
+ ];
21129
+ for (const path3 of pathsToTry) {
21130
+ const content = await fetchFileFromGitHub(owner, repo, path3);
21131
+ if (content) {
21132
+ return {
21133
+ success: true,
21134
+ content
21135
+ };
21136
+ }
21137
+ }
21138
+ return {
21139
+ success: false,
21140
+ error: `No workspace.yaml found in: ${owner}/${repo}${subpath ? `/${subpath}` : ""}
21141
+ Expected at: ${pathsToTry.join(" or ")}`
21142
+ };
21143
+ }
21144
+
21063
21145
  // src/core/workspace.ts
21064
21146
  async function initWorkspace(targetPath = ".", options2 = {}) {
21065
21147
  const absoluteTarget = resolve5(targetPath);
@@ -21079,48 +21161,72 @@ async function initWorkspace(targetPath = ".", options2 = {}) {
21079
21161
  let workspaceYamlContent;
21080
21162
  let sourceDir;
21081
21163
  if (options2.from) {
21082
- const fromPath = resolve5(options2.from);
21083
- if (!existsSync7(fromPath)) {
21084
- throw new Error(`Template not found: ${fromPath}`);
21085
- }
21086
- const { stat: stat2 } = await import("node:fs/promises");
21087
- const fromStat = await stat2(fromPath);
21088
- let sourceYamlPath;
21089
- if (fromStat.isDirectory()) {
21090
- const nestedPath = join8(fromPath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
21091
- const rootPath = join8(fromPath, WORKSPACE_CONFIG_FILE);
21092
- if (existsSync7(nestedPath)) {
21093
- sourceYamlPath = nestedPath;
21094
- sourceDir = fromPath;
21095
- } else if (existsSync7(rootPath)) {
21096
- sourceYamlPath = rootPath;
21097
- sourceDir = fromPath;
21098
- } else {
21099
- throw new Error(`No workspace.yaml found in: ${fromPath}
21100
- Expected at: ${nestedPath} or ${rootPath}`);
21164
+ if (isGitHubUrl(options2.from)) {
21165
+ const fetchResult = await fetchWorkspaceFromGitHub(options2.from);
21166
+ if (!fetchResult.success || !fetchResult.content) {
21167
+ throw new Error(fetchResult.error || "Failed to fetch workspace from GitHub");
21101
21168
  }
21102
- } else {
21103
- sourceYamlPath = fromPath;
21104
- const parentDir = dirname5(fromPath);
21105
- if (parentDir.endsWith(CONFIG_DIR)) {
21106
- sourceDir = dirname5(parentDir);
21107
- } else {
21108
- sourceDir = parentDir;
21109
- }
21110
- }
21111
- workspaceYamlContent = await readFile6(sourceYamlPath, "utf-8");
21112
- if (sourceDir) {
21169
+ workspaceYamlContent = fetchResult.content;
21113
21170
  const parsed2 = load(workspaceYamlContent);
21114
21171
  const workspace = parsed2?.workspace;
21115
21172
  if (workspace?.source) {
21116
21173
  const source = workspace.source;
21117
21174
  if (!isGitHubUrl(source) && !isAbsolute2(source)) {
21118
- workspace.source = resolve5(sourceDir, source);
21119
- workspaceYamlContent = dump(parsed2, { lineWidth: -1 });
21175
+ const parsedUrl = parseGitHubUrl(options2.from);
21176
+ if (parsedUrl) {
21177
+ const basePath = parsedUrl.subpath || "";
21178
+ const baseDir = basePath.replace(/\/?\.allagents\/workspace\.yaml$/, "").replace(/\/?workspace\.yaml$/, "");
21179
+ const sourcePath = baseDir ? `${baseDir}/${source}` : source;
21180
+ workspace.source = `https://github.com/${parsedUrl.owner}/${parsedUrl.repo}/tree/main/${sourcePath}`;
21181
+ workspaceYamlContent = dump(parsed2, { lineWidth: -1 });
21182
+ }
21183
+ }
21184
+ }
21185
+ console.log(`✓ Using workspace.yaml from: ${options2.from}`);
21186
+ } else {
21187
+ const fromPath = resolve5(options2.from);
21188
+ if (!existsSync7(fromPath)) {
21189
+ throw new Error(`Template not found: ${fromPath}`);
21190
+ }
21191
+ const { stat: stat2 } = await import("node:fs/promises");
21192
+ const fromStat = await stat2(fromPath);
21193
+ let sourceYamlPath;
21194
+ if (fromStat.isDirectory()) {
21195
+ const nestedPath = join8(fromPath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
21196
+ const rootPath = join8(fromPath, WORKSPACE_CONFIG_FILE);
21197
+ if (existsSync7(nestedPath)) {
21198
+ sourceYamlPath = nestedPath;
21199
+ sourceDir = fromPath;
21200
+ } else if (existsSync7(rootPath)) {
21201
+ sourceYamlPath = rootPath;
21202
+ sourceDir = fromPath;
21203
+ } else {
21204
+ throw new Error(`No workspace.yaml found in: ${fromPath}
21205
+ Expected at: ${nestedPath} or ${rootPath}`);
21206
+ }
21207
+ } else {
21208
+ sourceYamlPath = fromPath;
21209
+ const parentDir = dirname5(fromPath);
21210
+ if (parentDir.endsWith(CONFIG_DIR)) {
21211
+ sourceDir = dirname5(parentDir);
21212
+ } else {
21213
+ sourceDir = parentDir;
21214
+ }
21215
+ }
21216
+ workspaceYamlContent = await readFile6(sourceYamlPath, "utf-8");
21217
+ if (sourceDir) {
21218
+ const parsed2 = load(workspaceYamlContent);
21219
+ const workspace = parsed2?.workspace;
21220
+ if (workspace?.source) {
21221
+ const source = workspace.source;
21222
+ if (!isGitHubUrl(source) && !isAbsolute2(source)) {
21223
+ workspace.source = resolve5(sourceDir, source);
21224
+ workspaceYamlContent = dump(parsed2, { lineWidth: -1 });
21225
+ }
21120
21226
  }
21121
21227
  }
21228
+ console.log(`✓ Using workspace.yaml from: ${sourceYamlPath}`);
21122
21229
  }
21123
- console.log(`✓ Using workspace.yaml from: ${sourceYamlPath}`);
21124
21230
  } else {
21125
21231
  const defaultYamlPath = join8(defaultTemplatePath, CONFIG_DIR, WORKSPACE_CONFIG_FILE);
21126
21232
  if (!existsSync7(defaultYamlPath)) {
@@ -21747,6 +21853,9 @@ pluginCommand.command("validate <path>").description("Validate plugin structure
21747
21853
  });
21748
21854
 
21749
21855
  // src/cli/commands/update.ts
21856
+ import { readFileSync as readFileSync2 } from "node:fs";
21857
+ import { dirname as dirname6, join as join11 } from "node:path";
21858
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
21750
21859
  function detectPackageManagerFromPath(scriptPath) {
21751
21860
  if (scriptPath.includes(".bun")) {
21752
21861
  return "bun";
@@ -21756,12 +21865,12 @@ function detectPackageManagerFromPath(scriptPath) {
21756
21865
  function detectPackageManager() {
21757
21866
  return detectPackageManagerFromPath(process.argv[1] ?? "");
21758
21867
  }
21759
- async function getCurrentVersion() {
21868
+ function getCurrentVersion() {
21760
21869
  try {
21761
- const { createRequire: createRequire2 } = await import("node:module");
21762
- const require2 = createRequire2(import.meta.url);
21763
- const pkg = require2("../../../package.json");
21764
- return pkg.version;
21870
+ const __dirname2 = dirname6(fileURLToPath3(import.meta.url));
21871
+ const packageJsonPath = join11(__dirname2, "..", "package.json");
21872
+ const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
21873
+ return packageJson.version;
21765
21874
  } catch {
21766
21875
  return "unknown";
21767
21876
  }
@@ -21780,7 +21889,7 @@ var updateCommand = new Command("update").description("Update allagents to the l
21780
21889
  } else {
21781
21890
  packageManager = detectPackageManager();
21782
21891
  }
21783
- const currentVersion = await getCurrentVersion();
21892
+ const currentVersion = getCurrentVersion();
21784
21893
  console.log(`Current version: ${currentVersion}`);
21785
21894
  console.log(`Updating allagents using ${packageManager}...
21786
21895
  `);
@@ -21815,9 +21924,9 @@ Update complete.`);
21815
21924
  });
21816
21925
 
21817
21926
  // src/cli/index.ts
21818
- var __dirname2 = dirname6(fileURLToPath3(import.meta.url));
21819
- var packageJsonPath = join11(__dirname2, "..", "package.json");
21820
- var packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
21927
+ var __dirname2 = dirname7(fileURLToPath4(import.meta.url));
21928
+ var packageJsonPath = join12(__dirname2, "..", "package.json");
21929
+ var packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
21821
21930
  var program2 = new Command;
21822
21931
  program2.name("allagents").description("CLI tool for managing multi-repo AI agent workspaces with plugin synchronization").version(packageJson.version);
21823
21932
  program2.addCommand(workspaceCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "allagents",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "CLI tool for managing multi-repo AI agent workspaces with plugin synchronization",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,7 @@
14
14
  "docs:install": "bun install --cwd docs",
15
15
  "docs:build": "bun run --cwd docs build",
16
16
  "dev": "bun run src/cli/index.ts",
17
- "test": "bun test tests/unit/validators tests/unit/utils tests/unit/models && bun test tests/unit/core/marketplace.test.ts tests/unit/core/sync.test.ts tests/unit/core/transform-glob.test.ts && bun test tests/unit/core/plugin.test.ts",
17
+ "test": "bun test tests/unit/validators tests/unit/utils tests/unit/models && bun test tests/unit/core/marketplace.test.ts tests/unit/core/sync.test.ts tests/unit/core/transform-glob.test.ts tests/unit/core/github-fetch.test.ts && bun test tests/unit/core/plugin.test.ts",
18
18
  "test:watch": "bun test --watch",
19
19
  "test:coverage": "bun test --coverage",
20
20
  "test:integration": "bats tests/integration/*.bats",