@orderful/droid 0.2.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.
- package/.claude/CLAUDE.md +41 -0
- package/.github/workflows/changeset-check.yml +43 -0
- package/.github/workflows/release.yml +6 -3
- package/CHANGELOG.md +43 -0
- package/bun.lock +357 -14
- package/dist/agents/README.md +137 -0
- package/dist/bin/droid.js +12 -1
- package/dist/bin/droid.js.map +1 -1
- package/dist/commands/setup.d.ts +8 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +67 -0
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/tui.d.ts +2 -0
- package/dist/commands/tui.d.ts.map +1 -0
- package/dist/commands/tui.js +737 -0
- package/dist/commands/tui.js.map +1 -0
- package/dist/lib/agents.d.ts +53 -0
- package/dist/lib/agents.d.ts.map +1 -0
- package/dist/lib/agents.js +149 -0
- package/dist/lib/agents.js.map +1 -0
- package/dist/lib/skills.d.ts +20 -0
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/skills.js +102 -0
- package/dist/lib/skills.js.map +1 -1
- package/dist/lib/types.d.ts +5 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/version.d.ts +5 -0
- package/dist/lib/version.d.ts.map +1 -1
- package/dist/lib/version.js +19 -1
- package/dist/lib/version.js.map +1 -1
- package/dist/skills/README.md +85 -0
- package/dist/skills/comments/SKILL.md +8 -0
- package/dist/skills/comments/SKILL.yaml +32 -0
- package/dist/skills/comments/commands/README.md +58 -0
- package/package.json +15 -2
- package/src/agents/README.md +137 -0
- package/src/bin/droid.ts +12 -1
- package/src/commands/setup.ts +77 -0
- package/src/commands/tui.tsx +1535 -0
- package/src/lib/agents.ts +186 -0
- package/src/lib/skills.test.ts +75 -1
- package/src/lib/skills.ts +125 -0
- package/src/lib/types.ts +7 -0
- package/src/lib/version.test.ts +20 -1
- package/src/lib/version.ts +19 -1
- package/src/skills/README.md +85 -0
- package/src/skills/comments/SKILL.md +8 -0
- package/src/skills/comments/SKILL.yaml +32 -0
- package/src/skills/comments/commands/README.md +58 -0
- package/tsconfig.json +5 -3
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Contributing Skills
|
|
2
|
+
|
|
3
|
+
Skills are reusable AI capabilities that can be installed into Claude Code or OpenCode.
|
|
4
|
+
|
|
5
|
+
## Directory Structure
|
|
6
|
+
|
|
7
|
+
Each skill is a directory containing:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
skills/
|
|
11
|
+
└── my-skill/
|
|
12
|
+
├── SKILL.yaml # Required: Manifest with metadata
|
|
13
|
+
├── SKILL.md # Required: Instructions for the AI
|
|
14
|
+
└── commands/ # Optional: Slash commands
|
|
15
|
+
└── my-command.md
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## SKILL.yaml (Manifest)
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
name: my-skill # Must match directory name
|
|
22
|
+
description: Short description # Shown in TUI and listings
|
|
23
|
+
version: 1.0.0 # Semver
|
|
24
|
+
status: beta # alpha | beta | stable (optional)
|
|
25
|
+
dependencies: [] # Other skills required (optional)
|
|
26
|
+
provides_output: false # Can this skill be an output target?
|
|
27
|
+
|
|
28
|
+
# Configuration schema (optional)
|
|
29
|
+
config_schema:
|
|
30
|
+
option_name:
|
|
31
|
+
type: string # string | boolean
|
|
32
|
+
description: What this option does
|
|
33
|
+
default: "default value" # Optional default
|
|
34
|
+
|
|
35
|
+
# Examples shown in TUI (optional)
|
|
36
|
+
examples:
|
|
37
|
+
- title: "Example name"
|
|
38
|
+
code: |
|
|
39
|
+
// Example code block
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## SKILL.md (AI Instructions)
|
|
43
|
+
|
|
44
|
+
The SKILL.md file contains instructions for the AI. It must have YAML frontmatter:
|
|
45
|
+
|
|
46
|
+
```markdown
|
|
47
|
+
---
|
|
48
|
+
name: my-skill
|
|
49
|
+
description: Short description (must match SKILL.yaml)
|
|
50
|
+
globs:
|
|
51
|
+
- "**/*" # File patterns this skill applies to
|
|
52
|
+
alwaysApply: false # Always include in context?
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
# My Skill
|
|
56
|
+
|
|
57
|
+
Instructions for the AI on how to use this skill...
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Commands (Optional)
|
|
61
|
+
|
|
62
|
+
Commands are slash commands the user can invoke. Each is a markdown file:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
commands/
|
|
66
|
+
└── do-thing.md
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The command file is just markdown instructions. The filename becomes the command name (`/do-thing`).
|
|
70
|
+
|
|
71
|
+
## Testing Your Skill
|
|
72
|
+
|
|
73
|
+
1. Run `npm run build` to compile
|
|
74
|
+
2. Run `droid` to open the TUI
|
|
75
|
+
3. Navigate to Skills tab
|
|
76
|
+
4. Install your skill
|
|
77
|
+
5. Test in Claude Code with `/your-command` or by referencing the skill
|
|
78
|
+
|
|
79
|
+
## Checklist
|
|
80
|
+
|
|
81
|
+
- [ ] `SKILL.yaml` has all required fields (name, description, version)
|
|
82
|
+
- [ ] `SKILL.md` has valid YAML frontmatter
|
|
83
|
+
- [ ] Name in frontmatter matches directory name
|
|
84
|
+
- [ ] Description matches between SKILL.yaml and SKILL.md
|
|
85
|
+
- [ ] Tests pass: `bun test src/lib/skills.test.ts`
|
|
@@ -16,3 +16,35 @@ config_schema:
|
|
|
16
16
|
type: boolean
|
|
17
17
|
description: Keep original comments after addressing (vs removing them)
|
|
18
18
|
default: false
|
|
19
|
+
examples:
|
|
20
|
+
- title: "Action request"
|
|
21
|
+
code: |
|
|
22
|
+
// @droid use PascalCase for enum keys
|
|
23
|
+
enum Status {
|
|
24
|
+
PENDING = 'pending'
|
|
25
|
+
}
|
|
26
|
+
- title: "Ask a question"
|
|
27
|
+
code: |
|
|
28
|
+
> @droid Should we cache this?
|
|
29
|
+
|
|
30
|
+
> @fry Yes, add Redis caching here...
|
|
31
|
+
- title: "TODO with context"
|
|
32
|
+
code: |
|
|
33
|
+
// @droid TODO: refactor to async/await
|
|
34
|
+
// The callback pattern is unwieldy
|
|
35
|
+
function fetchData(callback) {
|
|
36
|
+
api.get('/data', callback);
|
|
37
|
+
}
|
|
38
|
+
- title: "Code review note"
|
|
39
|
+
code: |
|
|
40
|
+
// @droid potential memory leak here
|
|
41
|
+
// Clear interval on unmount?
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
setInterval(poll, 1000);
|
|
44
|
+
}, []);
|
|
45
|
+
- title: "Multi-line discussion"
|
|
46
|
+
code: |
|
|
47
|
+
> @droid Best approach for pagination?
|
|
48
|
+
> We have ~10k records.
|
|
49
|
+
|
|
50
|
+
> @fry Use cursor-based, limit 50.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Contributing Commands
|
|
2
|
+
|
|
3
|
+
Commands are slash commands that users invoke in Claude Code or OpenCode. They're bundled with skills.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
Commands live in a `commands/` subdirectory within a skill:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
skills/
|
|
11
|
+
└── my-skill/
|
|
12
|
+
├── SKILL.yaml
|
|
13
|
+
├── SKILL.md
|
|
14
|
+
└── commands/
|
|
15
|
+
├── README.md # This file
|
|
16
|
+
├── check.md # /check command
|
|
17
|
+
└── cleanup.md # /cleanup command
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Command File Format
|
|
21
|
+
|
|
22
|
+
Each command is a simple markdown file. The filename (without `.md`) becomes the command name.
|
|
23
|
+
|
|
24
|
+
**Example: `commands/check.md`**
|
|
25
|
+
|
|
26
|
+
```markdown
|
|
27
|
+
Scan the codebase for @droid comments and address each one.
|
|
28
|
+
|
|
29
|
+
## Behavior
|
|
30
|
+
|
|
31
|
+
1. Search for `> @droid` markers in files
|
|
32
|
+
2. For each comment found:
|
|
33
|
+
- If it's an action request → execute and remove
|
|
34
|
+
- If it's a question → respond with `> @{user_mention}`
|
|
35
|
+
|
|
36
|
+
## Arguments
|
|
37
|
+
|
|
38
|
+
- `{path}` - Optional path to scope the search (default: current directory)
|
|
39
|
+
|
|
40
|
+
## Examples
|
|
41
|
+
|
|
42
|
+
- `/comments check` - Check all files
|
|
43
|
+
- `/comments check src/` - Check only src directory
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Naming Convention
|
|
47
|
+
|
|
48
|
+
Commands are namespaced by skill. If your skill is `comments`, your commands become:
|
|
49
|
+
|
|
50
|
+
- `commands/check.md` → `/comments check`
|
|
51
|
+
- `commands/cleanup.md` → `/comments cleanup`
|
|
52
|
+
|
|
53
|
+
## Best Practices
|
|
54
|
+
|
|
55
|
+
1. **Be specific** - Describe exactly what the command does
|
|
56
|
+
2. **Include examples** - Show common usage patterns
|
|
57
|
+
3. **Document arguments** - List any parameters the command accepts
|
|
58
|
+
4. **Explain behavior** - Break down the steps the AI should follow
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orderful/droid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "AI workflow toolkit for sharing skills, commands, and agents across the team",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsc && cp -r src/skills dist/",
|
|
11
|
+
"build": "tsc && cp -r src/skills dist/ && cp -r src/agents dist/",
|
|
12
12
|
"dev": "tsc --watch",
|
|
13
13
|
"start": "bun dist/bin/droid.js",
|
|
14
14
|
"test": "bun test src/",
|
|
@@ -36,21 +36,34 @@
|
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=18.0.0"
|
|
38
38
|
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public",
|
|
41
|
+
"registry": "https://registry.npmjs.org/"
|
|
42
|
+
},
|
|
39
43
|
"dependencies": {
|
|
44
|
+
"@opentui/core": "^0.1.59",
|
|
45
|
+
"@opentui/react": "^0.1.59",
|
|
40
46
|
"chalk": "^5.3.0",
|
|
41
47
|
"commander": "^12.1.0",
|
|
48
|
+
"ink": "^6.5.1",
|
|
49
|
+
"ink-select-input": "^6.2.0",
|
|
50
|
+
"ink-text-input": "^6.0.0",
|
|
42
51
|
"inquirer": "^9.2.15",
|
|
43
52
|
"ora": "^8.0.1",
|
|
53
|
+
"react": "^19.2.1",
|
|
44
54
|
"yaml": "^2.4.1"
|
|
45
55
|
},
|
|
46
56
|
"devDependencies": {
|
|
47
57
|
"@changesets/changelog-github": "^0.5.2",
|
|
48
58
|
"@changesets/cli": "^2.29.8",
|
|
49
59
|
"@types/bun": "latest",
|
|
60
|
+
"@types/ink-text-input": "^2.0.5",
|
|
50
61
|
"@types/inquirer": "^9.0.7",
|
|
51
62
|
"@types/node": "^20.11.24",
|
|
63
|
+
"@types/react": "^19.2.7",
|
|
52
64
|
"@typescript-eslint/eslint-plugin": "^8.49.0",
|
|
53
65
|
"@typescript-eslint/parser": "^8.49.0",
|
|
66
|
+
"esbuild": "^0.27.1",
|
|
54
67
|
"eslint": "^8.57.0",
|
|
55
68
|
"prettier": "^3.2.5",
|
|
56
69
|
"typescript": "^5.4.2"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Contributing Agents
|
|
2
|
+
|
|
3
|
+
Agents are specialized AI personas with specific expertise or roles. They augment the AI's capabilities for particular tasks.
|
|
4
|
+
|
|
5
|
+
## Directory Structure
|
|
6
|
+
|
|
7
|
+
Each agent is a directory containing:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
agents/
|
|
11
|
+
└── my-agent/
|
|
12
|
+
├── AGENT.yaml # Required: Manifest with metadata and persona
|
|
13
|
+
└── AGENT.md # Required: Documentation for users
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## AGENT.yaml (Manifest)
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
name: my-agent # Must match directory name
|
|
20
|
+
description: Short description # Shown in TUI and listings
|
|
21
|
+
version: 1.0.0 # Semver
|
|
22
|
+
status: alpha # alpha | beta | stable (optional)
|
|
23
|
+
|
|
24
|
+
# Agent type (required)
|
|
25
|
+
mode: subagent # primary | subagent | all
|
|
26
|
+
|
|
27
|
+
# Tools this agent can use (optional)
|
|
28
|
+
tools:
|
|
29
|
+
- Read
|
|
30
|
+
- Glob
|
|
31
|
+
- Grep
|
|
32
|
+
- Bash
|
|
33
|
+
|
|
34
|
+
# Suggested triggers - phrases that might invoke this agent
|
|
35
|
+
triggers:
|
|
36
|
+
- "review my code"
|
|
37
|
+
- "check for bugs"
|
|
38
|
+
|
|
39
|
+
# Persona - system prompt additions for this agent (used if AGENT.md is minimal)
|
|
40
|
+
persona: |
|
|
41
|
+
You are a specialized assistant focused on...
|
|
42
|
+
|
|
43
|
+
Your priorities are:
|
|
44
|
+
1. First priority
|
|
45
|
+
2. Second priority
|
|
46
|
+
|
|
47
|
+
Always be specific and constructive.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Agent Modes
|
|
51
|
+
|
|
52
|
+
- **`primary`** - Main agents you interact with directly. Cycle through them with Tab key.
|
|
53
|
+
- **`subagent`** - Specialized helpers invoked via @mention (e.g., `@code-reviewer check this`) or by primary agents.
|
|
54
|
+
- **`all`** - Agent works as both primary and subagent.
|
|
55
|
+
|
|
56
|
+
## AGENT.md (Documentation)
|
|
57
|
+
|
|
58
|
+
The AGENT.md file documents the agent for users:
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
---
|
|
62
|
+
name: my-agent
|
|
63
|
+
description: Short description (must match AGENT.yaml)
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
# My Agent
|
|
67
|
+
|
|
68
|
+
Description of what this agent does and when to use it.
|
|
69
|
+
|
|
70
|
+
## What It Does
|
|
71
|
+
|
|
72
|
+
- Bullet points of capabilities
|
|
73
|
+
- What it focuses on
|
|
74
|
+
- What it ignores
|
|
75
|
+
|
|
76
|
+
## Usage
|
|
77
|
+
|
|
78
|
+
Examples of how to invoke or use this agent.
|
|
79
|
+
|
|
80
|
+
## Output Format
|
|
81
|
+
|
|
82
|
+
Description of how the agent formats its responses.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Example Agent
|
|
86
|
+
|
|
87
|
+
See `code-reviewer/` for a complete example:
|
|
88
|
+
|
|
89
|
+
- Reviews code for bugs, security issues, style
|
|
90
|
+
- Categorizes issues by severity (critical/warning/suggestion)
|
|
91
|
+
- References specific file and line numbers
|
|
92
|
+
|
|
93
|
+
## Ideas for Agents
|
|
94
|
+
|
|
95
|
+
- **test-writer** - Generates unit tests for code
|
|
96
|
+
- **doc-writer** - Writes documentation and comments
|
|
97
|
+
- **refactorer** - Suggests and applies refactoring patterns
|
|
98
|
+
- **security-auditor** - Deep security analysis
|
|
99
|
+
- **performance-optimizer** - Identifies performance bottlenecks
|
|
100
|
+
|
|
101
|
+
## Installation
|
|
102
|
+
|
|
103
|
+
When you install an agent via the TUI, droid:
|
|
104
|
+
|
|
105
|
+
1. Reads `AGENT.yaml` for metadata (name, description, tools)
|
|
106
|
+
2. Reads `AGENT.md` for the agent's instructions/persona
|
|
107
|
+
3. Combines them into a single `.md` file with frontmatter
|
|
108
|
+
4. Writes to `~/.claude/agents/{name}.md`
|
|
109
|
+
|
|
110
|
+
The installed format matches what Claude Code expects:
|
|
111
|
+
|
|
112
|
+
```markdown
|
|
113
|
+
---
|
|
114
|
+
name: my-agent
|
|
115
|
+
description: Short description
|
|
116
|
+
tools: Read, Glob, Grep, Bash
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
[Content from AGENT.md]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Testing Your Agent
|
|
123
|
+
|
|
124
|
+
1. Run `npm run build` to compile
|
|
125
|
+
2. Run `droid` to open the TUI
|
|
126
|
+
3. Navigate to Agents tab
|
|
127
|
+
4. Verify your agent appears with correct metadata
|
|
128
|
+
5. Install and verify it appears in `~/.claude/agents/`
|
|
129
|
+
|
|
130
|
+
## Checklist
|
|
131
|
+
|
|
132
|
+
- [ ] `AGENT.yaml` has all required fields (name, description, version, mode)
|
|
133
|
+
- [ ] `AGENT.md` contains the agent's instructions/persona
|
|
134
|
+
- [ ] Name matches directory name
|
|
135
|
+
- [ ] Description is clear and concise
|
|
136
|
+
- [ ] Mode is appropriate (subagent for specialized tasks, primary for main assistants)
|
|
137
|
+
- [ ] Tools list only includes what the agent needs
|
package/src/bin/droid.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { skillsCommand } from '../commands/skills.js';
|
|
|
7
7
|
import { installCommand } from '../commands/install.js';
|
|
8
8
|
import { uninstallCommand } from '../commands/uninstall.js';
|
|
9
9
|
import { updateCommand } from '../commands/update.js';
|
|
10
|
+
import { tuiCommand } from '../commands/tui.js';
|
|
10
11
|
import { getVersion, checkForUpdates } from '../lib/version.js';
|
|
11
12
|
|
|
12
13
|
const version = getVersion();
|
|
@@ -52,7 +53,17 @@ program
|
|
|
52
53
|
.argument('[skill]', 'Update a specific skill')
|
|
53
54
|
.action(updateCommand);
|
|
54
55
|
|
|
56
|
+
program
|
|
57
|
+
.command('tui')
|
|
58
|
+
.description('Launch interactive TUI dashboard')
|
|
59
|
+
.action(tuiCommand);
|
|
60
|
+
|
|
55
61
|
// Check for updates on any command (non-blocking)
|
|
56
62
|
checkForUpdates().catch(() => {});
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
// If no command provided, launch TUI
|
|
65
|
+
if (process.argv.length === 2) {
|
|
66
|
+
tuiCommand();
|
|
67
|
+
} else {
|
|
68
|
+
program.parse();
|
|
69
|
+
}
|
package/src/commands/setup.ts
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
import inquirer from 'inquirer';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { execSync } from 'child_process';
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { homedir } from 'os';
|
|
4
7
|
import { loadConfig, saveConfig, configExists } from '../lib/config.js';
|
|
5
8
|
import { getBundledSkills } from '../lib/skills.js';
|
|
6
9
|
import { AITool, BuiltInOutput, type DroidConfig, type OutputPreference } from '../lib/types.js';
|
|
7
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Permissions droid needs to operate without constant prompts
|
|
13
|
+
*/
|
|
14
|
+
const DROID_PERMISSIONS = [
|
|
15
|
+
'Read(~/.droid/**)',
|
|
16
|
+
'Write(~/.droid/**)',
|
|
17
|
+
'Edit(~/.droid/**)',
|
|
18
|
+
'Glob(~/.droid/**)',
|
|
19
|
+
'Grep(~/.droid/**)',
|
|
20
|
+
];
|
|
21
|
+
|
|
8
22
|
/**
|
|
9
23
|
* Detect which AI tool is installed
|
|
10
24
|
*/
|
|
@@ -37,6 +51,60 @@ function detectGitUsername(): string {
|
|
|
37
51
|
}
|
|
38
52
|
}
|
|
39
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Configure AI tool permissions for droid
|
|
56
|
+
*/
|
|
57
|
+
export function configureAIToolPermissions(aiTool: AITool): { added: string[]; alreadyPresent: boolean } {
|
|
58
|
+
const added: string[] = [];
|
|
59
|
+
|
|
60
|
+
if (aiTool === AITool.ClaudeCode) {
|
|
61
|
+
const settingsPath = join(homedir(), '.claude', 'settings.json');
|
|
62
|
+
|
|
63
|
+
// Ensure .claude directory exists
|
|
64
|
+
const claudeDir = join(homedir(), '.claude');
|
|
65
|
+
if (!existsSync(claudeDir)) {
|
|
66
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Load or create settings
|
|
70
|
+
let settings: { permissions?: { allow?: string[]; deny?: string[]; ask?: string[] } } = {};
|
|
71
|
+
if (existsSync(settingsPath)) {
|
|
72
|
+
try {
|
|
73
|
+
settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
74
|
+
} catch {
|
|
75
|
+
// Invalid JSON, start fresh
|
|
76
|
+
settings = {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Ensure permissions structure exists
|
|
81
|
+
if (!settings.permissions) {
|
|
82
|
+
settings.permissions = {};
|
|
83
|
+
}
|
|
84
|
+
if (!Array.isArray(settings.permissions.allow)) {
|
|
85
|
+
settings.permissions.allow = [];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Add missing permissions
|
|
89
|
+
for (const perm of DROID_PERMISSIONS) {
|
|
90
|
+
if (!settings.permissions.allow.includes(perm)) {
|
|
91
|
+
settings.permissions.allow.push(perm);
|
|
92
|
+
added.push(perm);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Save if we added anything
|
|
97
|
+
if (added.length > 0) {
|
|
98
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return { added, alreadyPresent: added.length === 0 };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// OpenCode - TODO: implement when we know the settings path
|
|
105
|
+
return { added: [], alreadyPresent: true };
|
|
106
|
+
}
|
|
107
|
+
|
|
40
108
|
/**
|
|
41
109
|
* Get available output options (built-in + skills that provide output)
|
|
42
110
|
*/
|
|
@@ -145,5 +213,14 @@ export async function setupCommand(): Promise<void> {
|
|
|
145
213
|
saveConfig(config);
|
|
146
214
|
|
|
147
215
|
console.log(chalk.green('\n✓ Config saved to ~/.droid/config.yaml'));
|
|
216
|
+
|
|
217
|
+
// Configure AI tool permissions
|
|
218
|
+
const { added, alreadyPresent } = configureAIToolPermissions(answers.ai_tool);
|
|
219
|
+
if (added.length > 0) {
|
|
220
|
+
console.log(chalk.green(`✓ Added droid permissions to ${answers.ai_tool} settings`));
|
|
221
|
+
} else if (alreadyPresent) {
|
|
222
|
+
console.log(chalk.gray(` Droid permissions already configured in ${answers.ai_tool}`));
|
|
223
|
+
}
|
|
224
|
+
|
|
148
225
|
console.log(chalk.gray('\nRun `droid skills` to browse and install skills.'));
|
|
149
226
|
}
|