Mastermind workspaces — manage isolated git worktree workspaces per project. List, attach, detach, stop, and prune workspaces. Grouped by project with running service counts and agent assignments.
Scanned 9/10/2026
Install to Claude Code
npx -y skills add monoes/monomind --skill mastermind-workspaces --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Mastermind Workspaces?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/monoes-mastermind-workspaces)More formats (shields.io, HTML) on the badges page.
---
name: mastermind-workspaces
description: Mastermind workspaces — manage isolated git worktree workspaces per project. List, attach, detach, stop, and prune workspaces. Grouped by project with running service counts and agent assignments.
type: domain-skill
default_mode: confirm
---
# Mastermind Workspaces
This skill is invoked by `mastermind:workspaces` or directly via `/mastermind:workspaces`.
---
## Inputs
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
- `org_name`: org to manage workspaces for (required)
- `action`: list | status | attach | detach | stop | prune
- `workspace_id`: workspace id (required for status/detach/stop)
- `project_id`: project to filter by (optional for list)
- `agent_id`: agent to assign to workspace (required for attach)
- `worktree_path`: filesystem path of the worktree (required for attach)
- `caller`: command | master
---
## Workspace Model
A workspace is a git worktree assigned to a project, optionally running services and assigned to an agent.
```json
{
"id": "ws-abc123",
"project_id": "project-slug",
"agent_id": "backend-dev",
"worktree_path": "/tmp/monomind/worktrees/project-slug-abc123",
"branch": "feat/my-feature",
"status": "active",
"services": ["dev-server", "db-watcher"],
"createdAt": "2026-01-01T00:00:00Z",
"lastActiveAt": "2026-01-02T00:00:00Z"
}
```
---
## Step 0 — Brain Load (standalone only)
If `caller` is not "command", load brain context following mastermind-protocol/SKILL.md Brain Load Procedure with namespace: `ops`.
---
## Step 1 — Load Workspace Data
```bash
orgFile=".monomind/orgs/${org_name}.json"
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
wsFile=".monomind/orgs/${org_name}-workspaces.json"
[ ! -f "$wsFile" ] && echo '{"workspaces":[]}' > "$wsFile"
projectsFile=".monomind/orgs/${org_name}-projects.json"
worktreeRegistry=".monomind/orgs/${org_name}-worktrees.json"
```
---
## Step 2 — Execute Action
### list (default)
```bash
echo "WORKSPACES — org: $org_name"
[ -n "$project_id" ] && echo "(filtered by project: $project_id)"
echo "────────────────────────────────────────────────────────"
total=$(jq '.workspaces | length' "$wsFile")
if [ "$total" -eq 0 ]; then
echo " No workspaces. Use --action attach to register one."
else
# Group by project
projects=$(jq -r --arg pid "${project_id:-}" '
.workspaces |
if $pid != "" then map(select(.project_id == $pid)) else . end |
[.[].project_id] | unique[]
' "$wsFile")
while IFS= read -r proj; do
[ -z "$proj" ] && continue
projName=$([ -f "$projectsFile" ] && jq -r --arg pid "$proj" '(.projects // [])[] | select(.id == $pid) | .name // $pid' "$projectsFile" || echo "$proj")
echo ""
echo " PROJECT: $projName"
echo " ──────────────────────────────────────────────────"
printf " %-18s %-14s %-18s %-12s %-6s %s\n" "ID" "STATUS" "AGENT" "BRANCH" "SVCS" "PATH"
jq -r --arg pid "$proj" '(.workspaces // [])[] | select(.project_id == $pid) |
[.id, (.status // "unknown"), (.agent_id // "(none)"),
(.branch // "?"), ((.services // []) | length | tostring),
(.worktree_path // "-")]
| @tsv' "$wsFile" | while IFS=$'\t' read -r id st ag br svc path; do
printf " %-18s %-14s %-18s %-12s %-6s %s\n" "$id" "$st" "$ag" "$br" "$svc" "$path"
done
done <<< "$projects"
fi
echo ""
echo "Total: $total workspace(s)"
```
### status
```bash
[ -z "$workspace_id" ] && { echo "ERROR: --workspace-id required."; exit 1; }
wsDef=$(jq -r --arg id "$workspace_id" '(.workspaces // [])[] | select(.id == $id)' "$wsFile")
[ -z "$wsDef" ] && { echo "ERROR: Workspace '$workspace_id' not found."; exit 1; }
echo "WORKSPACE STATUS — $workspace_id"
echo "────────────────────────────────────────────────────────"
echo "$wsDef" | jq -r '
" ID: \(.id)",
" Project: \(.project_id // "-")",
" Agent: \(.agent_id // "(unassigned)")",
" Branch: \(.branch // "?")",
" Status: \(.status // "unknown")",
" Created: \(.createdAt // "-")",
" Last active: \(.lastActiveAt // "-")",
" Path: \(.worktree_path // "-")"
'
# Check if worktree path exists
path=$(echo "$wsDef" | jq -r '.worktree_path // ""')
if [ -n "$path" ]; then
if [ -d "$path" ]; then
echo ""
echo " Worktree: EXISTS at $path"
branch=$(git -C "$path" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "?")
echo " Git branch: $branch"
dirty=$(git -C "$path" status --porcelain 2>/dev/null | wc -l | tr -d ' ')
[ "$dirty" -gt 0 ] && echo " Uncommitted changes: $dirty file(s)"
else
echo " WARNING: Worktree path does not exist: $path"
fi
fi
echo ""
echo "Services:"
echo "$wsDef" | jq -r '(.services // [])[] | " · \(.)"' || echo " (none)"
```
### attach
```bash
[ -z "$project_id" ] && { echo "ERROR: --project-id required."; exit 1; }
[ -z "$worktree_path" ] && { echo "ERROR: --worktree-path required."; exit 1; }
[ ! -d "$worktree_path" ] && { echo "ERROR: Path does not exist: $worktree_path"; exit 1; }
wsId="ws-$(openssl rand -hex 4 2>/dev/null || python3 -c 'import secrets; print(secrets.token_hex(4))')"
branch=$(git -C "$worktree_path" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
tmp="${wsFile}.tmp"
jq --arg id "$wsId" \
--arg pid "$project_id" \
--arg ag "${agent_id:-}" \
--arg path "$worktree_path" \
--arg branch "$branch" \
--arg ts "$ts" \
'.workspaces += [{"id":$id,"project_id":$pid,
"agent_id":(if $ag != "" then $ag else null end),
"worktree_path":$path,"branch":$branch,
"status":"active","services":[],"createdAt":$ts,"lastActiveAt":$ts}]' \
"$wsFile" > "$tmp" && mv "$tmp" "$wsFile"
echo "Workspace attached: $wsId"
echo " Project: $project_id"
echo " Agent: ${agent_id:-(unassigned)}"
echo " Branch: $branch"
echo " Path: $worktree_path"
```
### detach
```bash
[ -z "$workspace_id" ] && { echo "ERROR: --workspace-id required."; exit 1; }
tmp="${wsFile}.tmp"
jq --arg id "$workspace_id" \
'.workspaces = [(.workspaces // [])[] | if .id == $id then .status = "detached" else . end]' \
"$wsFile" > "$tmp" && mv "$tmp" "$wsFile"
echo "Workspace '$workspace_id' → detached. The worktree is preserved on disk."
```
### stop
```bash
[ -z "$workspace_id" ] && { echo "ERROR: --workspace-id required."; exit 1; }
wsDef=$(jq -r --arg id "$workspace_id" '(.workspaces // [])[] | select(.id == $id)' "$wsFile")
[ -z "$wsDef" ] && { echo "ERROR: Workspace '$workspace_id' not found."; exit 1; }
services=$(echo "$wsDef" | jq -r '(.services // [])[]')
if [ -n "$services" ]; then
echo "Stopping services for workspace $workspace_id…"
while IFS= read -r svc; do
echo " Stopping: $svc"
done <<< "$services"
fi
tmp="${wsFile}.tmp"
jq --arg id "$workspace_id" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
'.workspaces = [(.workspaces // [])[] | if .id == $id then .status = "stopped" | .services = [] | .lastActiveAt = $ts else . end]' \
"$wsFile" > "$tmp" && mv "$tmp" "$wsFile"
echo "Workspace '$workspace_id' stopped."
```
### prune
```bash
echo "Pruning stopped/detached workspaces for org '$org_name'…"
before=$(jq '.workspaces | length' "$wsFile")
removed=0
orphaned=0
tmp="${wsFile}.tmp"
jq '.workspaces = [(.workspaces // [])[] | select(.status != "stopped" and .status != "detached")]' \
"$wsFile" > "$tmp" && mv "$tmp" "$wsFile"
after=$(jq '.workspaces | length' "$wsFile")
removed=$((before - after))
# Find orphaned worktrees (path gone)
while IFS= read -r path; do
{ [ -z "$path" ] || [ "$path" = "null" ]; } && continue
[ ! -d "$path" ] && orphaned=$((orphaned + 1))
done < <(jq -r '(.workspaces // [])[].worktree_path // ""' "$wsFile")
echo " Removed $removed stopped/detached workspace record(s)."
[ "$orphaned" -gt 0 ] && echo " WARNING: $orphaned workspace(s) have missing worktree paths. Run --action status to investigate."
echo "Done. Active workspaces: $(jq '.workspaces | length' "$wsFile")"
```
---
## Step 3 — Return Output
```yaml
domain: ops
status: complete
action: <action>
org: <org_name>
workspace_id: <id if applicable>
workspaces_total: <N>
```
---
## Step 4 — Brain Write (standalone only)
If `caller` is not "command", follow mastermind-protocol/SKILL.md Brain Write Procedure for domain `ops`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!