@factory/cli 0.1.2-dev.7 → 0.56.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.
- package/README.md +27 -258
- package/bin/droid +112 -0
- package/install.js +314 -0
- package/package.json +38 -95
- package/platform.js +166 -0
- package/bundle/droid.js +0 -1549
- package/bundle/index.js.map +0 -2584
package/README.md
CHANGED
|
@@ -1,278 +1,47 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @factory/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> The power of [Factory](https://factory.ai) in your terminal
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
2. **Headless commands** – traditional `droid headless <command>` sub-commands powered by Commander
|
|
7
|
-
|
|
8
|
-
The entry-point (`src/index.ts`) detects how it was invoked and chooses the right mode automatically.
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## 1. Overview of the Hybrid Architecture
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
src/
|
|
16
|
-
├── index.ts # Hybrid entry – mode detection
|
|
17
|
-
│
|
|
18
|
-
├── app.tsx # React/Ink TUI (interactive mode)
|
|
19
|
-
│
|
|
20
|
-
└── commands/ # Commander commands (headless mode)
|
|
21
|
-
├── droid.ts
|
|
22
|
-
└── login.ts
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
• **No positional args** ➜ Interactive TUI
|
|
26
|
-
• **`headless` subcommand** ➜ Headless mode
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## 2 · Local Development
|
|
31
|
-
|
|
32
|
-
All dev tasks are exposed as **npm scripts** – never run compiled `.js` files directly.
|
|
33
|
-
|
|
34
|
-
| Purpose | Command |
|
|
35
|
-
| ------------------------- | ------------------- |
|
|
36
|
-
| Start CLI (auto mode) | `npm start` |
|
|
37
|
-
| Start with Node inspector | `npm run debug` |
|
|
38
|
-
| Lint source | `npm run lint` |
|
|
39
|
-
| Type-check | `npm run typecheck` |
|
|
40
|
-
| Run tests | `npm test` |
|
|
41
|
-
| Build JS into `dist/` | `npm run build` |
|
|
42
|
-
| Produce executable bundle | `npm run bundle` |
|
|
43
|
-
| Clean build artifacts | `npm run clean` |
|
|
44
|
-
|
|
45
|
-
The `start`/`debug` scripts use **tsx** so you can edit TypeScript and restart instantly.
|
|
46
|
-
|
|
47
|
-
---
|
|
48
|
-
|
|
49
|
-
## 3 · Testing Both Modes Locally
|
|
50
|
-
|
|
51
|
-
### Interactive TUI
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
# Launch interactive UI
|
|
55
|
-
npm start
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
You'll see a colourful Ink interface; quit with `Ctrl-C`.
|
|
59
|
-
|
|
60
|
-
### Running in VSCode
|
|
61
|
-
|
|
62
|
-
Factory CLI can also be run inside VSCode using the Factory extension:
|
|
63
|
-
|
|
64
|
-
1. First, install the Factory VSCode extension (see [VSCode Extension README](../factory-vscode-extension/README.md) for installation instructions)
|
|
65
|
-
2. Click the **Run Factory** button (🤖) in the editor toolbar to launch Factory CLI in a dedicated terminal
|
|
66
|
-
3. The extension provides full VSCode context (open files, selections, diagnostics) to Factory via MCP
|
|
67
|
-
|
|
68
|
-
### Headless Commands
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
# Show global help
|
|
72
|
-
npm start -- --help
|
|
73
|
-
|
|
74
|
-
# Show headless subcommands
|
|
75
|
-
npm start -- headless --help
|
|
76
|
-
|
|
77
|
-
# Run login interactively (headless)
|
|
78
|
-
npm start -- headless login
|
|
79
|
-
|
|
80
|
-
# Send message to a droid
|
|
81
|
-
npm start -- headless droid "Hello, Droid!" --session-id <sessionId>
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
The extra `--` after `npm start` passes subsequent flags to the CLI.
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## 4 · Development vs Production
|
|
89
|
-
|
|
90
|
-
| Phase | Command(s) | Result |
|
|
91
|
-
| ----------- | ------------------------------------ | ---------------------------------------------- |
|
|
92
|
-
| **Dev** | `npm start` / `npm run debug` | Runs from TS sources with tsx, fast reload. |
|
|
93
|
-
| **Build** | `npm run build` | Compiles TS → `dist/`. |
|
|
94
|
-
| **Bundle** | `npm run bundle` (calls `build`) | Generates single executable `bundle/droid.js`. |
|
|
95
|
-
| **Publish** | `npm publish` (bundled in `prepare`) | Users install `droid` binary from npm. |
|
|
96
|
-
|
|
97
|
-
During CI the `prepare` script produces the bundle automatically.
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## 5 · Examples
|
|
102
|
-
|
|
103
|
-
### Headless examples
|
|
5
|
+
## Installation
|
|
104
6
|
|
|
105
7
|
```bash
|
|
106
|
-
|
|
107
|
-
droid headless status
|
|
108
|
-
|
|
109
|
-
# Authenticate (opens browser)
|
|
110
|
-
droid headless login
|
|
111
|
-
|
|
112
|
-
# Talk to Droid
|
|
113
|
-
droid headless droid "Hello" --session-id dOLpXUI8ux6YdZrg3kCs
|
|
8
|
+
npm install -g @factory/cli
|
|
114
9
|
```
|
|
115
10
|
|
|
116
|
-
|
|
11
|
+
Then navigate to your project and start the droid CLI:
|
|
117
12
|
|
|
118
13
|
```bash
|
|
119
|
-
|
|
14
|
+
cd /path/to/your/project
|
|
120
15
|
droid
|
|
121
16
|
```
|
|
122
17
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
## 6 · Testing the Production **`droid`** Command
|
|
126
|
-
|
|
127
|
-
Sometimes you need to test the **exact binary** users will get from `npm
|
|
128
|
-
install -g factory-cli`.
|
|
129
|
-
Follow this workflow:
|
|
130
|
-
|
|
131
|
-
```bash
|
|
132
|
-
# 1. Build optimised bundle (also compiles TS → JS)
|
|
133
|
-
npm run bundle
|
|
134
|
-
|
|
135
|
-
# 2. Link globally so `droid` is on your PATH
|
|
136
|
-
npm link
|
|
137
|
-
|
|
138
|
-
# 3. Use it anywhere
|
|
139
|
-
droid --help
|
|
140
|
-
droid headless status
|
|
141
|
-
droid headless droid "Hello" --session-id <sessionId>
|
|
142
|
-
|
|
143
|
-
# 4. (Optional) Un-link when finished
|
|
144
|
-
npm unlink -g factory-cli
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
| Situation | Command to use |
|
|
148
|
-
| --------------------------- | --------------------------------------------------------- |
|
|
149
|
-
| Fast iteration / TypeScript | `npm start -- <args>` |
|
|
150
|
-
| Debug with inspector | `npm run debug -- <args>` |
|
|
151
|
-
| Validate production bundle | `npm run bundle && npm link` then `droid headless <args>` |
|
|
152
|
-
|
|
153
|
-
ℹ️ _Tip:_ The extra `--` after `npm start` or `npm run debug` passes the
|
|
154
|
-
remaining flags **directly to the CLI**.
|
|
155
|
-
|
|
156
|
-
---
|
|
157
|
-
|
|
158
|
-
## 7 · ESM & Imports
|
|
159
|
-
|
|
160
|
-
The package is `"type": "module"`; all runtime imports use `.js` extensions even though the source is TypeScript. The build pipeline rewrites them automatically.
|
|
161
|
-
|
|
162
|
-
---
|
|
163
|
-
|
|
164
|
-
## 8 · Troubleshooting
|
|
165
|
-
|
|
166
|
-
| Problem | Fix |
|
|
167
|
-
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
168
|
-
| `EACCES` when running `droid` | Ensure the bundle is executable (`chmod +x bundle/droid.js`). `npm run bundle` handles this automatically. |
|
|
169
|
-
| `module not found` after rename | Run `npm run clean && npm run bundle` to rebuild from scratch. |
|
|
170
|
-
| Global command still points to old code | Run `npm unlink -g factory-cli && npm link` to refresh the symlink. |
|
|
171
|
-
|
|
172
|
-
---
|
|
173
|
-
|
|
174
|
-
## 9 · Logging
|
|
175
|
-
|
|
176
|
-
Factory CLI has two different logging behaviors depending on the execution mode:
|
|
177
|
-
|
|
178
|
-
### Interactive Mode Logging
|
|
179
|
-
|
|
180
|
-
When running in **interactive TUI mode** (`droid` with no arguments), all logging output is redirected to files to avoid interfering with the clean React/Ink interface:
|
|
181
|
-
|
|
182
|
-
- **Log Directory**: `~/.factory/logs/`
|
|
183
|
-
- **Log Files**: `droid-log-<timestamp>.log` (e.g., `droid-log-2025-01-15T10-30-45-123Z.log`)
|
|
184
|
-
- **Content**: All `logInfo`, `logException`, and `logWarn` calls are written to the timestamped log file
|
|
185
|
-
- **Format**: `[timestamp] LEVEL: message | Context: {...}`
|
|
186
|
-
|
|
187
|
-
**Example log file location:**
|
|
188
|
-
|
|
189
|
-
```bash
|
|
190
|
-
~/.factory/logs/droid-log-2025-01-15T10-30-45-123Z.log
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
**Example log entry:**
|
|
194
|
-
|
|
195
|
-
```
|
|
196
|
-
[2025-01-15T10:30:45.123Z] INFO: User started interactive session
|
|
197
|
-
[2025-01-15T10:30:47.456Z] ERROR: Failed to initialize MCP client: Connection refused | Context: {"retry": 1}
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### Headless Mode Logging
|
|
201
|
-
|
|
202
|
-
When running **headless commands** (`droid headless <command>`), logging follows standard console output patterns:
|
|
203
|
-
|
|
204
|
-
- **Log Output**: Directly to stdout/stderr using the standard `@factory/logging` package
|
|
205
|
-
- **Integration**: Works with existing telemetry, Sentry, and monitoring systems
|
|
206
|
-
- **Format**: Standard Factory logging format with metadata support
|
|
207
|
-
|
|
208
|
-
### Accessing Logs
|
|
209
|
-
|
|
210
|
-
**Interactive Mode Logs:**
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
# View the most recent log file
|
|
214
|
-
ls -la ~/.factory/logs/
|
|
215
|
-
|
|
216
|
-
# Tail the logs in real-time (find the most recent file)
|
|
217
|
-
tail -f ~/.factory/logs/droid-log-*.log
|
|
218
|
-
|
|
219
|
-
# View logs from a specific session
|
|
220
|
-
cat ~/.factory/logs/droid-log-2025-01-15T10-30-45-123Z.log
|
|
221
|
-
```
|
|
18
|
+
You're now connected to Factory's development agent from your terminal.
|
|
222
19
|
|
|
223
|
-
**
|
|
20
|
+
> **Quick tip:** Press `!` to toggle bash mode and run shell commands directly without AI interpretation. Press `Esc` to return to normal mode.
|
|
224
21
|
|
|
225
|
-
|
|
226
|
-
# Logs appear directly in terminal output
|
|
227
|
-
droid headless droid "test message" --session-id abc123
|
|
22
|
+
## What droid brings to your workflow
|
|
228
23
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
24
|
+
- **End-to-end feature development**: From planning to implementation to testing - droid handles the complete development lifecycle while keeping you in control through transparent review workflows.
|
|
25
|
+
- **Deep codebase understanding**: Leverages your organization's shared knowledge across repositories, documentation, and issue tracking to provide contextually aware assistance that improves over time.
|
|
26
|
+
- **Engineering system integration**: Connects directly to your existing tools — with native integrations to Jira, Notion, Slack, and many more tools — so development work stays synchronized with your team's processes.
|
|
27
|
+
- **Production-ready automation**: Deploy the same workflows locally during development or in CI/CD pipelines, with enterprise security and compliance built-in from day one.
|
|
232
28
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
Interactive mode creates a new log file for each session. To manage disk space:
|
|
236
|
-
|
|
237
|
-
```bash
|
|
238
|
-
# Remove logs older than 7 days
|
|
239
|
-
find ~/.factory/logs -name "droid-log-*.log" -mtime +7 -delete
|
|
240
|
-
|
|
241
|
-
# View total log directory size
|
|
242
|
-
du -sh ~/.factory/logs
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## 10 · Tool Registry & Executors Design
|
|
248
|
-
|
|
249
|
-
### 🔄 What Changed
|
|
250
|
-
|
|
251
|
-
**After:** Dynamic mapping automatically discovers tools from TUI registry
|
|
252
|
-
|
|
253
|
-
```javascript
|
|
254
|
-
// Tools are automatically discovered from TUI registry
|
|
255
|
-
const toolMapping = buildToolMapping();
|
|
256
|
-
```
|
|
29
|
+
## Why teams choose Factory
|
|
257
30
|
|
|
258
|
-
|
|
31
|
+
- **Built for enterprise**: On-premise deployment options, SOC-2 compliance, and air-gapped environments.
|
|
32
|
+
- **Your tools, enhanced**: Works within your existing terminal, IDE, and development environment.
|
|
33
|
+
- **Transparent and controllable**: Every decision droid makes is visible and reviewable. You maintain full oversight of code changes with our native diff viewer and approval workflows.
|
|
34
|
+
- **Model flexibility**: Not locked into a single AI provider. Factory allows you to route tasks to the best model for each job while maintaining consistent behavior and memory across your organization.
|
|
259
35
|
|
|
260
|
-
|
|
261
|
-
2. **Register in TUI registry** in `src/tools/tui.ts`:
|
|
262
|
-
```javascript
|
|
263
|
-
getTUIToolRegistry().register({
|
|
264
|
-
tool: myNewCliTool, // from @factory/droid-core/tools/definitions
|
|
265
|
-
executorFactory: () => new MyNewExecutor(),
|
|
266
|
-
});
|
|
267
|
-
```
|
|
268
|
-
3. **That's it!** Tool is automatically available in `executeTool()` using its `llmId`
|
|
36
|
+
## Documentation
|
|
269
37
|
|
|
270
|
-
|
|
38
|
+
- [Quickstart Guide](https://docs.factory.ai/cli/getting-started/quickstart)
|
|
39
|
+
- [Common Use Cases](https://docs.factory.ai/cli/getting-started/common-use-cases)
|
|
40
|
+
- [IDE Integration](https://docs.factory.ai/cli/configuration/ide-integrations)
|
|
41
|
+
- [Configuration](https://docs.factory.ai/cli/configuration/settings)
|
|
42
|
+
- [AGENTS.md Guide](https://docs.factory.ai/cli/configuration/agents-md)
|
|
43
|
+
- [CLI Reference](https://docs.factory.ai/reference/cli-reference)
|
|
271
44
|
|
|
272
|
-
##
|
|
45
|
+
## Full Documentation Index
|
|
273
46
|
|
|
274
|
-
|
|
275
|
-
2. `cd apps/factory-cli`
|
|
276
|
-
3. Implement feature / fix
|
|
277
|
-
4. Ensure `npm run lint && npm run typecheck && npm test` pass
|
|
278
|
-
5. Commit & open PR 🚀
|
|
47
|
+
Fetch the complete documentation index at: https://docs.factory.ai/llms.txt
|
package/bin/droid
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* JavaScript shim for the droid command.
|
|
5
|
+
*
|
|
6
|
+
* This shim finds and executes the appropriate platform-specific binary.
|
|
7
|
+
* For x64 platforms, it detects AVX2 support and selects the appropriate
|
|
8
|
+
* binary (regular or baseline for older CPUs).
|
|
9
|
+
*
|
|
10
|
+
* In optimized installations, this file is replaced with a hard link to
|
|
11
|
+
* the actual binary, avoiding Node.js startup overhead.
|
|
12
|
+
*
|
|
13
|
+
* Based on esbuild's approach: https://github.com/evanw/esbuild/pull/1621
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const child_process = require('child_process');
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
PLATFORM_PACKAGES,
|
|
22
|
+
getPlatformKey,
|
|
23
|
+
getBinaryName,
|
|
24
|
+
getBinaryPathWithInfo,
|
|
25
|
+
resolveBinaryPath,
|
|
26
|
+
} = require('../platform.js');
|
|
27
|
+
|
|
28
|
+
function runBinary(binaryPath, args) {
|
|
29
|
+
const result = child_process.spawnSync(binaryPath, args, {
|
|
30
|
+
stdio: 'inherit',
|
|
31
|
+
windowsHide: true,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (result.error) {
|
|
35
|
+
throw result.error;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getBinaryPath() {
|
|
42
|
+
const platformKey = getPlatformKey();
|
|
43
|
+
const packages = PLATFORM_PACKAGES[platformKey];
|
|
44
|
+
|
|
45
|
+
if (!packages) {
|
|
46
|
+
console.error(`Error: Unsupported platform: ${platformKey}`);
|
|
47
|
+
console.error(
|
|
48
|
+
`Supported platforms: ${Object.keys(PLATFORM_PACKAGES).join(', ')}`
|
|
49
|
+
);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Try to get binary from optionalDependencies
|
|
54
|
+
const result = getBinaryPathWithInfo();
|
|
55
|
+
if (result) {
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Fallback: check if binary exists alongside this script (for development)
|
|
60
|
+
const localBinary = path.join(
|
|
61
|
+
__dirname,
|
|
62
|
+
'..',
|
|
63
|
+
'dist',
|
|
64
|
+
process.platform,
|
|
65
|
+
process.arch,
|
|
66
|
+
getBinaryName()
|
|
67
|
+
);
|
|
68
|
+
if (fs.existsSync(localBinary)) {
|
|
69
|
+
return {
|
|
70
|
+
path: localBinary,
|
|
71
|
+
pkg: 'local',
|
|
72
|
+
hasBaseline: !!packages.baseline,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.error(
|
|
77
|
+
`Error: Could not find the droid binary for ${platformKey}.\n\n` +
|
|
78
|
+
`This usually means the optional dependency "${packages.regular}" was not installed.\n` +
|
|
79
|
+
`Try running: npm install\n\n` +
|
|
80
|
+
`If you're using npm with --ignore-scripts, the binary may not have been set up correctly.`
|
|
81
|
+
);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Get the binary path and execute
|
|
86
|
+
const { path: binPath, pkg, hasBaseline } = getBinaryPath();
|
|
87
|
+
const args = process.argv.slice(2);
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const result = runBinary(binPath, args);
|
|
91
|
+
|
|
92
|
+
// Check for illegal instruction error (CPU doesn't support AVX2)
|
|
93
|
+
// This can happen on Windows where we couldn't detect AVX2 upfront
|
|
94
|
+
if (result.signal === 'SIGILL' && hasBaseline && !pkg.includes('baseline')) {
|
|
95
|
+
console.error(
|
|
96
|
+
`\nNote: Your CPU doesn't support AVX2 instructions. Trying baseline build...`
|
|
97
|
+
);
|
|
98
|
+
// Try baseline
|
|
99
|
+
const baselinePath = resolveBinaryPath(
|
|
100
|
+
PLATFORM_PACKAGES[getPlatformKey()].baseline
|
|
101
|
+
);
|
|
102
|
+
if (baselinePath) {
|
|
103
|
+
const baselineResult = runBinary(baselinePath, args);
|
|
104
|
+
process.exit(baselineResult.status ?? 0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
process.exit(result.status ?? 0);
|
|
109
|
+
} catch (e) {
|
|
110
|
+
console.error(`Error executing droid: ${e.message}`);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|