From obsidian
Build and schedule a personalized Operator prompt that runs the user's second brain on a recurring cadence. The skill is invoked from inside the vault folder locally — it reads `Context/` and `CLAUDE.md` first to infer org, team, brand voice, and paths, then asks ONLY the gaps it can't determine (cadence, connectors, DM recipient, budgets, signature). Fills `references/operator-prompt-template.md`, writes the rendered prompt locally, then invokes the `schedule` skill to wire up the recurring trigger automatically. Template is a generic version of a battle-tested vault Operator spec — cadence awareness, freshness, daily-as-state, idle-timeout protection, principles, hard rules, failure handling, report schema. Use when the user says "set up the operator", "build my operator prompt", "operate my second brain", "schedule my OS", "os operator", "vault operator", or runs /os-operator.
How this skill is triggered — by the user, by Claude, or both
Slash command
/obsidian:os-operatorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build a personalized Operator prompt that runs the user's second brain on a recurring schedule. The Operator is a fully autonomous maintenance agent — one session = one run, no questions, no confirmations, executes and reports.
Build a personalized Operator prompt that runs the user's second brain on a recurring schedule. The Operator is a fully autonomous maintenance agent — one session = one run, no questions, no confirmations, executes and reports.
This skill does four jobs, in order:
Context/ and CLAUDE.md silently — extract org name, team scope, brand voice, vault folders, runtime conventions.schedule skill (via the Skill tool) so the trigger is wired before the run ends — the user does not need to manually run /schedule create.references/operator-prompt-template.md — the parameterized prompt. ~400 lines, preserves every critical rule from the source spec.references/connector-fragments.md — spliceable body blocks per connector (transcripts, chat, community).Read both before generating output.
The user invokes this skill from inside their vault folder locally. Everything here is filesystem-only. Do NOT call any vault_* MCP tools — the Vault MCP only matters at runtime when the rendered Operator agent runs.
claude.md or CLAUDE.md must exist at the cwd root. If neither exists, ask the user to cd into their vault and re-run. Do not proceed.Glob pattern */ at cwd. Cache the result as {{VAULT_FOLDERS}} (one folder name per line).CLAUDE.md. Pull conventions: signature style, em-dash rule, voice rules, folder routing, any explicit operator paths, os-mode (professional vs business).Context/. Whichever exist:
Context/me.md — operator profile (name, role, focus)Context/operator.md — same, business-mode equivalentContext/business.md / Context/organization.md — org name, mission, products, locationsContext/team.md — team member full names, roles, who handles whatContext/brand.md — voice, colors (look for hex codes that could seed the signature)Context/strategy.md — current focus, OKRs (informs which workstreams the operator emphasises)Context/stakeholders.md — external people the operator should be aware of (not in team scope, but referenced){{ORG_NAME}} ← from Context/business.md or organization.md (title heading or name: frontmatter). If none, fall back to the cwd folder name.{{TEAM_MEMBERS}} ← comma-separated full names from Context/team.md. If solo (os-mode: professional), use the operator's own name from Context/me.md.{{EXAMPLE_TEAM_MEMBER}} ← first name in {{TEAM_MEMBERS}}.{{OPERATOR_NAME}} (default) ← {{ORG_NAME}} Vault Operator.{{OPERATOR_HANDLE}} ← slugified, e.g. Vault-Operator.{{OPERATOR_BASE_PATH}} ← /Team/{{ORG_NAME}}/Profiles/Vault-Operator/ if Team/ is one of the discovered top-level folders, else /{{ORG_NAME}}/Vault-Operator/.{{PROFILE_BASE_PATH_PATTERN}} ← /Team/{{ORG_NAME}}/Profiles/{Name}/ if applicable.{{SIGNATURE_BG_COLOR}} ← any brand color hex found in Context/brand.md, else #D2ECD0.{{SIGNATURE_FG_COLOR}} ← #020309.After Phase 0, summarise to the user in 4–6 short lines what you found. Format:
Discovered from your vault:
- Org:
{{ORG_NAME}}- Team:
{{TEAM_MEMBERS}}- Top-level folders:
{count}({list first 5})- Operator path (proposed):
{{OPERATOR_BASE_PATH}}- Brand signature color (proposed):
{{SIGNATURE_BG_COLOR}}Anything to override? (Type the field name, or say "looks good" to continue.)
If the user wants overrides, accept them inline (one short follow-up) and update the cache. If "looks good", proceed straight to Phase 1.
Do not re-ask any of the above as standalone questions. They were inferred. Phase 1 is for things the vault genuinely cannot tell you.
These are the questions the vault cannot answer. Ask one at a time with AskUserQuestion.
AskUserQuestion with options:
Save as {{CADENCE_HUMAN}} and {{CADENCE_TAG}}.
Don't show the user a checklist of connectors and trust their answer. Probe what's actually wired up in this environment, then confirm.
Inspect the running session's available tools. Look for tool names matching these prefixes (any namespace — mcp__*, plain, or vendor-specific):
| Category | Detection signal | Live probe (read-only) |
|---|---|---|
| Vault | vault_* (e.g. vault_folders, vault_relays, vault_list) | Call vault_folders (or equivalent). Success = list of folder names. |
| Transcripts | fireflies_*, otter_*, granola_*, read_ai_* | Call the connector's "list recent" / "get transcripts" with a 1-item or 24h window. Success = ≥0 results, no auth error. |
| Chat | slack_*, teams_*, discord_*, telegram_* | Call the connector's "list channels" / "search users" / equivalent read-only call. Success = response, no auth error. |
| Community | circle_*, discourse_* | Call list_spaces / categories with per_page: 1. Success = response. |
Run all detected probes in parallel in one batch. Narrate before the batch ("Probing 3 connectors live: vault, fireflies, slack…") and after ("Vault OK (13 folders). Fireflies OK. Slack auth error.").
For each connector:
{{*_MCP_NAME}} and infer the product name (e.g. fireflies → Fireflies)./os-operator later after wiring a new MCP.Show one summary block:
Connectors detected:
- ✅ Vault MCP —
relay-mcp(13 folders)- ✅ Transcripts —
fireflies(last transcript: 2 hours ago)- ✅ Chat —
slack(12 channels visible)- ❌ Community — none detected
Use these in the Operator? (yes / customize)
If the user says "customize", let them toggle individual entries off (but never on for something not detected — they need to wire that MCP first). If they say "yes" or just confirm, proceed.
{{TRANSCRIPT_PRODUCT_NAME}} and {{TRANSCRIPT_MCP_NAME}}{{CHAT_PRODUCT_NAME}} and {{CHAT_MCP_NAME}}{{COMMUNITY_PRODUCT_NAME}} and {{COMMUNITY_MCP_NAME}}{{VAULT_MCP_NAME}} (whatever the probe identified — default relay-mcp if ambiguous)Probes are read-only by design. Never invoke a write/send tool during detection (no DMs, no posts, no file writes).
Some MCP servers (Relay-style) expose vault-root files under a named folder like Shared Files (root) rather than /. The rendered prompt needs to know this exact string so the Operator's vault_* calls work.
AskUserQuestion with options:
Shared Files (root) — Relay MCP default./ — most other MCPs.Save as {{ROOT_FOLDER_NAME}}.
When the Operator finds a community post or chat thread that needs human action, who receives the 1:1 escalation DM? One person only. No channels, no groups.
Default the picker to names in {{TEAM_MEMBERS}} so the user can pick rather than retype. Save as {{DM_RECIPIENT_NAME}}.
If no chat connector is enabled, skip this question. Set {{DM_RECIPIENT_NAME}} to the operator's own name from Context/me.md/operator.md — the placeholder is referenced in a few sections that will be stripped during render anyway.
AskUserQuestion with options:
Save as {{BUDGET_READS}}, {{BUDGET_WRITES}}, {{BUDGET_TRANSCRIPTS}}, {{BUDGET_DMS}}, {{BUDGET_HOUSEKEEPING}}.
If Context/brand.md already gave a brand color, skip this. Otherwise:
The Operator stamps every file it edits with a colored span. Pick a background color (default:
#D2ECD0, soft mint green). Foreground default:#020309.
Save as {{SIGNATURE_BG_COLOR}} and {{SIGNATURE_FG_COLOR}}.
references/operator-prompt-template.md.references/connector-fragments.md.{{PLACEHOLDER}} with the captured value. For connector-specific placeholders ({{TRANSCRIPTS_BOOTSTRAP_LINE}}, {{CHAT_BOOTSTRAP_LINE}}, {{COMMUNITY_BOOTSTRAP_LINE}}, {{TRANSCRIPTS_STEP_BODY}}, {{COMMUNITY_STEP_BODY}}, {{CHAT_STEP_BODY}}, {{ENABLED_CONNECTORS_LINE}}, {{MCP_BLOCK}}):
connector-fragments.md, then re-run placeholder substitution on any nested placeholders.{{OPERATOR_BASE_PATH}} and {{PROFILE_BASE_PATH_PATTERN}} so MCP examples are correct:
{{OPERATOR_TASK_LIST_PATH}} = {{OPERATOR_BASE_PATH}}task-list/Tasks.md{{OPERATOR_TASK_LIST_FOLDER}} and {{OPERATOR_TASK_LIST_SUBPATH}}{{OPERATOR_REPORT_PATH_PATTERN}} = {{OPERATOR_BASE_PATH}}Daily/{YYYY-MM-DD}-daily.md{{PROFILE_DAILY_PATH_PATTERN}}, {{PROFILE_DAILY_FOLDER}}, {{PROFILE_DAILY_PATH_FORMAT}}, {{PROFILE_DAILY_PATH_EXAMPLE}}, {{PROFILE_DAILY_SUBPATH_EXAMPLE}}{{...}} strings. If any remain, fix or flag to the user before saving.Show the user a short preview (title, cadence line, team scope, the rendered MCP block) and ask one yes/no: "Save it?"
If yes:
Write tool against the local filesystem.{{OPERATOR_BASE_PATH}}operator-prompt.md resolved relative to the cwd (the vault root). Strip the leading / from {{OPERATOR_BASE_PATH}} when resolving locally.Read it back to confirm content present.If the file already exists, ask before overwriting.
After the prompt is saved, immediately invoke the schedule skill via the Skill tool. Do not stop at "saved". Do not tell the user to run /schedule create themselves — wire the trigger now.
Convert {{CADENCE_HUMAN}} into a cron expression for the schedule skill:
| Cadence | Cron |
|---|---|
| Hourly | 0 * * * * |
| Every 4 hours | 0 */4 * * * |
| Daily | 0 9 * * * (9am local; ask if they want a different hour) |
| Custom | use what the user typed |
The schedule skill creates a remote trigger that runs Claude Code on a cron. Hand it:
"Run the Operator. Read and execute @{{OPERATOR_BASE_PATH}}operator-prompt.md exactly as written. One run = one report. Stop when done."{{OPERATOR_HANDLE}}-{{CADENCE_TAG}} (e.g. Vault-Operator-hourly)."{{OPERATOR_NAME}} — {{CADENCE_HUMAN}}".Call the Skill tool with skill: "schedule" and pass the args described above. Let the schedule skill do its own confirmation flow with the user (timezone, confirm cron, etc.) — it owns that interaction.
If the schedule skill is not installed in the user's environment, fall back to a clear text instruction with the exact cron expression and prompt to paste. Do not pretend the trigger is wired when it isn't.
Tell the user, in one short paragraph:
Operator prompt saved to
{{OPERATOR_BASE_PATH}}operator-prompt.mdand scheduled{{CADENCE_HUMAN}}(cron{cron}). First run will fire on the next tick. Manage the trigger anytime with/schedule listor/schedule update.
Stop. Do not propose other follow-ups.
Context/ and CLAUDE.md before asking anything. Never ask for a value the vault already contains.Glob, Read, and Write against the local filesystem for everything except connector probes. Vault MCP is only used at runtime by the rendered Operator agent, OR briefly during Phase 1 Q2 as a live probe to confirm the MCP is wired and authenticated.schedule skill in the same run. Do not stop at "saved" and tell the user to schedule it themselves.CLAUDE.md. The Operator owns that file at runtime, not the builder.Slack and Circle should not appear anywhere in the rendered prompt.{{ after render. Catch unfilled placeholders before saving.npx claudepluginhub benaios/benai-skills-main --plugin obsidianBuilds a throwaway prototype to answer a design question about UI appearance or state/logic behavior. Guides you through two branches: interactive terminal app for logic validation, or multiple UI variations for visual exploration.