binder-cli 1.1.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 (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +177 -0
  3. package/bin/binder.js +2 -0
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +119 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/context.d.ts +12 -0
  9. package/dist/commands/context.d.ts.map +1 -0
  10. package/dist/commands/context.js +105 -0
  11. package/dist/commands/context.js.map +1 -0
  12. package/dist/commands/init.d.ts +5 -0
  13. package/dist/commands/init.d.ts.map +1 -0
  14. package/dist/commands/init.js +119 -0
  15. package/dist/commands/init.js.map +1 -0
  16. package/dist/commands/pull.d.ts +5 -0
  17. package/dist/commands/pull.d.ts.map +1 -0
  18. package/dist/commands/pull.js +47 -0
  19. package/dist/commands/pull.js.map +1 -0
  20. package/dist/commands/status.d.ts +5 -0
  21. package/dist/commands/status.d.ts.map +1 -0
  22. package/dist/commands/status.js +116 -0
  23. package/dist/commands/status.js.map +1 -0
  24. package/dist/core/config/parser.d.ts +24 -0
  25. package/dist/core/config/parser.d.ts.map +1 -0
  26. package/dist/core/config/parser.js +116 -0
  27. package/dist/core/config/parser.js.map +1 -0
  28. package/dist/core/config/types.d.ts +142 -0
  29. package/dist/core/config/types.d.ts.map +1 -0
  30. package/dist/core/config/types.js +71 -0
  31. package/dist/core/config/types.js.map +1 -0
  32. package/dist/core/generator/context-map.d.ts +6 -0
  33. package/dist/core/generator/context-map.d.ts.map +1 -0
  34. package/dist/core/generator/context-map.js +124 -0
  35. package/dist/core/generator/context-map.js.map +1 -0
  36. package/dist/core/generator/injection-content.d.ts +9 -0
  37. package/dist/core/generator/injection-content.d.ts.map +1 -0
  38. package/dist/core/generator/injection-content.js +38 -0
  39. package/dist/core/generator/injection-content.js.map +1 -0
  40. package/dist/core/generator/rule-injector.d.ts +33 -0
  41. package/dist/core/generator/rule-injector.d.ts.map +1 -0
  42. package/dist/core/generator/rule-injector.js +208 -0
  43. package/dist/core/generator/rule-injector.js.map +1 -0
  44. package/dist/core/git/operations.d.ts +52 -0
  45. package/dist/core/git/operations.d.ts.map +1 -0
  46. package/dist/core/git/operations.js +221 -0
  47. package/dist/core/git/operations.js.map +1 -0
  48. package/dist/core/workspace/orchestrator.d.ts +28 -0
  49. package/dist/core/workspace/orchestrator.d.ts.map +1 -0
  50. package/dist/core/workspace/orchestrator.js +151 -0
  51. package/dist/core/workspace/orchestrator.js.map +1 -0
  52. package/dist/core/workspace/status.d.ts +45 -0
  53. package/dist/core/workspace/status.d.ts.map +1 -0
  54. package/dist/core/workspace/status.js +142 -0
  55. package/dist/core/workspace/status.js.map +1 -0
  56. package/dist/index.d.ts +9 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +19 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/utils/errors.d.ts +45 -0
  61. package/dist/utils/errors.d.ts.map +1 -0
  62. package/dist/utils/errors.js +83 -0
  63. package/dist/utils/errors.js.map +1 -0
  64. package/dist/utils/filesystem.d.ts +42 -0
  65. package/dist/utils/filesystem.d.ts.map +1 -0
  66. package/dist/utils/filesystem.js +152 -0
  67. package/dist/utils/filesystem.js.map +1 -0
  68. package/dist/utils/logger.d.ts +59 -0
  69. package/dist/utils/logger.d.ts.map +1 -0
  70. package/dist/utils/logger.js +118 -0
  71. package/dist/utils/logger.js.map +1 -0
  72. package/package.json +79 -0
  73. package/templates/binder.yaml.template +52 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Corrjo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # Binder
2
+
3
+ A lightweight CLI tool to orchestrate "Virtual Monoliths" from distributed repositories and define semantic boundaries for AI agents.
4
+
5
+ **[Read the docs →](https://corrjo.github.io/binder-website/)**
6
+
7
+ ## What is Binder?
8
+
9
+ Binder helps you work across multiple repositories by defining clear scopes and permissions for AI-assisted development. Instead of manually managing repo clones and context, define your workspace topology once and let Binder handle the rest.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install -g binder-cli
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```bash
20
+ # Initialize a new workspace
21
+ binder init
22
+
23
+ # Edit binder.yaml to add your repositories...
24
+
25
+ # Clone/checkout repositories
26
+ binder pull
27
+
28
+ # Generate AI context map
29
+ binder context
30
+
31
+ # Check workspace status
32
+ binder status
33
+ ```
34
+
35
+ ## Commands
36
+
37
+ ### `binder init`
38
+
39
+ Creates a new `binder.yaml` configuration file with a commented template.
40
+
41
+ ### `binder pull`
42
+
43
+ Clones missing repositories and checks out configured branches. This command is idempotent - safe to run multiple times.
44
+
45
+ ### `binder context`
46
+
47
+ Generates `CONTEXT_MAP.md` - an AI-readable file that describes your workspace topology, scopes, and permissions. Use this in your AI system prompts or `.cursorrules`.
48
+
49
+ ### `binder status`
50
+
51
+ Shows the current state of your workspace:
52
+ - Which repos exist vs missing
53
+ - Dirty repos (uncommitted changes)
54
+ - Branch mismatches
55
+ - Orphaned repos (on disk but not in config)
56
+
57
+ ## Configuration
58
+
59
+ ### binder.yaml
60
+
61
+ ```yaml
62
+ name: my-workspace
63
+
64
+ repos:
65
+ # OWNER - Full read/write access
66
+ - name: my-service
67
+ url: git@github.com:org/my-service.git
68
+ scope: owner
69
+ path: ./services/my-service # optional
70
+ branch: main # optional
71
+ notes: "Core service" # optional
72
+
73
+ # PLATFORM - Guest contributor
74
+ - name: shared-platform
75
+ url: https://github.com/org/platform.git
76
+ scope: platform
77
+ notes: "Shared infrastructure - minimal changes only"
78
+
79
+ # REFERENCE - Read only
80
+ - name: legacy-api
81
+ url: git@github.com:org/legacy-api.git
82
+ scope: reference
83
+ depth: 1 # shallow clone
84
+ notes: "Reference only - historical context"
85
+ ```
86
+
87
+ ### Repository Options
88
+
89
+ | Option | Required | Description |
90
+ |--------|----------|-------------|
91
+ | `name` | Yes | Repository name (used for display and default path) |
92
+ | `url` | Yes | Git URL (HTTPS or SSH) |
93
+ | `scope` | Yes | Access level: `owner`, `platform`, or `reference` |
94
+ | `path` | No | Local path (defaults to `./repos/{name}`) |
95
+ | `branch` | No | Branch to checkout |
96
+ | `notes` | No | Context notes for AI agents |
97
+ | `depth` | No | Shallow clone depth |
98
+
99
+ ## Core Concepts
100
+
101
+ ### Scopes
102
+
103
+ - **OWNER** (green) - Full read/write access. Your primary workspace. AI can refactor freely.
104
+ - **PLATFORM** (yellow) - Guest contributor. Read fully, edit conservatively. AI should follow existing patterns.
105
+ - **REFERENCE** (red) - Read-only. For validation and historical context. AI should not suggest modifications.
106
+
107
+ ### CONTEXT_MAP.md
108
+
109
+ The generated context map tells AI agents:
110
+ - Which repositories exist in your workspace
111
+ - What scope/permissions apply to each
112
+ - Specific instructions per scope
113
+ - Any notes you've provided
114
+
115
+ Example output:
116
+
117
+ ```markdown
118
+ # WORKSPACE TOPOLOGY & SCOPE DEFINITIONS
119
+
120
+ **Workspace:** my-workspace
121
+
122
+ ## 🟢 SCOPE: OWNER (Full Authority)
123
+
124
+ **Repositories:**
125
+ - `my-service` at `./services/my-service`
126
+
127
+ **Permissions:** Full read/write access
128
+ **Instructions:**
129
+ - You are responsible for architecture, implementation, and refactoring.
130
+ - Make changes freely to improve code quality and functionality.
131
+
132
+ ## 🟡 SCOPE: PLATFORM (Restricted Contributor)
133
+
134
+ **Repositories:**
135
+ - `shared-platform` at `./repos/shared-platform`
136
+ - *Shared infrastructure - minimal changes only*
137
+
138
+ **Permissions:** Limited write access
139
+ **Instructions:**
140
+ - Only make minimal changes when necessary to support OWNER scope.
141
+ - Strictly adhere to existing patterns and conventions.
142
+ ```
143
+
144
+ ## Philosophy
145
+
146
+ **Topology vs. Task** - Binder separates workspace definition from feature implementation:
147
+
148
+ - **Binder's job**: "Here are the repos. You own these, you're a guest here, read-only there."
149
+ - **Your job**: "We are building Feature X. Please implement Y."
150
+
151
+ This separation allows AI agents to understand their permissions and responsibilities across your distributed codebase without manual context management.
152
+
153
+ ## Development
154
+
155
+ ```bash
156
+ # Install dependencies
157
+ npm install
158
+
159
+ # Run in development mode
160
+ npm run dev -- init
161
+
162
+ # Run tests
163
+ npm test
164
+
165
+ # Lint and format
166
+ npm run lint:fix
167
+
168
+ # Build
169
+ npm run build
170
+
171
+ # Link globally for testing
172
+ npm link
173
+ ```
174
+
175
+ ## License
176
+
177
+ MIT
package/bin/binder.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ require('../dist/cli.js');
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ const commander_1 = require("commander");
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const init_1 = require("./commands/init");
41
+ const pull_1 = require("./commands/pull");
42
+ const context_1 = require("./commands/context");
43
+ const status_1 = require("./commands/status");
44
+ const logger_1 = require("./utils/logger");
45
+ // Read version from package.json
46
+ const packageJsonPath = path.join(__dirname, '../package.json');
47
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
48
+ const program = new commander_1.Command();
49
+ program
50
+ .name('binder')
51
+ .description('Orchestrate Virtual Monoliths from distributed repositories')
52
+ .version(packageJson.version)
53
+ .option('-v, --verbose', 'Enable verbose output')
54
+ .hook('preAction', (thisCommand) => {
55
+ const opts = thisCommand.opts();
56
+ if (opts.verbose) {
57
+ (0, logger_1.setVerbose)(true);
58
+ }
59
+ });
60
+ program
61
+ .command('init')
62
+ .description('Create a new binder.yaml configuration file')
63
+ .action(async () => {
64
+ try {
65
+ await (0, init_1.initCommand)();
66
+ }
67
+ catch (error) {
68
+ console.error('Unexpected error while running "init" command:', error);
69
+ process.exitCode = 1;
70
+ }
71
+ });
72
+ program
73
+ .command('pull')
74
+ .description('Clone missing repositories and checkout configured branches')
75
+ .action(async () => {
76
+ try {
77
+ await (0, pull_1.pullCommand)();
78
+ }
79
+ catch (error) {
80
+ console.error('Unexpected error while running "pull" command:', error);
81
+ process.exitCode = 1;
82
+ }
83
+ });
84
+ // Helper to collect multiple --file options into an array
85
+ function collect(value, previous) {
86
+ return previous.concat([value]);
87
+ }
88
+ program
89
+ .command('context')
90
+ .description('Generate CONTEXT_MAP.md for AI agents')
91
+ .option('--claude', 'Inject instructions into CLAUDE.md')
92
+ .option('--cursor', 'Inject instructions into .cursorrules')
93
+ .option('--roo', 'Inject instructions into .roo/rules.md')
94
+ .option('--agents', 'Inject instructions into agents.md')
95
+ .option('--file <path>', 'Inject into a custom file (can be used multiple times)', collect, [])
96
+ .action(async (options) => {
97
+ try {
98
+ await (0, context_1.contextCommand)(options);
99
+ }
100
+ catch (error) {
101
+ console.error('Unexpected error while running "context" command:', error);
102
+ process.exitCode = 1;
103
+ }
104
+ });
105
+ program
106
+ .command('status')
107
+ .description('Show workspace status (repos, branches, dirty state)')
108
+ .action(async () => {
109
+ try {
110
+ await (0, status_1.statusCommand)();
111
+ }
112
+ catch (error) {
113
+ console.error('Unexpected error while running "status" command:', error);
114
+ process.exitCode = 1;
115
+ }
116
+ });
117
+ // Parse arguments
118
+ program.parse();
119
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface ContextCommandOptions {
2
+ claude?: boolean;
3
+ cursor?: boolean;
4
+ roo?: boolean;
5
+ agents?: boolean;
6
+ file?: string[];
7
+ }
8
+ /**
9
+ * Generate CONTEXT_MAP.md from binder.yaml
10
+ */
11
+ export declare function contextCommand(options?: ContextCommandOptions): Promise<void>;
12
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CA4DvF"}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.contextCommand = contextCommand;
37
+ const path = __importStar(require("path"));
38
+ const parser_1 = require("../core/config/parser");
39
+ const context_map_1 = require("../core/generator/context-map");
40
+ const rule_injector_1 = require("../core/generator/rule-injector");
41
+ const filesystem_1 = require("../utils/filesystem");
42
+ const logger_1 = require("../utils/logger");
43
+ const CONTEXT_MAP_FILENAME = 'CONTEXT_MAP.md';
44
+ /**
45
+ * Generate CONTEXT_MAP.md from binder.yaml
46
+ */
47
+ async function contextCommand(options = {}) {
48
+ // Load configuration
49
+ let config;
50
+ try {
51
+ config = await (0, parser_1.loadConfig)();
52
+ }
53
+ catch (err) {
54
+ if (err instanceof parser_1.ConfigError) {
55
+ (0, logger_1.error)(err.message);
56
+ (0, logger_1.info)('Run `binder init` to create a configuration file.');
57
+ }
58
+ else {
59
+ (0, logger_1.error)('Failed to load configuration');
60
+ }
61
+ process.exit(1);
62
+ }
63
+ // Generate context map content
64
+ const content = (0, context_map_1.generateContextMap)(config);
65
+ // Write to file
66
+ const outputPath = path.join(process.cwd(), CONTEXT_MAP_FILENAME);
67
+ try {
68
+ await (0, filesystem_1.writeFile)(outputPath, content);
69
+ (0, logger_1.success)(`Generated ${CONTEXT_MAP_FILENAME}`);
70
+ }
71
+ catch (err) {
72
+ const message = err instanceof Error ? err.message : 'Unknown error';
73
+ (0, logger_1.error)(`Failed to write ${CONTEXT_MAP_FILENAME}: ${message}`);
74
+ process.exit(1);
75
+ }
76
+ // Check if any injection flags were provided
77
+ const hasInjectionFlags = options.claude ||
78
+ options.cursor ||
79
+ options.roo ||
80
+ options.agents ||
81
+ (options.file && options.file.length > 0);
82
+ if (hasInjectionFlags) {
83
+ (0, logger_1.newline)();
84
+ (0, logger_1.info)('Injecting Binder instructions into AI rule files...');
85
+ (0, logger_1.newline)();
86
+ const targets = {
87
+ claude: options.claude,
88
+ cursor: options.cursor,
89
+ roo: options.roo,
90
+ agents: options.agents,
91
+ file: options.file,
92
+ };
93
+ await (0, rule_injector_1.injectIntoRuleFiles)({
94
+ basePath: process.cwd(),
95
+ contextMapPath: CONTEXT_MAP_FILENAME,
96
+ targets,
97
+ });
98
+ }
99
+ else {
100
+ (0, logger_1.newline)();
101
+ (0, logger_1.info)('This file describes your workspace topology for AI agents.');
102
+ (0, logger_1.info)('Use --claude, --cursor, --roo, --agents, or --file to inject instructions.');
103
+ }
104
+ }
105
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,wCA4DC;AAhFD,2CAA6B;AAC7B,kDAAgE;AAChE,+DAAmE;AACnE,mEAAwF;AACxF,oDAAgD;AAChD,4CAAgE;AAEhE,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAU9C;;GAEG;AACI,KAAK,UAAU,cAAc,CAAC,UAAiC,EAAE;IACtE,qBAAqB;IACrB,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAA,mBAAU,GAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,oBAAW,EAAE,CAAC;YAC/B,IAAA,cAAK,EAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnB,IAAA,aAAI,EAAC,mDAAmD,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,IAAA,cAAK,EAAC,8BAA8B,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,+BAA+B;IAC/B,MAAM,OAAO,GAAG,IAAA,gCAAkB,EAAC,MAAM,CAAC,CAAC;IAE3C,gBAAgB;IAChB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC;IAClE,IAAI,CAAC;QACH,MAAM,IAAA,sBAAS,EAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACrC,IAAA,gBAAO,EAAC,aAAa,oBAAoB,EAAE,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,IAAA,cAAK,EAAC,mBAAmB,oBAAoB,KAAK,OAAO,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,6CAA6C;IAC7C,MAAM,iBAAiB,GACrB,OAAO,CAAC,MAAM;QACd,OAAO,CAAC,MAAM;QACd,OAAO,CAAC,GAAG;QACX,OAAO,CAAC,MAAM;QACd,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE5C,IAAI,iBAAiB,EAAE,CAAC;QACtB,IAAA,gBAAO,GAAE,CAAC;QACV,IAAA,aAAI,EAAC,qDAAqD,CAAC,CAAC;QAC5D,IAAA,gBAAO,GAAE,CAAC;QAEV,MAAM,OAAO,GAAqB;YAChC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC;QAEF,MAAM,IAAA,mCAAmB,EAAC;YACxB,QAAQ,EAAE,OAAO,CAAC,GAAG,EAAE;YACvB,cAAc,EAAE,oBAAoB;YACpC,OAAO;SACR,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,IAAA,gBAAO,GAAE,CAAC;QACV,IAAA,aAAI,EAAC,4DAA4D,CAAC,CAAC;QACnE,IAAA,aAAI,EAAC,4EAA4E,CAAC,CAAC;IACrF,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Initialize a new binder.yaml configuration file
3
+ */
4
+ export declare function initCommand(): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoCjD"}
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.initCommand = initCommand;
37
+ const path = __importStar(require("path"));
38
+ const fs = __importStar(require("fs-extra"));
39
+ const logger_1 = require("../utils/logger");
40
+ const CONFIG_FILENAME = 'binder.yaml';
41
+ /**
42
+ * Initialize a new binder.yaml configuration file
43
+ */
44
+ async function initCommand() {
45
+ const configPath = path.join(process.cwd(), CONFIG_FILENAME);
46
+ // Check if config already exists
47
+ if (await fs.pathExists(configPath)) {
48
+ (0, logger_1.warning)(`${CONFIG_FILENAME} already exists in this directory.`);
49
+ (0, logger_1.info)('Edit the existing file or delete it to start fresh.');
50
+ return;
51
+ }
52
+ // Read the template
53
+ const templatePath = path.join(__dirname, '../../templates/binder.yaml.template');
54
+ let template;
55
+ try {
56
+ template = await fs.readFile(templatePath, 'utf-8');
57
+ }
58
+ catch {
59
+ // Fallback if template file is not found (e.g., in development)
60
+ template = getDefaultTemplate();
61
+ }
62
+ // Write the config file
63
+ try {
64
+ await fs.writeFile(configPath, template, 'utf-8');
65
+ (0, logger_1.success)(`Created ${CONFIG_FILENAME}`);
66
+ (0, logger_1.info)('');
67
+ (0, logger_1.info)('Next steps:');
68
+ (0, logger_1.info)(' 1. Edit binder.yaml to add your repositories');
69
+ (0, logger_1.info)(' 2. Run `binder pull` to clone/checkout repositories');
70
+ (0, logger_1.info)(' 3. Run `binder context` to generate CONTEXT_MAP.md');
71
+ (0, logger_1.info)(' 4. Run `binder status` to see workspace state');
72
+ }
73
+ catch (err) {
74
+ const message = err instanceof Error ? err.message : 'Unknown error';
75
+ (0, logger_1.error)(`Failed to create ${CONFIG_FILENAME}: ${message}`);
76
+ process.exit(1);
77
+ }
78
+ }
79
+ /**
80
+ * Default template content (fallback)
81
+ */
82
+ function getDefaultTemplate() {
83
+ return `# ============================================================================
84
+ # Binder Configuration
85
+ # ============================================================================
86
+ # This file defines your workspace topology and repository scopes.
87
+ # Run 'binder pull' to clone/checkout repositories.
88
+ # Run 'binder context' to generate CONTEXT_MAP.md for AI agents.
89
+ # Run 'binder status' to see workspace state.
90
+ # ============================================================================
91
+
92
+ # Workspace name (used in CONTEXT_MAP.md header)
93
+ name: my-workspace
94
+
95
+ # Repository definitions
96
+ repos:
97
+ # OWNER SCOPE - Full Authority
98
+ - name: my-service
99
+ url: git@github.com:org/my-service.git
100
+ scope: owner
101
+ # path: ./services/my-service # Optional: local path
102
+ # branch: main # Optional: branch to checkout
103
+ # notes: "Core service" # Optional: context for AI agents
104
+
105
+ # PLATFORM SCOPE - Restricted Contributor
106
+ # - name: shared-platform
107
+ # url: https://github.com/org/platform.git
108
+ # scope: platform
109
+ # notes: "Shared infrastructure - minimal changes only"
110
+
111
+ # REFERENCE SCOPE - Read Only
112
+ # - name: legacy-api
113
+ # url: git@github.com:org/legacy-api.git
114
+ # scope: reference
115
+ # depth: 1 # Optional: shallow clone
116
+ # notes: "Reference only - historical context"
117
+ `;
118
+ }
119
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,kCAoCC;AA7CD,2CAA6B;AAC7B,6CAA+B;AAC/B,4CAAgE;AAEhE,MAAM,eAAe,GAAG,aAAa,CAAC;AAEtC;;GAEG;AACI,KAAK,UAAU,WAAW;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;IAE7D,iCAAiC;IACjC,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACpC,IAAA,gBAAO,EAAC,GAAG,eAAe,oCAAoC,CAAC,CAAC;QAChE,IAAA,aAAI,EAAC,qDAAqD,CAAC,CAAC;QAC5D,OAAO;IACT,CAAC;IAED,oBAAoB;IACpB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,sCAAsC,CAAC,CAAC;IAClF,IAAI,QAAgB,CAAC;IAErB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;QAChE,QAAQ,GAAG,kBAAkB,EAAE,CAAC;IAClC,CAAC;IAED,wBAAwB;IACxB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,IAAA,gBAAO,EAAC,WAAW,eAAe,EAAE,CAAC,CAAC;QACtC,IAAA,aAAI,EAAC,EAAE,CAAC,CAAC;QACT,IAAA,aAAI,EAAC,aAAa,CAAC,CAAC;QACpB,IAAA,aAAI,EAAC,gDAAgD,CAAC,CAAC;QACvD,IAAA,aAAI,EAAC,uDAAuD,CAAC,CAAC;QAC9D,IAAA,aAAI,EAAC,sDAAsD,CAAC,CAAC;QAC7D,IAAA,aAAI,EAAC,iDAAiD,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACrE,IAAA,cAAK,EAAC,oBAAoB,eAAe,KAAK,OAAO,EAAE,CAAC,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB;IACzB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCR,CAAC;AACF,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Pull (clone/checkout) repositories according to binder.yaml
3
+ */
4
+ export declare function pullCommand(): Promise<void>;
5
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAsCjD"}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pullCommand = pullCommand;
4
+ const parser_1 = require("../core/config/parser");
5
+ const orchestrator_1 = require("../core/workspace/orchestrator");
6
+ const logger_1 = require("../utils/logger");
7
+ /**
8
+ * Pull (clone/checkout) repositories according to binder.yaml
9
+ */
10
+ async function pullCommand() {
11
+ // Load configuration
12
+ let config;
13
+ try {
14
+ config = await (0, parser_1.loadConfig)();
15
+ }
16
+ catch (err) {
17
+ if (err instanceof parser_1.ConfigError) {
18
+ (0, logger_1.error)(err.message);
19
+ (0, logger_1.info)('Run `binder init` to create a configuration file.');
20
+ }
21
+ else {
22
+ (0, logger_1.error)('Failed to load configuration');
23
+ }
24
+ process.exit(1);
25
+ }
26
+ (0, logger_1.header)(`Pulling repositories for "${config.name}"`);
27
+ // Orchestrate repositories
28
+ const result = await (0, orchestrator_1.orchestrate)(config);
29
+ // Summary
30
+ (0, logger_1.newline)();
31
+ if (result.success) {
32
+ (0, logger_1.success)('Orchestration complete!');
33
+ }
34
+ else {
35
+ (0, logger_1.error)('Orchestration completed with errors.');
36
+ }
37
+ (0, logger_1.info)(` Cloned: ${result.cloned}`);
38
+ (0, logger_1.info)(` Checked out: ${result.checkedOut}`);
39
+ (0, logger_1.info)(` Up to date: ${result.skipped}`);
40
+ if (result.errors > 0) {
41
+ (0, logger_1.info)(` Errors: ${result.errors}`);
42
+ }
43
+ if (!result.success) {
44
+ process.exit(1);
45
+ }
46
+ }
47
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":";;AAOA,kCAsCC;AA7CD,kDAAgE;AAChE,iEAA6D;AAC7D,4CAAwE;AAExE;;GAEG;AACI,KAAK,UAAU,WAAW;IAC/B,qBAAqB;IACrB,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,IAAA,mBAAU,GAAE,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,oBAAW,EAAE,CAAC;YAC/B,IAAA,cAAK,EAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACnB,IAAA,aAAI,EAAC,mDAAmD,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,IAAA,cAAK,EAAC,8BAA8B,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAA,eAAM,EAAC,6BAA6B,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAEpD,2BAA2B;IAC3B,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAW,EAAC,MAAM,CAAC,CAAC;IAEzC,UAAU;IACV,IAAA,gBAAO,GAAE,CAAC;IACV,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,IAAA,gBAAO,EAAC,yBAAyB,CAAC,CAAC;IACrC,CAAC;SAAM,CAAC;QACN,IAAA,cAAK,EAAC,sCAAsC,CAAC,CAAC;IAChD,CAAC;IAED,IAAA,aAAI,EAAC,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,IAAA,aAAI,EAAC,kBAAkB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5C,IAAA,aAAI,EAAC,iBAAiB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,IAAA,aAAI,EAAC,aAAa,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Display workspace status
3
+ */
4
+ export declare function statusCommand(): Promise<void>;
5
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAgDA;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAsEnD"}