@monoes/monomindcli 1.9.17 → 1.10.1
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/commands/mastermind/_repeat.md +182 -39
- package/.claude/commands/mastermind/architect.md +17 -11
- package/.claude/commands/mastermind/brain.md +4 -0
- package/.claude/commands/mastermind/build.md +4 -0
- package/.claude/commands/mastermind/content.md +4 -0
- package/.claude/commands/mastermind/createorg.md +5 -3
- package/.claude/commands/mastermind/finance.md +4 -0
- package/.claude/commands/mastermind/idea.md +4 -0
- package/.claude/commands/mastermind/marketing.md +4 -0
- package/.claude/commands/mastermind/master.md +63 -37
- package/.claude/commands/mastermind/ops.md +4 -0
- package/.claude/commands/mastermind/release.md +4 -0
- package/.claude/commands/mastermind/research.md +4 -0
- package/.claude/commands/mastermind/review.md +4 -0
- package/.claude/commands/mastermind/runorg.md +5 -3
- package/.claude/commands/mastermind/sales.md +4 -0
- package/.claude/commands/mastermind/techport.md +9 -0
- package/.claude/commands/monomind/do.md +5 -1
- package/.claude/commands/monomind/idea.md +5 -1
- package/.claude/commands/monomind/improve.md +5 -1
- package/.claude/commands/monomind/repeat.md +85 -29
- package/.claude/commands/monomind/review.md +6 -2
- package/.claude/commands/monomind/understand.md +10 -8
- package/.claude/helpers/extras-registry.json +235 -235
- package/.claude/helpers/graphify-freshen.cjs +13 -1
- package/.claude/helpers/hook-handler.cjs +1 -1
- package/.claude/helpers/router.cjs +4 -1
- package/.claude/skills/mastermind/_protocol.md +28 -21
- package/.claude/skills/mastermind/access.md +236 -0
- package/.claude/skills/mastermind/activity.md +191 -0
- package/.claude/skills/mastermind/adapter-manager.md +259 -0
- package/.claude/skills/mastermind/adapters.md +204 -0
- package/.claude/skills/mastermind/agent-detail.md +242 -0
- package/.claude/skills/mastermind/agents.md +178 -0
- package/.claude/skills/mastermind/approval-detail.md +259 -0
- package/.claude/skills/mastermind/approve.md +181 -0
- package/.claude/skills/mastermind/architect.md +24 -8
- package/.claude/skills/mastermind/backup.md +197 -0
- package/.claude/skills/mastermind/bootstrap.md +190 -0
- package/.claude/skills/mastermind/budgets.md +237 -0
- package/.claude/skills/mastermind/companies.md +256 -0
- package/.claude/skills/mastermind/costs.md +151 -0
- package/.claude/skills/mastermind/createorg.md +23 -5
- package/.claude/skills/mastermind/diagnose.md +249 -0
- package/.claude/skills/mastermind/env.md +198 -0
- package/.claude/skills/mastermind/environments.md +250 -0
- package/.claude/skills/mastermind/export.md +324 -0
- package/.claude/skills/mastermind/goal-detail.md +255 -0
- package/.claude/skills/mastermind/goals.md +149 -0
- package/.claude/skills/mastermind/heartbeat.md +164 -0
- package/.claude/skills/mastermind/idea.md +250 -122
- package/.claude/skills/mastermind/import.md +281 -0
- package/.claude/skills/mastermind/inbox.md +214 -0
- package/.claude/skills/mastermind/instance-settings.md +315 -0
- package/.claude/skills/mastermind/instance.md +231 -0
- package/.claude/skills/mastermind/invite-landing.md +227 -0
- package/.claude/skills/mastermind/invites.md +254 -0
- package/.claude/skills/mastermind/issue-detail.md +291 -0
- package/.claude/skills/mastermind/issues.md +235 -0
- package/.claude/skills/mastermind/join-queue.md +170 -0
- package/.claude/skills/mastermind/liveness.md +392 -0
- package/.claude/skills/mastermind/memory.md +321 -0
- package/.claude/skills/mastermind/my-issues.md +146 -0
- package/.claude/skills/mastermind/new-agent.md +241 -0
- package/.claude/skills/mastermind/org-chart.md +207 -0
- package/.claude/skills/mastermind/org-settings.md +217 -0
- package/.claude/skills/mastermind/plan-to-tasks.md +136 -0
- package/.claude/skills/mastermind/plugin-manager.md +241 -0
- package/.claude/skills/mastermind/plugin-settings.md +273 -0
- package/.claude/skills/mastermind/plugins.md +190 -0
- package/.claude/skills/mastermind/profile.md +187 -0
- package/.claude/skills/mastermind/project-detail.md +249 -0
- package/.claude/skills/mastermind/project-workspace.md +244 -0
- package/.claude/skills/mastermind/projects.md +164 -0
- package/.claude/skills/mastermind/routine-detail.md +253 -0
- package/.claude/skills/mastermind/routines.md +202 -0
- package/.claude/skills/mastermind/runorg.md +74 -9
- package/.claude/skills/mastermind/search.md +186 -0
- package/.claude/skills/mastermind/secrets.md +199 -0
- package/.claude/skills/mastermind/skills.md +156 -0
- package/.claude/skills/mastermind/tasks.md +149 -0
- package/.claude/skills/mastermind/techport.md +5 -5
- package/.claude/skills/mastermind/threads.md +259 -0
- package/.claude/skills/mastermind/tree-control.md +250 -0
- package/.claude/skills/mastermind/wiki.md +314 -0
- package/.claude/skills/mastermind/workspace-detail.md +317 -0
- package/.claude/skills/mastermind/workspaces.md +261 -0
- package/.claude/skills/mastermind/worktree.md +187 -0
- package/dist/src/init/executor.js +8 -8
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +12 -0
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/ui/.monomind/data/ranked-context.json +1 -1
- package/dist/src/ui/.monomind/loops/mastermind-review-1778664132789.json +16 -0
- package/dist/src/ui/.monomind/sessions/current.json +5 -5
- package/dist/src/ui/.monomind/sessions/session-1776778451399.json +15 -0
- package/dist/src/ui/dashboard.html +3030 -181
- package/dist/src/ui/data/mastermind-events.jsonl +8 -0
- package/dist/src/ui/data/mastermind-sessions.json +1 -0
- package/dist/src/ui/server.mjs +738 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/.claude/skills/.monomind/data/ranked-context.json +0 -5
- package/.claude/skills/.monomind/sessions/current.json +0 -13
- package/.claude/skills/.monomind/sessions/session-1777829336455.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777831614725.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777832095857.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777839814183.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777841847131.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777843309463.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777880867159.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777881884593.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777884090471.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777884808221.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777885672155.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777886852818.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777896532690.json +0 -15
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-plan-to-tasks
|
|
3
|
+
description: Mastermind plan-to-tasks — converts a written plan (prose, outline, or structured doc) into assigned org issues with correct specialties, dependency wiring, and parallelization. Mirrors Paperclip's plan-to-tasks skill. Use when breaking down a project plan into executable issue trees.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Plan to Tasks
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:plan-to-tasks` or directly via `/mastermind:plan-to-tasks`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
17
|
+
- `org_name`: org to create issues in (required)
|
|
18
|
+
- `plan`: the plan text (required — paste inline or pipe in)
|
|
19
|
+
- `project_id`: assign all issues to this project (optional)
|
|
20
|
+
- `workspace_id`: assign all issues to this workspace (optional)
|
|
21
|
+
- `dry_run`: true | false (default: false — if true, print plan without creating issues)
|
|
22
|
+
- `caller`: command | master
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Step 0 — Brain Load (standalone only)
|
|
27
|
+
|
|
28
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Step 1 — Validate Inputs
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
[ -z "$org_name" ] && { echo "ERROR: --org required."; exit 1; }
|
|
36
|
+
[ -z "$plan" ] && { echo "ERROR: --plan required (the plan text to decompose)."; exit 1; }
|
|
37
|
+
|
|
38
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
39
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Step 2 — Load Agents for Specialty Matching
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
echo "PLAN-TO-TASKS — $org_name"
|
|
48
|
+
echo "────────────────────────────────────────────────────────"
|
|
49
|
+
echo ""
|
|
50
|
+
echo "AGENTS IN ORG:"
|
|
51
|
+
jq -r '.roles[] | " \(.id) \(.title // "-") [\(.adapter.type // "?")]"' "$orgFile"
|
|
52
|
+
echo ""
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Step 3 — Decompose Plan into Issues
|
|
58
|
+
|
|
59
|
+
Read the plan carefully and apply these rules:
|
|
60
|
+
|
|
61
|
+
**Planning principles (from Paperclip plan-to-tasks):**
|
|
62
|
+
|
|
63
|
+
1. **Plan deeply.** Capture real detail: goals, constraints, unknowns, success criteria, risks. A shallow plan becomes rework.
|
|
64
|
+
2. **Know your team.** Read the org's agents and their specialties (titles, roles, adapters) before assigning anything.
|
|
65
|
+
3. **Assign for specialty.** Hand each piece of work to the most relevant agent. If no agent fits, flag the gap.
|
|
66
|
+
4. **Take responsibility.** When you (the AI) are best-suited for a piece, assign it to yourself instead of delegating.
|
|
67
|
+
5. **Use the dependency tree.** Express every concrete deliverable as an issue. Wire real blockers via `blockedByIssueIds`. When done, dependents auto-wake.
|
|
68
|
+
6. **Order, then parallelize.** Sequence by real dependencies. Independent branches start in parallel.
|
|
69
|
+
7. **Enough is enough.** Plans unblock execution. Don't re-plan already clear work.
|
|
70
|
+
|
|
71
|
+
**Decomposition output:**
|
|
72
|
+
|
|
73
|
+
For each issue extracted from the plan, produce:
|
|
74
|
+
```
|
|
75
|
+
ISSUE: <title>
|
|
76
|
+
assignee: <agent-id or UNASSIGNED>
|
|
77
|
+
priority: low | medium | high | urgent
|
|
78
|
+
blockedBy: <issue-title> (or none)
|
|
79
|
+
description: <1-2 sentence summary of the deliverable>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Quality checklist before creating:**
|
|
83
|
+
- [ ] Enough detail that assignees can act without re-asking
|
|
84
|
+
- [ ] Every concrete deliverable is an issue
|
|
85
|
+
- [ ] Each issue has a deliberate, specialty-matched assignee
|
|
86
|
+
- [ ] Each issue's real blockers are declared
|
|
87
|
+
- [ ] Independent branches can start in parallel
|
|
88
|
+
- [ ] Gaps (missing skills, decisions, external inputs) are surfaced, not hidden
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Step 4 — Create Issues (unless dry_run=true)
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
issuesFile=".monomind/orgs/${org_name}-issues.json"
|
|
96
|
+
[ ! -f "$issuesFile" ] && echo '{"issues":[]}' > "$issuesFile"
|
|
97
|
+
|
|
98
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
99
|
+
|
|
100
|
+
# Issues are created from the decomposition above
|
|
101
|
+
# Each issue gets:
|
|
102
|
+
# id: issue-<timestamp>-<N>
|
|
103
|
+
# title, description, priority, status: open
|
|
104
|
+
# assigneeId (from matched agent)
|
|
105
|
+
# projectId, workspaceId (if provided)
|
|
106
|
+
# blockedByIssueIds (resolved after all issues are created)
|
|
107
|
+
# createdAt, updatedAt
|
|
108
|
+
|
|
109
|
+
echo ""
|
|
110
|
+
if [ "${dry_run:-false}" = "true" ]; then
|
|
111
|
+
echo "DRY RUN — no issues were created."
|
|
112
|
+
echo "Remove --dry-run to create these issues."
|
|
113
|
+
else
|
|
114
|
+
echo "CREATED ISSUES:"
|
|
115
|
+
# (issue creation happens inline above as each issue is decomposed)
|
|
116
|
+
fi
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Step 5 — Return Output
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
domain: ops
|
|
125
|
+
status: complete
|
|
126
|
+
action: plan-to-tasks
|
|
127
|
+
org_name: <org_name>
|
|
128
|
+
issues_created: <N>
|
|
129
|
+
dry_run: <true|false>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Step 6 — Brain Write (standalone only)
|
|
135
|
+
|
|
136
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-plugin-manager
|
|
3
|
+
description: Mastermind plugin-manager — install plugins from npm, uninstall with two-step confirmation, enable/disable installed plugins. Extends mastermind:plugins (listing) and mastermind:plugin-settings (per-plugin config) with the install/uninstall lifecycle. Mirrors PluginManager.tsx.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Plugin Manager
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:plugin-manager` or directly via `/mastermind:plugin-manager`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
17
|
+
- `action`: list | install | uninstall | enable | disable | check-updates
|
|
18
|
+
- `package_name`: npm package name to install (for install; e.g. `@monomind/plugin-github`)
|
|
19
|
+
- `plugin_id`: plugin id slug (required for uninstall/enable/disable)
|
|
20
|
+
- `confirm`: yes (required second step for uninstall — prevents accidental removal)
|
|
21
|
+
- `caller`: command | master
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Plugin Record Schema
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"id": "plugin-slug",
|
|
30
|
+
"packageName": "@monomind/plugin-name",
|
|
31
|
+
"status": "installed",
|
|
32
|
+
"version": "1.2.0",
|
|
33
|
+
"category": "monitoring",
|
|
34
|
+
"description": "One-line plugin description",
|
|
35
|
+
"installedAt": "2026-01-01T00:00:00Z",
|
|
36
|
+
"config": {},
|
|
37
|
+
"grants": [],
|
|
38
|
+
"health": {"status": "ok", "lastCheck": null}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Step 0 — Brain Load (standalone only)
|
|
45
|
+
|
|
46
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Step 1 — Load Plugin Registry
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
registryFile=".monomind/plugins/registry.json"
|
|
54
|
+
mkdir -p ".monomind/plugins"
|
|
55
|
+
[ ! -f "$registryFile" ] && echo '{"plugins":[]}' > "$registryFile"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Step 2 — Execute Action
|
|
61
|
+
|
|
62
|
+
### list (default)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
echo "INSTALLED PLUGINS"
|
|
66
|
+
echo "────────────────────────────────────────────────────────"
|
|
67
|
+
printf "%-24s %-10s %-10s %-14s %s\n" "ID" "STATUS" "VERSION" "CATEGORY" "PACKAGE"
|
|
68
|
+
echo "────────────────────────────────────────────────────────"
|
|
69
|
+
|
|
70
|
+
count=$(jq '.plugins | length' "$registryFile")
|
|
71
|
+
if [ "$count" -eq 0 ]; then
|
|
72
|
+
echo " No plugins installed."
|
|
73
|
+
echo " Install one: --action install --package-name @monomind/plugin-github"
|
|
74
|
+
else
|
|
75
|
+
jq -r '.plugins[] |
|
|
76
|
+
[.id, (.status // "installed"), (.version // "-"), (.category // "general"),
|
|
77
|
+
(.packageName // "-")] | @tsv' \
|
|
78
|
+
"$registryFile" | while IFS=$'\t' read -r id st ver cat pkg; do
|
|
79
|
+
printf "%-24s %-10s %-10s %-14s %s\n" "$id" "$st" "$ver" "$cat" "$pkg"
|
|
80
|
+
done
|
|
81
|
+
|
|
82
|
+
errCount=$(jq '[.plugins[] | select(.status == "error")] | length' "$registryFile")
|
|
83
|
+
[ "$errCount" -gt 0 ] && echo "" && echo " WARNING: $errCount plugin(s) in error state. Run: --action list to inspect."
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
echo ""
|
|
87
|
+
echo " Install: --action install --package-name <npm-package>"
|
|
88
|
+
echo " Uninstall: --action uninstall --plugin-id <id>"
|
|
89
|
+
echo " Settings: /mastermind:plugin-settings --plugin-id <id>"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### install
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
[ -z "$package_name" ] && { echo "ERROR: --package-name required (e.g. @monomind/plugin-github)."; exit 1; }
|
|
96
|
+
|
|
97
|
+
echo "INSTALLING PLUGIN — $package_name"
|
|
98
|
+
echo "────────────────────────────────────────────────────────"
|
|
99
|
+
echo " Running: npm install $package_name"
|
|
100
|
+
|
|
101
|
+
# Check if already installed
|
|
102
|
+
alreadyId=$(jq -r --arg pkg "$package_name" '.plugins[] | select(.packageName == $pkg) | .id' "$registryFile" | head -1)
|
|
103
|
+
[ -n "$alreadyId" ] && {
|
|
104
|
+
echo " Plugin already installed as '$alreadyId'. Use --action enable/disable or reinstall via npm."
|
|
105
|
+
exit 0
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if npm install "$package_name" 2>&1 | tail -5; then
|
|
109
|
+
# Derive plugin metadata from npm package
|
|
110
|
+
pkgVer=$(node -e "try{console.log(require('${package_name}/package.json').version)}catch(e){console.log('0.0.0')}" 2>/dev/null || echo "0.0.0")
|
|
111
|
+
pkgDesc=$(node -e "try{console.log(require('${package_name}/package.json').description||'')}catch(e){console.log('')}" 2>/dev/null || echo "")
|
|
112
|
+
pluginId=$(echo "$package_name" | sed 's|@[^/]*/||' | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-//;s/-$//')
|
|
113
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
114
|
+
|
|
115
|
+
tmp="${registryFile}.tmp"
|
|
116
|
+
jq --arg id "$pluginId" \
|
|
117
|
+
--arg pkg "$package_name" \
|
|
118
|
+
--arg ver "$pkgVer" \
|
|
119
|
+
--arg desc "$pkgDesc" \
|
|
120
|
+
--arg ts "$ts" \
|
|
121
|
+
'.plugins += [{"id":$id,"packageName":$pkg,"status":"installed","version":$ver,
|
|
122
|
+
"description":$desc,"category":"general","config":{},"grants":[],
|
|
123
|
+
"health":{"status":"ok","lastCheck":null},"installedAt":$ts}]' \
|
|
124
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
125
|
+
|
|
126
|
+
echo ""
|
|
127
|
+
echo "Plugin installed: $pluginId @ $pkgVer"
|
|
128
|
+
echo " Configure: /mastermind:plugin-settings --plugin-id $pluginId"
|
|
129
|
+
else
|
|
130
|
+
echo " ERROR: npm install failed. Check the package name and network connectivity."
|
|
131
|
+
exit 1
|
|
132
|
+
fi
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### uninstall
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
[ -z "$plugin_id" ] && { echo "ERROR: --plugin-id required."; exit 1; }
|
|
139
|
+
|
|
140
|
+
exists=$(jq -r --arg id "$plugin_id" '[.plugins[] | select(.id == $id)] | length' "$registryFile")
|
|
141
|
+
[ "$exists" -eq 0 ] && { echo "ERROR: Plugin '$plugin_id' not found."; exit 1; }
|
|
142
|
+
|
|
143
|
+
# Two-step confirmation
|
|
144
|
+
if [ "${confirm:-}" != "yes" ]; then
|
|
145
|
+
pkg=$(jq -r --arg id "$plugin_id" '.plugins[] | select(.id == $id) | .packageName // $id' "$registryFile")
|
|
146
|
+
echo "UNINSTALL CONFIRMATION REQUIRED"
|
|
147
|
+
echo "────────────────────────────────────────────────────────"
|
|
148
|
+
echo " Plugin: $plugin_id ($pkg)"
|
|
149
|
+
echo " This will remove the plugin and all its configuration."
|
|
150
|
+
echo ""
|
|
151
|
+
echo " To confirm: --action uninstall --plugin-id $plugin_id --confirm yes"
|
|
152
|
+
exit 0
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
pkg=$(jq -r --arg id "$plugin_id" '.plugins[] | select(.id == $id) | .packageName // ""' "$registryFile")
|
|
156
|
+
|
|
157
|
+
# Remove from registry
|
|
158
|
+
tmp="${registryFile}.tmp"
|
|
159
|
+
jq --arg id "$plugin_id" \
|
|
160
|
+
'.plugins = [.plugins[] | select(.id != $id)]' \
|
|
161
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
162
|
+
|
|
163
|
+
echo "Plugin '$plugin_id' removed from registry."
|
|
164
|
+
|
|
165
|
+
# Attempt npm uninstall if packageName known
|
|
166
|
+
if [ -n "$pkg" ]; then
|
|
167
|
+
echo " Running: npm uninstall $pkg"
|
|
168
|
+
npm uninstall "$pkg" 2>&1 | tail -3 || echo " WARNING: npm uninstall had errors — registry entry removed anyway."
|
|
169
|
+
fi
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### enable
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
[ -z "$plugin_id" ] && { echo "ERROR: --plugin-id required."; exit 1; }
|
|
176
|
+
|
|
177
|
+
exists=$(jq -r --arg id "$plugin_id" '[.plugins[] | select(.id == $id)] | length' "$registryFile")
|
|
178
|
+
[ "$exists" -eq 0 ] && { echo "ERROR: Plugin '$plugin_id' not found."; exit 1; }
|
|
179
|
+
|
|
180
|
+
tmp="${registryFile}.tmp"
|
|
181
|
+
jq --arg id "$plugin_id" \
|
|
182
|
+
'.plugins = [.plugins[] | if .id == $id then .status = "installed" | .disabledAt = null else . end]' \
|
|
183
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
184
|
+
|
|
185
|
+
echo "Plugin '$plugin_id' ENABLED."
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### disable
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
[ -z "$plugin_id" ] && { echo "ERROR: --plugin-id required."; exit 1; }
|
|
192
|
+
|
|
193
|
+
exists=$(jq -r --arg id "$plugin_id" '[.plugins[] | select(.id == $id)] | length' "$registryFile")
|
|
194
|
+
[ "$exists" -eq 0 ] && { echo "ERROR: Plugin '$plugin_id' not found."; exit 1; }
|
|
195
|
+
|
|
196
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
197
|
+
tmp="${registryFile}.tmp"
|
|
198
|
+
jq --arg id "$plugin_id" --arg ts "$ts" \
|
|
199
|
+
'.plugins = [.plugins[] | if .id == $id then .status = "disabled" | .disabledAt = $ts else . end]' \
|
|
200
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
201
|
+
|
|
202
|
+
echo "Plugin '$plugin_id' DISABLED — will not load on next startup."
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### check-updates
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
echo "CHECKING PLUGIN UPDATES"
|
|
209
|
+
echo "────────────────────────────────────────────────────────"
|
|
210
|
+
|
|
211
|
+
count=$(jq '.plugins | length' "$registryFile")
|
|
212
|
+
[ "$count" -eq 0 ] && { echo " No plugins installed."; exit 0; }
|
|
213
|
+
|
|
214
|
+
jq -r '.plugins[] | select(.packageName != null) |
|
|
215
|
+
[.id, .packageName, (.version // "unknown")] | @tsv' \
|
|
216
|
+
"$registryFile" | while IFS=$'\t' read -r id pkg ver; do
|
|
217
|
+
latest=$(curl -sf "https://registry.npmjs.org/${pkg}/latest" 2>/dev/null | jq -r '.version // "?"' 2>/dev/null || echo "?")
|
|
218
|
+
if [ "$latest" != "?" ] && [ "$latest" != "$ver" ]; then
|
|
219
|
+
echo " [$id] $ver → $latest — run: npm install $pkg"
|
|
220
|
+
else
|
|
221
|
+
echo " [$id] $ver (up to date)"
|
|
222
|
+
fi
|
|
223
|
+
done
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Step 3 — Return Output
|
|
229
|
+
|
|
230
|
+
```yaml
|
|
231
|
+
domain: ops
|
|
232
|
+
status: complete
|
|
233
|
+
action: <action>
|
|
234
|
+
plugin_id: <plugin_id>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Step 4 — Brain Write (standalone only)
|
|
240
|
+
|
|
241
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-plugin-settings
|
|
3
|
+
description: Mastermind plugin-settings — inspect and configure a single installed plugin. View configuration fields, manage file system access grants (read/write paths), check runtime health/status, and update plugin settings. Mirrors Paperclip's PluginSettings page with configuration and status tabs.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: confirm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Plugin Settings
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:plugin-settings` or directly via `/mastermind:plugin-settings`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
17
|
+
- `plugin_id`: plugin id to manage (required)
|
|
18
|
+
- `org_name`: org scope (optional — uses global registry if omitted)
|
|
19
|
+
- `action`: show | config | status | grants | set-config | add-grant | remove-grant
|
|
20
|
+
- `config_key`: config key to set (for set-config)
|
|
21
|
+
- `config_value`: config value (for set-config)
|
|
22
|
+
- `grant_path`: filesystem path to grant access to (for add-grant/remove-grant)
|
|
23
|
+
- `grant_access`: read | write | readwrite (for add-grant, default: read)
|
|
24
|
+
- `caller`: command | master
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Plugin Configuration Model
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"id": "plugin-slug",
|
|
33
|
+
"packageName": "@monomind/plugin-name",
|
|
34
|
+
"status": "installed",
|
|
35
|
+
"version": "1.2.0",
|
|
36
|
+
"category": "monitoring",
|
|
37
|
+
"config": {
|
|
38
|
+
"apiKey": "***",
|
|
39
|
+
"webhookUrl": "https://...",
|
|
40
|
+
"customField": "value"
|
|
41
|
+
},
|
|
42
|
+
"grants": [
|
|
43
|
+
{ "path": "/tmp/plugin-data", "access": "readwrite" },
|
|
44
|
+
{ "path": "/project/logs", "access": "read" }
|
|
45
|
+
],
|
|
46
|
+
"health": {
|
|
47
|
+
"status": "ok",
|
|
48
|
+
"lastCheck": "2026-01-01T00:00:00Z",
|
|
49
|
+
"message": null
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Step 0 — Brain Load (standalone only)
|
|
57
|
+
|
|
58
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Step 1 — Load Plugin Registry
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
registryFile=".monomind/plugins/registry.json"
|
|
66
|
+
[ ! -f "$registryFile" ] && { echo "ERROR: No plugin registry found. Install plugins via /mastermind:plugins."; exit 1; }
|
|
67
|
+
|
|
68
|
+
pluginDef=$(jq -r --arg id "$plugin_id" '.plugins[] | select(.id == $id)' "$registryFile")
|
|
69
|
+
[ -z "$pluginDef" ] && { echo "ERROR: Plugin '$plugin_id' not found. List plugins via /mastermind:plugins --action list."; exit 1; }
|
|
70
|
+
|
|
71
|
+
# Load org-level overrides if org_name specified
|
|
72
|
+
orgPluginsFile=""
|
|
73
|
+
if [ -n "$org_name" ]; then
|
|
74
|
+
orgPluginsFile=".monomind/orgs/${org_name}-plugins.json"
|
|
75
|
+
orgOverride=$([ -f "$orgPluginsFile" ] && jq -r --arg id "$plugin_id" '.plugins[] | select(.id == $id)' "$orgPluginsFile" || echo "")
|
|
76
|
+
fi
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Step 2 — Execute Action
|
|
82
|
+
|
|
83
|
+
### show (default)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
echo "PLUGIN — $plugin_id"
|
|
87
|
+
echo "────────────────────────────────────────────────────────"
|
|
88
|
+
|
|
89
|
+
echo "$pluginDef" | jq -r '
|
|
90
|
+
" ID: \(.id)",
|
|
91
|
+
" Package: \(.packageName // "-")",
|
|
92
|
+
" Version: \(.version // "-")",
|
|
93
|
+
" Status: \(.status // "unknown")",
|
|
94
|
+
" Category: \(.category // "general")",
|
|
95
|
+
" Local path: \(if .isLocalPath then "yes" else "no" end)",
|
|
96
|
+
" Installed: \(.installedAt // "-")"
|
|
97
|
+
'
|
|
98
|
+
|
|
99
|
+
if [ -n "$orgOverride" ] && [ "$orgOverride" != "null" ]; then
|
|
100
|
+
echo ""
|
|
101
|
+
echo " ORG OVERRIDE ($org_name):"
|
|
102
|
+
echo "$orgOverride" | jq -r '" Status: \(.status // "inherited")"'
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
# Config summary
|
|
106
|
+
configCount=$(echo "$pluginDef" | jq -r '(.config // {}) | length')
|
|
107
|
+
echo ""
|
|
108
|
+
echo " Config fields: $configCount"
|
|
109
|
+
echo " Grants: $(echo "$pluginDef" | jq -r '(.grants // []) | length')"
|
|
110
|
+
|
|
111
|
+
# Health
|
|
112
|
+
healthStatus=$(echo "$pluginDef" | jq -r '.health.status // "unknown"')
|
|
113
|
+
healthMsg=$(echo "$pluginDef" | jq -r '.health.message // ""')
|
|
114
|
+
echo " Health: $healthStatus${healthMsg:+ — $healthMsg}"
|
|
115
|
+
|
|
116
|
+
# Last error
|
|
117
|
+
lastErr=$(echo "$pluginDef" | jq -r '.lastError // ""')
|
|
118
|
+
[ -n "$lastErr" ] && echo "" && echo " LAST ERROR: $lastErr"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### config
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
echo "CONFIG — $plugin_id"
|
|
125
|
+
echo "────────────────────────────────────────────────────────"
|
|
126
|
+
|
|
127
|
+
config=$(echo "$pluginDef" | jq -r '.config // {}')
|
|
128
|
+
count=$(echo "$config" | jq 'length')
|
|
129
|
+
|
|
130
|
+
if [ "$count" -eq 0 ]; then
|
|
131
|
+
echo " No configuration fields."
|
|
132
|
+
echo " Set a field: --action set-config --config-key <key> --config-value <value>"
|
|
133
|
+
else
|
|
134
|
+
echo "$config" | jq -r 'to_entries[] |
|
|
135
|
+
if (.value | type) == "string" and (.key | test("key|token|secret|password|api"; "i")) then
|
|
136
|
+
" \(.key) = ***"
|
|
137
|
+
else
|
|
138
|
+
" \(.key) = \(.value)"
|
|
139
|
+
end'
|
|
140
|
+
fi
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### status
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
echo "PLUGIN STATUS — $plugin_id"
|
|
147
|
+
echo "────────────────────────────────────────────────────────"
|
|
148
|
+
|
|
149
|
+
echo "$pluginDef" | jq -r '
|
|
150
|
+
" Status: \(.status // "unknown")",
|
|
151
|
+
" Version: \(.version // "-")",
|
|
152
|
+
" Installed: \(.installedAt // "-")"
|
|
153
|
+
'
|
|
154
|
+
|
|
155
|
+
health=$(echo "$pluginDef" | jq -r '.health // {}')
|
|
156
|
+
healthStatus=$(echo "$health" | jq -r '.status // "unknown"')
|
|
157
|
+
lastCheck=$(echo "$health" | jq -r '.lastCheck // "-"')
|
|
158
|
+
healthMsg=$(echo "$health" | jq -r '.message // ""')
|
|
159
|
+
|
|
160
|
+
echo ""
|
|
161
|
+
echo "HEALTH CHECK"
|
|
162
|
+
echo " Status: $healthStatus"
|
|
163
|
+
echo " Last: $lastCheck"
|
|
164
|
+
[ -n "$healthMsg" ] && echo " Message: $healthMsg"
|
|
165
|
+
|
|
166
|
+
# Error
|
|
167
|
+
lastErr=$(echo "$pluginDef" | jq -r '.lastError // ""')
|
|
168
|
+
if [ -n "$lastErr" ]; then
|
|
169
|
+
echo ""
|
|
170
|
+
echo "LAST ERROR"
|
|
171
|
+
echo " $lastErr"
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
# Suggest reload
|
|
175
|
+
[ "$healthStatus" = "error" ] && echo "" && echo " Run: /mastermind:plugins --action reload --plugin-id $plugin_id"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### grants
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
echo "FILE SYSTEM GRANTS — $plugin_id"
|
|
182
|
+
echo "────────────────────────────────────────────────────────"
|
|
183
|
+
printf "%-6s %s\n" "ACCESS" "PATH"
|
|
184
|
+
echo "────────────────────────────────────────────────────────"
|
|
185
|
+
|
|
186
|
+
grants=$(echo "$pluginDef" | jq -r '(.grants // [])[]' 2>/dev/null)
|
|
187
|
+
if [ -z "$grants" ]; then
|
|
188
|
+
echo " No file system grants."
|
|
189
|
+
echo " Add a grant: --action add-grant --grant-path /path/to/dir --grant-access read"
|
|
190
|
+
else
|
|
191
|
+
echo "$pluginDef" | jq -r '(.grants // [])[] |
|
|
192
|
+
" \(.access // "read")\t\(.path)"' | while IFS=$'\t' read -r acc path; do
|
|
193
|
+
printf " %-10s %s\n" "$acc" "$path"
|
|
194
|
+
done
|
|
195
|
+
fi
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### set-config
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
[ -z "$config_key" ] && { echo "ERROR: --config-key required."; exit 1; }
|
|
202
|
+
[ -z "$config_value" ] && { echo "ERROR: --config-value required."; exit 1; }
|
|
203
|
+
|
|
204
|
+
tmp="${registryFile}.tmp"
|
|
205
|
+
jq --arg id "$plugin_id" --arg k "$config_key" --arg v "$config_value" \
|
|
206
|
+
'.plugins = [.plugins[] | if .id == $id then
|
|
207
|
+
if .config == null then .config = {} else . end |
|
|
208
|
+
.config[$k] = $v
|
|
209
|
+
else . end]' \
|
|
210
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
211
|
+
|
|
212
|
+
# Mask value in output if sensitive key
|
|
213
|
+
if echo "$config_key" | grep -qiE "key|token|secret|password|api"; then
|
|
214
|
+
echo "Config set: $config_key = ***"
|
|
215
|
+
else
|
|
216
|
+
echo "Config set: $config_key = $config_value"
|
|
217
|
+
fi
|
|
218
|
+
echo "NOTE: Restart agents or reload the plugin for changes to take effect."
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### add-grant
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
[ -z "$grant_path" ] && { echo "ERROR: --grant-path required."; exit 1; }
|
|
225
|
+
access="${grant_access:-read}"
|
|
226
|
+
case "$access" in read|write|readwrite) : ;; *)
|
|
227
|
+
echo "ERROR: --grant-access must be read, write, or readwrite"; exit 1 ;;
|
|
228
|
+
esac
|
|
229
|
+
|
|
230
|
+
tmp="${registryFile}.tmp"
|
|
231
|
+
jq --arg id "$plugin_id" --arg path "$grant_path" --arg access "$access" \
|
|
232
|
+
'.plugins = [.plugins[] | if .id == $id then
|
|
233
|
+
.grants = ((.grants // []) | map(select(.path != $path))) +
|
|
234
|
+
[{"path":$path,"access":$access}]
|
|
235
|
+
else . end]' \
|
|
236
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
237
|
+
|
|
238
|
+
echo "Grant added: $access → $grant_path"
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### remove-grant
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
[ -z "$grant_path" ] && { echo "ERROR: --grant-path required."; exit 1; }
|
|
245
|
+
|
|
246
|
+
tmp="${registryFile}.tmp"
|
|
247
|
+
jq --arg id "$plugin_id" --arg path "$grant_path" \
|
|
248
|
+
'.plugins = [.plugins[] | if .id == $id then
|
|
249
|
+
.grants = [(.grants // [])[] | select(.path != $path)]
|
|
250
|
+
else . end]' \
|
|
251
|
+
"$registryFile" > "$tmp" && mv "$tmp" "$registryFile"
|
|
252
|
+
|
|
253
|
+
echo "Grant removed: $grant_path"
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Step 3 — Return Output
|
|
259
|
+
|
|
260
|
+
```yaml
|
|
261
|
+
domain: ops
|
|
262
|
+
status: complete
|
|
263
|
+
action: <action>
|
|
264
|
+
plugin_id: <plugin_id>
|
|
265
|
+
plugin_status: <status>
|
|
266
|
+
health_status: <health>
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Step 4 — Brain Write (standalone only)
|
|
272
|
+
|
|
273
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|