Bladeren bron

Small annoyance fixes (#330)

* Toast config

* Improve installer onboarding output

Replace fragile Unicode status symbols with ASCII-safe output and align the installer next steps with the README onboarding flow so first-run setup is clearer.

* Bundle simplify skill by default

Bundle the simplify skill locally, assign it to Oracle by default, and streamline the installer by enabling skills by default and removing unused summary and tmux options.

* Preserve parent agent in task notifications

Send background task completion and failure notifications with the parent session's tracked agent so nested subagent sessions do not silently switch back to the default orchestrator agent.

* Exclude context7 from orchestrator defaults

Keep broad MCP access for the orchestrator while removing Context7 from its default MCP list, leaving official docs lookup to the librarian by default.

* Tune fixer prompt
Alvin 3 maanden geleden
bovenliggende
commit
0261f0565b

+ 8 - 4
AGENTS.md

@@ -92,10 +92,14 @@ oh-my-opencode-slim/
 ## Development Workflow
 
 1. Make code changes
-2. Run `bun run check:ci` to verify linting and formatting
-3. Run `bun run typecheck` to verify types
-4. Run `bun test` to verify tests pass
-5. Commit changes
+2. Update docs when behavior, commands, configuration, workflows, or user-facing output changes
+   - Check `README.md` plus relevant files in `docs/`
+   - Keep examples, command snippets, and feature lists in sync with the code
+   - If no doc update is needed, explicitly confirm that in your final summary
+3. Run `bun run check:ci` to verify linting and formatting
+4. Run `bun run typecheck` to verify types
+5. Run `bun test` to verify tests pass
+6. Commit changes
 
 ## Tmux Session Lifecycle Management
 

+ 3 - 3
README.md

@@ -58,10 +58,10 @@ The default generated configuration looks like this:
   "preset": "openai",
   "presets": {
     "openai": {
-      "orchestrator": { "model": "openai/gpt-5.4", "variant": "high", "skills": ["*"], "mcps": ["*"] },
-      "oracle": { "model": "openai/gpt-5.4", "variant": "high", "skills": [], "mcps": [] },
+      "orchestrator": { "model": "openai/gpt-5.4", "variant": "high", "skills": ["*"], "mcps": ["*", "!context7"] },
+      "oracle": { "model": "openai/gpt-5.4", "variant": "high", "skills": ["simplify"], "mcps": [] },
       "librarian": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": [], "mcps": ["websearch", "context7", "grep_app"] },
-      "explorer": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": [], "mcps": [] },
+      "explorer": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": ["cartography"], "mcps": [] },
       "designer": { "model": "openai/gpt-5.4-mini", "variant": "medium", "skills": ["agent-browser"], "mcps": [] },
       "fixer": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": [], "mcps": [] }
     }

+ 12 - 0
docs/configuration.md

@@ -91,6 +91,7 @@ All config files support **JSONC** (JSON with Comments):
 | `presets.<name>.<agent>.mcps` | string[] | — | MCPs the agent can use (`"*"`, `"!item"`, explicit list) |
 | `presets.<name>.<agent>.options` | object | — | Provider-specific model options passed to the AI SDK (e.g., `textVerbosity`, `thinking` budget) |
 | `agents.<agent>.displayName` | string | — | Custom user-facing alias for the agent in the active config |
+| `showStartupToast` | boolean | `true` | Show the startup activation toast (`oh-my-opencode-slim is active`) when OpenCode starts |
 | `tmux.enabled` | boolean | `false` | Enable tmux pane spawning |
 | `tmux.layout` | string | `"main-vertical"` | Layout: `main-vertical`, `main-horizontal`, `tiled`, `even-horizontal`, `even-vertical` |
 | `tmux.main_pane_size` | number | `60` | Main pane size as percentage (20–80) |
@@ -125,6 +126,17 @@ All config files support **JSONC** (JSON with Comments):
 | `interview.port` | integer | `0` | Interview server port (0–65535). `0` = OS-assigned random port (per-session mode). Any value > 0 enables [dashboard mode](interview.md#dashboard-mode) |
 | `interview.dashboard` | boolean | `false` | Enable [dashboard mode](interview.md#dashboard-mode) on the default port (43211). Setting `port` > 0 also enables dashboard mode. If both are set, `port` takes precedence |
 
+### Startup Toast
+
+Set `showStartupToast` to `false` if you want to disable the startup toast that
+appears when the plugin activates.
+
+```jsonc
+{
+  "showStartupToast": false
+}
+```
+
 ### Agent Display Names
 
 Use `displayName` to give an agent a user-facing alias while keeping the

+ 29 - 16
docs/installation.md

@@ -24,7 +24,7 @@ bunx oh-my-opencode-slim@latest install
 Or use non-interactive mode:
 
 ```bash
-bunx oh-my-opencode-slim@latest install --no-tui --tmux=no --skills=yes
+bunx oh-my-opencode-slim@latest install --no-tui --skills=yes
 ```
 
 ### Configuration Options
@@ -33,8 +33,7 @@ The installer supports the following options:
 
 | Option | Description |
 |--------|-------------|
-| `--tmux=yes|no` | Enable tmux integration (yes/no) |
-| `--skills=yes|no` | Install recommended skills (yes/no) |
+| `--skills=yes|no` | Install recommended and bundled skills (default: yes) |
 | `--no-tui` | Non-interactive mode |
 | `--dry-run` | Simulate install without writing files |
 | `--reset` | Force overwrite of existing configuration |
@@ -44,7 +43,7 @@ The installer supports the following options:
 By default, the installer is non-destructive. If an `oh-my-opencode-slim.json` configuration file already exists, the installer will **not** overwrite it. Instead, it will display a message:
 
 ```
- Configuration already exists at ~/.config/opencode/oh-my-opencode-slim.json. Use --reset to overwrite.
+[i] Configuration already exists at ~/.config/opencode/oh-my-opencode-slim.json. Use --reset to overwrite.
 ```
 
 To force overwrite of your existing configuration, use the `--reset` flag:
@@ -57,16 +56,27 @@ bunx oh-my-opencode-slim@latest install --reset
 
 ### After Installation
 
-The installer generates an OpenAI configuration by default (using `gpt-5.4` and `gpt-5-codex` models). To use alternative providers like Kimi, GitHub Copilot, or ZAI Coding Plan, see **[Provider Configurations](provider-configurations.md)** for step-by-step instructions.
+The installer generates an OpenAI configuration by default (using `gpt-5.4` and `gpt-5.4-mini` models). To use alternative providers like Kimi, GitHub Copilot, or ZAI Coding Plan, see **[Provider Configurations](provider-configurations.md)** for step-by-step instructions.
 
-Authenticate with your provider:
+Then:
 
 ```bash
 opencode auth login
-# Select your provider → Complete OAuth flow
+# Select your provider and complete OAuth flow
+```
+
+```bash
+opencode models --refresh
 ```
 
-Once authenticated, run OpenCode and `ping all agents` to verify all agents respond.
+Open your generated config at `~/.config/opencode/oh-my-opencode-slim.json`
+and adjust models if needed.
+
+Then run OpenCode and verify the agents:
+
+```text
+ping all agents
+```
 
 > **💡 Tip: Models are fully customizable.** The installer sets sensible defaults, but you can assign *any* model to *any* agent. Edit `~/.config/opencode/oh-my-opencode-slim.json` (or `.jsonc` for comments support) to override models, adjust reasoning effort, or disable agents entirely.
 
@@ -98,7 +108,7 @@ If not installed, direct the user to https://opencode.ai/docs first.
 The installer generates an OpenAI configuration by default:
 
 ```bash
-bunx oh-my-opencode-slim@latest install --no-tui --tmux=no --skills=yes
+bunx oh-my-opencode-slim@latest install --no-tui --skills=yes
 ```
 
 **Examples:**
@@ -106,11 +116,11 @@ bunx oh-my-opencode-slim@latest install --no-tui --tmux=no --skills=yes
 # Interactive install (asks about tmux and skills)
 bunx oh-my-opencode-slim@latest install
 
-# Non-interactive with tmux and skills
-bunx oh-my-opencode-slim@latest install --no-tui --tmux=yes --skills=yes
+# Non-interactive with default skills
+bunx oh-my-opencode-slim@latest install --no-tui --skills=yes
 
-# Non-interactive without tmux or skills
-bunx oh-my-opencode-slim@latest install --no-tui --tmux=no --skills=no
+# Non-interactive without skills
+bunx oh-my-opencode-slim@latest install --no-tui --skills=no
 
 # Force overwrite existing configuration
 bunx oh-my-opencode-slim@latest install --reset
@@ -134,8 +144,10 @@ opencode auth login
 
 Ask the user to:
 
-1. Start OpenCode: `opencode`
-2. Run: `ping all agents`
+1. Authenticate: `opencode auth login`
+2. Refresh models: `opencode models --refresh`
+3. Start OpenCode: `opencode`
+4. Run: `ping all agents`
 
 Verify all agents respond successfully.
 
@@ -244,6 +256,7 @@ See the [Multiplexer Integration Guide](multiplexer-integration.md) for more det
 
 3. **Remove skills (optional)**:
    ```bash
-   npx skills remove simplify
    npx skills remove agent-browser
+   rm -rf ~/.config/opencode/skills/simplify
+   rm -rf ~/.config/opencode/skills/cartography
    ```

+ 2 - 2
docs/mcps.md

@@ -18,7 +18,7 @@ Built-in Model Context Protocol (MCP) servers ship with oh-my-opencode-slim and
 
 | Agent | Default MCPs |
 |-------|-------------|
-| `orchestrator` | `*` |
+| `orchestrator` | `*`, `!context7` |
 | `librarian` | `websearch`, `context7`, `grep_app` |
 | `designer` | none |
 | `oracle` | none |
@@ -53,7 +53,7 @@ Control which MCPs each agent can use via the `mcps` array in your preset config
   "presets": {
     "my-preset": {
       "orchestrator": {
-        "mcps": ["*"]
+        "mcps": ["*", "!context7"]
       },
       "librarian": {
         "mcps": ["websearch", "context7", "grep_app"]

+ 15 - 15
docs/provider-configurations.md

@@ -15,10 +15,10 @@ The installer generates this configuration automatically:
   "preset": "openai",
   "presets": {
     "openai": {
-      "orchestrator": { "model": "openai/gpt-5.4", "variant": "high", "skills": ["*"], "mcps": ["*"] },
-      "oracle": { "model": "openai/gpt-5.4", "variant": "high", "skills": [], "mcps": [] },
+      "orchestrator": { "model": "openai/gpt-5.4", "variant": "high", "skills": ["*"], "mcps": ["*", "!context7"] },
+      "oracle": { "model": "openai/gpt-5.4", "variant": "high", "skills": ["simplify"], "mcps": [] },
       "librarian": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": [], "mcps": ["websearch", "context7", "grep_app"] },
-      "explorer": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": [], "mcps": [] },
+      "explorer": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": ["cartography"], "mcps": [] },
       "designer": { "model": "openai/gpt-5.4-mini", "variant": "medium", "skills": ["agent-browser"], "mcps": [] },
       "fixer": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": [], "mcps": [] }
     }
@@ -35,10 +35,10 @@ To use Kimi, add a `kimi` preset and set it as active:
   "preset": "kimi",
   "presets": {
     "kimi": {
-      "orchestrator": { "model": "kimi-for-coding/k2p5", "variant": "high", "skills": ["*"], "mcps": ["*"] },
-      "oracle": { "model": "kimi-for-coding/k2p5", "variant": "high", "skills": [], "mcps": [] },
+      "orchestrator": { "model": "kimi-for-coding/k2p5", "variant": "high", "skills": ["*"], "mcps": ["*", "!context7"] },
+      "oracle": { "model": "kimi-for-coding/k2p5", "variant": "high", "skills": ["simplify"], "mcps": [] },
       "librarian": { "model": "kimi-for-coding/k2p5", "variant": "low", "skills": [], "mcps": ["websearch", "context7", "grep_app"] },
-      "explorer": { "model": "kimi-for-coding/k2p5", "variant": "low", "skills": [], "mcps": [] },
+      "explorer": { "model": "kimi-for-coding/k2p5", "variant": "low", "skills": ["cartography"], "mcps": [] },
       "designer": { "model": "kimi-for-coding/k2p5", "variant": "medium", "skills": ["agent-browser"], "mcps": [] },
       "fixer": { "model": "kimi-for-coding/k2p5", "variant": "low", "skills": [], "mcps": [] }
     }
@@ -61,10 +61,10 @@ To use GitHub Copilot with Grok Code Fast:
   "preset": "copilot",
   "presets": {
     "copilot": {
-      "orchestrator": { "model": "github-copilot/claude-opus-4.6", "variant": "high", "skills": ["*"], "mcps": ["*"] },
-      "oracle": { "model": "github-copilot/claude-opus-4.6", "variant": "high", "skills": [], "mcps": [] },
+      "orchestrator": { "model": "github-copilot/claude-opus-4.6", "variant": "high", "skills": ["*"], "mcps": ["*", "!context7"] },
+      "oracle": { "model": "github-copilot/claude-opus-4.6", "variant": "high", "skills": ["simplify"], "mcps": [] },
       "librarian": { "model": "github-copilot/grok-code-fast-1", "variant": "low", "skills": [], "mcps": ["websearch", "context7", "grep_app"] },
-      "explorer": { "model": "github-copilot/grok-code-fast-1", "variant": "low", "skills": [], "mcps": [] },
+      "explorer": { "model": "github-copilot/grok-code-fast-1", "variant": "low", "skills": ["cartography"], "mcps": [] },
       "designer": { "model": "github-copilot/gemini-3.1-pro-preview", "variant": "medium", "skills": ["agent-browser"], "mcps": [] },
       "fixer": { "model": "github-copilot/claude-sonnet-4.6", "variant": "low", "skills": [], "mcps": [] }
     }
@@ -87,10 +87,10 @@ To use ZAI Coding Plan with GLM 5:
   "preset": "zai-plan",
   "presets": {
     "zai-plan": {
-      "orchestrator": { "model": "zai-coding-plan/glm-5", "variant": "high", "skills": ["*"], "mcps": ["*"] },
-      "oracle": { "model": "zai-coding-plan/glm-5", "variant": "high", "skills": [], "mcps": [] },
+      "orchestrator": { "model": "zai-coding-plan/glm-5", "variant": "high", "skills": ["*"], "mcps": ["*", "!context7"] },
+      "oracle": { "model": "zai-coding-plan/glm-5", "variant": "high", "skills": ["simplify"], "mcps": [] },
       "librarian": { "model": "zai-coding-plan/glm-5", "variant": "low", "skills": [], "mcps": ["websearch", "context7", "grep_app"] },
-      "explorer": { "model": "zai-coding-plan/glm-5", "variant": "low", "skills": [], "mcps": [] },
+      "explorer": { "model": "zai-coding-plan/glm-5", "variant": "low", "skills": ["cartography"], "mcps": [] },
       "designer": { "model": "zai-coding-plan/glm-5", "variant": "medium", "skills": ["agent-browser"], "mcps": [] },
       "fixer": { "model": "zai-coding-plan/glm-5", "variant": "low", "skills": [], "mcps": [] }
     }
@@ -113,10 +113,10 @@ You can mix models from different providers across agents. Create a custom prese
   "preset": "my-mix",
   "presets": {
     "my-mix": {
-      "orchestrator": { "model": "openai/gpt-5.4", "skills": ["*"], "mcps": ["*"] },
-      "oracle": { "model": "openai/gpt-5.4", "variant": "high", "skills": [], "mcps": [] },
+      "orchestrator": { "model": "openai/gpt-5.4", "skills": ["*"], "mcps": ["*", "!context7"] },
+      "oracle": { "model": "openai/gpt-5.4", "variant": "high", "skills": ["simplify"], "mcps": [] },
       "librarian": { "model": "kimi-for-coding/k2p5", "variant": "low", "skills": [], "mcps": ["websearch", "context7", "grep_app"] },
-      "explorer": { "model": "github-copilot/grok-code-fast-1", "variant": "low", "skills": [], "mcps": [] },
+      "explorer": { "model": "github-copilot/grok-code-fast-1", "variant": "low", "skills": ["cartography"], "mcps": [] },
       "designer": { "model": "kimi-for-coding/k2p5", "variant": "medium", "skills": ["agent-browser"], "mcps": [] },
       "fixer": { "model": "openai/gpt-5.4-mini", "variant": "low", "skills": [], "mcps": [] }
     }

+ 6 - 4
docs/skills.md

@@ -12,25 +12,27 @@ Skills are installed via the `oh-my-opencode-slim` installer or manually with `n
 
 | Skill | Description | Assigned to by default |
 |-------|-------------|----------------------|
-| [`simplify`](#simplify) | YAGNI code simplification expert | `oracle` |
 | [`agent-browser`](#agent-browser) | High-performance browser automation | `designer` |
 
 ### Bundled in repo
 
 | Skill | Description | Assigned to by default |
 |-------|-------------|----------------------|
-| [`cartography`](#cartography) | Repository codemap generation | `orchestrator` |
+| [`simplify`](#simplify) | Behavior-preserving code simplification | `oracle` |
+| [`cartography`](#cartography) | Repository codemap generation | `orchestrator`, `explorer` |
 
 ---
 
 ## simplify
 
-**The Minimalist's sacred truth: every line of code is a liability.**
+**Behavior-preserving simplification for readability and maintainability.**
 
-`simplify` is a specialized skill for complexity analysis and YAGNI enforcement. It identifies unnecessary abstractions, over-engineered patterns, and redundant code — and suggests minimal, direct implementations instead.
+`simplify` is a bundled skill for clarity-focused refactoring without behavior changes. It helps `oracle` reduce unnecessary complexity, improve naming and structure, and keep simplification work scoped and reviewable.
 
 By default, this skill is assigned to `oracle`, which owns code review, maintainability review, and simplification guidance. The `orchestrator` should route simplification requests to `oracle` instead of handling them as a top-level specialty itself.
 
+Source: adapted from Addy Osmani's `code-simplification` skill and bundled locally as `simplify`.
+
 ---
 
 ## agent-browser

+ 4 - 0
oh-my-opencode-slim.schema.json

@@ -19,6 +19,10 @@
     "balanceProviderUsage": {
       "type": "boolean"
     },
+    "showStartupToast": {
+      "description": "Show the startup activation toast when OpenCode starts. Defaults to true.",
+      "type": "boolean"
+    },
     "manualPlan": {
       "type": "object",
       "properties": {

+ 1 - 0
scripts/verify-release-artifact.ts

@@ -29,6 +29,7 @@ const packagedRequiredFiles = [
   'dist/index.d.ts',
   'dist/cli/index.js',
   'oh-my-opencode-slim.schema.json',
+  'src/skills/simplify/SKILL.md',
   'src/skills/cartography/SKILL.md',
 ];
 

+ 9 - 0
src/agents/index.test.ts

@@ -249,6 +249,15 @@ describe('skill permissions', () => {
       ?.skill as Record<string, string>;
     expect(skillPerm?.['requesting-code-review']).toBe('allow');
   });
+
+  test('oracle gets simplify skill allowed by default', () => {
+    const agents = createAgents();
+    const oracle = agents.find((a) => a.name === 'oracle');
+    expect(oracle).toBeDefined();
+    const skillPerm = (oracle?.config.permission as Record<string, unknown>)
+      ?.skill as Record<string, string>;
+    expect(skillPerm?.simplify).toBe('allow');
+  });
 });
 
 describe('isSubagent type guard', () => {

+ 22 - 22
src/agents/orchestrator.ts

@@ -1,4 +1,4 @@
-import type { AgentConfig } from '@opencode-ai/sdk/v2';
+import type { AgentConfig } from "@opencode-ai/sdk/v2";
 
 export interface AgentDefinition {
   name: string;
@@ -17,7 +17,7 @@ export interface AgentDefinition {
 export function resolvePrompt(
   base: string,
   customPrompt?: string,
-  customAppendPrompt?: string,
+  customAppendPrompt?: string
 ): string {
   if (customPrompt) return customPrompt;
   if (customAppendPrompt) return `${base}\n\n${customAppendPrompt}`;
@@ -61,9 +61,9 @@ const AGENT_DESCRIPTIONS: Record<string, string> = {
 - Role: Fast execution specialist for well-defined tasks, which empowers orchestrator with parallel, speedy executions
 - Stats: 2x faster code edits, 1/2 cost of orchestrator, 0.8x quality of orchestrator
 - Tools/Constraints: Execution-focused—no research, no architectural decisions
-- **Delegate when:** For implementation work, think and triage first. If the change is non-trivial or multi-file, hand bounded execution to @fixer • Writing or updating tests • Tasks that touch test files, fixtures, mocks, or test helpers
+- **Delegate when:** For implementation work, think and triage first. If the change is non-trivial or multi-file, hand bounded execution to @fixer • Writing or updating tests • Tasks that touch test files, fixtures, mocks, or test helpers. Parallelization benefits: Task involves multiple folders and multiple files modificaiton, scoping work per folder and spawning parallel @fixers for each folder.
 - **Don't delegate when:** Needs discovery/research/decisions • Single small change (<20 lines, one file) • Unclear requirements needing iteration • Explaining to fixer > doing • Tight integration with your current work • Sequential dependencies
-- **Rule of thumb:** Explaining > doing? → yourself. Test file modifications and bounded implementation work usually go to @fixer. Orchestrator paths selection is vastly improved by Fixer. eg it can reduce overall speed if Orchestrator splits what's usually a single task into multiple subtasks and parallelize it with fixer.`,
+- **Rule of thumb:** Explaining > doing? → yourself. Test file modifications and bounded implementation work usually go to @fixer. Bigger or lots of edits, splitting makes sense, parallelized by spawning @fixers per certain scope.`,
 
   council: `@council
 - Role: Multi-LLM consensus engine for high-confidence answers
@@ -86,19 +86,19 @@ const AGENT_DESCRIPTIONS: Record<string, string> = {
 
 // Validation routing lines that reference agents
 const VALIDATION_ROUTING = [
-  '- Route UI/UX validation and review to @designer',
-  '- Route code review, simplification, maintainability review, and YAGNI checks to @oracle',
-  '- Route test writing, test updates, and changes touching test files to @fixer',
-  '- Route visual/media analysis and interpretation to @observer',
-  '- If a request spans multiple lanes, delegate only the lanes that add clear value',
+  "- Route UI/UX validation and review to @designer",
+  "- Route code review, simplification, maintainability review, and YAGNI checks to @oracle",
+  "- Route test writing, test updates, and changes touching test files to @fixer",
+  "- Route visual/media analysis and interpretation to @observer",
+  "- If a request spans multiple lanes, delegate only the lanes that add clear value",
 ];
 
 // Parallel delegation examples
 const PARALLEL_DELEGATION_EXAMPLES = [
-  '- Multiple @explorer searches across different domains?',
-  '- @explorer + @librarian research in parallel?',
-  '- Multiple @fixer instances for faster, scoped implementation?',
-  '- @observer + @explorer in parallel (visual analysis + code search)?',
+  "- Multiple @explorer searches across different domains?",
+  "- @explorer + @librarian research in parallel?",
+  "- Multiple @fixer instances for faster, scoped implementation?",
+  "- @observer + @explorer in parallel (visual analysis + code search)?",
 ];
 
 /**
@@ -111,14 +111,14 @@ export function buildOrchestratorPrompt(disabledAgents?: Set<string>): string {
   const enabledAgents = Object.entries(AGENT_DESCRIPTIONS)
     .filter(([name]) => !disabledAgents?.has(name))
     .map(([, desc]) => desc)
-    .join('\n\n');
+    .join("\n\n");
 
   // Filter validation routing lines — remove lines mentioning any disabled agent
   const enabledValidationRouting = VALIDATION_ROUTING.filter((line) => {
     const mentions = [...line.matchAll(/@(\w+)/g)].map((m) => m[1]);
     if (mentions.length === 0) return true;
     return mentions.every((name) => !disabledAgents?.has(name));
-  }).join('\n');
+  }).join("\n");
 
   // Filter parallel delegation examples — remove lines mentioning any disabled agent
   const enabledParallelExamples = PARALLEL_DELEGATION_EXAMPLES.filter(
@@ -126,8 +126,8 @@ export function buildOrchestratorPrompt(disabledAgents?: Set<string>): string {
       const mentions = [...line.matchAll(/@(\w+)/g)].map((m) => m[1]);
       if (mentions.length === 0) return true;
       return mentions.every((name) => !disabledAgents?.has(name));
-    },
-  ).join('\n');
+    }
+  ).join("\n");
 
   return `<Role>
 You are an AI coding orchestrator that optimizes for quality, speed, cost, and reliability by delegating to specialists when it provides net efficiency gains.
@@ -232,15 +232,15 @@ export function createOrchestratorAgent(
   model?: string | Array<string | { id: string; variant?: string }>,
   customPrompt?: string,
   customAppendPrompt?: string,
-  disabledAgents?: Set<string>,
+  disabledAgents?: Set<string>
 ): AgentDefinition {
   const basePrompt = buildOrchestratorPrompt(disabledAgents);
   const prompt = resolvePrompt(basePrompt, customPrompt, customAppendPrompt);
 
   const definition: AgentDefinition = {
-    name: 'orchestrator',
+    name: "orchestrator",
     description:
-      'AI coding orchestrator that delegates tasks to specialist agents for optimal quality, speed, and cost',
+      "AI coding orchestrator that delegates tasks to specialist agents for optimal quality, speed, and cost",
     config: {
       temperature: 0.1,
       prompt,
@@ -249,9 +249,9 @@ export function createOrchestratorAgent(
 
   if (Array.isArray(model)) {
     definition._modelArray = model.map((m) =>
-      typeof m === 'string' ? { id: m } : m,
+      typeof m === "string" ? { id: m } : m
     );
-  } else if (typeof model === 'string' && model) {
+  } else if (typeof model === "string" && model) {
     definition.config.model = model;
   }
 

+ 110 - 0
src/background/background-manager.test.ts

@@ -748,6 +748,116 @@ describe('BackgroundTaskManager', () => {
       ).toBe(true);
     });
 
+    test('sends completion notification to parent with parent agent', async () => {
+      const ctx = createMockContext({
+        sessionMessagesResult: {
+          data: [
+            {
+              info: { role: 'assistant' },
+              parts: [{ type: 'text', text: 'done' }],
+            },
+          ],
+        },
+      });
+
+      const manager = new BackgroundTaskManager(ctx);
+
+      // Create a tracked orchestrator parent session
+      const parentTask = manager.launch({
+        agent: 'orchestrator',
+        prompt: 'orchestrate',
+        description: 'parent orchestration',
+        parentSessionId: 'root-session',
+      });
+
+      await Promise.resolve();
+      await Promise.resolve();
+
+      const parentSessionId = parentTask.sessionId;
+      if (!parentSessionId) throw new Error('Expected parent session id');
+
+      // Launch nested subagent under orchestrator
+      const childTask = manager.launch({
+        agent: 'explorer',
+        prompt: 'collect tests',
+        description: 'nested subagent',
+        parentSessionId,
+      });
+
+      await Promise.resolve();
+      await Promise.resolve();
+
+      await manager.handleSessionStatus({
+        type: 'session.status',
+        properties: {
+          sessionID: childTask.sessionId,
+          status: { type: 'idle' },
+        },
+      });
+
+      const promptCalls = ctx.client.session.prompt.mock.calls as Array<
+        {
+          path: { id: string };
+          body: { agent?: string; parts: Array<{ text?: string }> };
+        }
+      >;
+
+      const notificationCall = promptCalls.find(
+        (c) => c[0].path.id === parentSessionId,
+      );
+
+      expect(notificationCall).toBeDefined();
+      expect(notificationCall?.[0].body.agent).toBe('orchestrator');
+    });
+
+    test('sends completion notification using orchestrator for untracked parent', async () => {
+      const ctx = createMockContext({
+        sessionMessagesResult: {
+          data: [
+            {
+              info: { role: 'assistant' },
+              parts: [{ type: 'text', text: 'done' }],
+            },
+          ],
+        },
+      });
+
+      const manager = new BackgroundTaskManager(ctx);
+      const untrackedParentId = 'unknown-root';
+
+      const childTask = manager.launch({
+        agent: 'explorer',
+        prompt: 'collect tests',
+        description: 'orphan child',
+        parentSessionId: untrackedParentId,
+      });
+
+      await Promise.resolve();
+      await Promise.resolve();
+
+      await manager.handleSessionStatus({
+        type: 'session.status',
+        properties: {
+          sessionID: childTask.sessionId,
+          status: { type: 'idle' },
+        },
+      });
+
+      const promptCalls = ctx.client.session.prompt.mock.calls as Array<
+        {
+          path: { id: string };
+          body: { agent?: string };
+        }
+      >;
+
+      const notificationCall = promptCalls.find(
+        (c) => c[0].path.id === untrackedParentId,
+      );
+
+      expect(notificationCall).toBeDefined();
+      expect(notificationCall?.[0].body.agent).toBe('orchestrator');
+    });
+
     test('retries next fallback model when first model returns empty response', async () => {
       let messagesCallCount = 0;
       const ctx = createMockContext({

+ 10 - 0
src/background/background-manager.ts

@@ -137,6 +137,14 @@ export class BackgroundTaskManager {
     );
   }
 
+  /**
+   * Resolve the agent associated with a session.
+   * Untracked sessions are treated as orchestrator sessions by default.
+   */
+  private getSessionAgent(sessionId: string): string {
+    return this.agentBySessionId.get(sessionId) ?? 'orchestrator';
+  }
+
   /**
    * Check if a parent session is allowed to delegate to a specific agent type.
    * @param parentSessionId - The session ID of the parent
@@ -625,6 +633,7 @@ export class BackgroundTaskManager {
   private async sendCompletionNotification(
     task: BackgroundTask,
   ): Promise<void> {
+    const parentAgent = this.getSessionAgent(task.parentSessionId);
     const message =
       task.status === 'completed'
         ? `[Background task "${task.description}" completed]`
@@ -633,6 +642,7 @@ export class BackgroundTaskManager {
     await this.client.session.prompt({
       path: { id: task.parentSessionId },
       body: {
+        agent: parentAgent,
         parts: [createInternalAgentTextPart(message)],
       },
     });

+ 6 - 0
src/cli/custom-skills.ts

@@ -28,6 +28,12 @@ export interface CustomSkill {
  * Registry of custom skills bundled in this repository.
  */
 export const CUSTOM_SKILLS: CustomSkill[] = [
+  {
+    name: 'simplify',
+    description: 'Code simplification and readability-focused refactoring',
+    allowedAgents: ['oracle'],
+    sourcePath: 'src/skills/simplify',
+  },
   {
     name: 'cartography',
     description: 'Repository understanding and hierarchical codemap generation',

+ 3 - 5
src/cli/index.ts

@@ -5,13 +5,12 @@ import type { BooleanArg, InstallArgs } from './types';
 function parseArgs(args: string[]): InstallArgs {
   const result: InstallArgs = {
     tui: true,
+    skills: 'yes',
   };
 
   for (const arg of args) {
     if (arg === '--no-tui') {
       result.tui = false;
-    } else if (arg.startsWith('--tmux=')) {
-      result.tmux = arg.split('=')[1] as BooleanArg;
     } else if (arg.startsWith('--skills=')) {
       result.skills = arg.split('=')[1] as BooleanArg;
     } else if (arg === '--dry-run') {
@@ -34,8 +33,7 @@ oh-my-opencode-slim installer
 Usage: bunx oh-my-opencode-slim install [OPTIONS]
 
 Options:
-  --tmux=yes|no          Enable tmux integration (yes/no)
-  --skills=yes|no        Install recommended skills (yes/no)
+  --skills=yes|no        Install recommended and bundled skills (default: yes)
   --no-tui               Non-interactive mode
   --dry-run              Simulate install without writing files
   --reset                Force overwrite of existing configuration
@@ -46,7 +44,7 @@ For alternative providers, see docs/provider-configurations.md.
 
 Examples:
   bunx oh-my-opencode-slim install
-  bunx oh-my-opencode-slim install --no-tui --tmux=no --skills=yes
+  bunx oh-my-opencode-slim install --no-tui --skills=yes
   bunx oh-my-opencode-slim install --reset
 `);
 }

+ 26 - 29
src/cli/install.ts

@@ -24,13 +24,13 @@ const DIM = '\x1b[2m';
 const RESET = '\x1b[0m';
 
 const SYMBOLS = {
-  check: `${GREEN}${RESET}`,
-  cross: `${RED}${RESET}`,
-  arrow: `${BLUE}${RESET}`,
-  bullet: `${DIM}${RESET}`,
-  info: `${BLUE}${RESET}`,
-  warn: `${YELLOW}${RESET}`,
-  star: `${YELLOW}${RESET}`,
+  check: `${GREEN}[ok]${RESET}`,
+  cross: `${RED}[x]${RESET}`,
+  arrow: `${BLUE}->${RESET}`,
+  bullet: `${DIM}-${RESET}`,
+  info: `${BLUE}[i]${RESET}`,
+  warn: `${YELLOW}[!]${RESET}`,
+  star: `${YELLOW}*${RESET}`,
 };
 
 function printHeader(isUpdate: boolean): void {
@@ -98,19 +98,6 @@ function handleStepResult(
   return true;
 }
 
-function formatConfigSummary(): string {
-  const lines: string[] = [];
-  lines.push(`${BOLD}Configuration Summary${RESET}`);
-  lines.push('');
-  lines.push(`  ${BOLD}Preset:${RESET} ${BLUE}openai${RESET}`);
-  lines.push(`  ${SYMBOLS.check} OpenAI (default)`);
-  const seeDocs = 'see docs/provider-configurations.md';
-  lines.push(`  ${DIM}○ Kimi — ${seeDocs}${RESET}`);
-  lines.push(`  ${DIM}○ GitHub Copilot — ${seeDocs}${RESET}`);
-  lines.push(`  ${DIM}○ ZAI Coding Plan — ${seeDocs}${RESET}`);
-  return lines.join('\n');
-}
-
 async function runInstall(config: InstallConfig): Promise<number> {
   const detected = detectCurrentConfig();
   const isUpdate = detected.isInstalled;
@@ -225,11 +212,6 @@ async function runInstall(config: InstallConfig): Promise<number> {
     }
   }
 
-  // Summary
-  console.log();
-  console.log(formatConfigSummary());
-  console.log();
-
   const statusMsg = isUpdate
     ? 'Configuration updated!'
     : 'Installation complete!';
@@ -238,15 +220,30 @@ async function runInstall(config: InstallConfig): Promise<number> {
   console.log(`${BOLD}Next steps:${RESET}`);
   console.log();
 
-  console.log(`  1. Start OpenCode:`);
+  const configPath = getExistingLiteConfigPath();
+
+  console.log('  1. Log in to the provider(s) you want to use:');
+  console.log(`     ${BLUE}$ opencode auth login${RESET}`);
+  console.log();
+  console.log('  2. Refresh the models OpenCode can see:');
+  console.log(`     ${BLUE}$ opencode models --refresh${RESET}`);
+  console.log();
+  console.log('  3. Review your generated config:');
+  console.log(`     ${BLUE}${configPath}${RESET}`);
+  console.log();
+  console.log('  4. Start OpenCode:');
   console.log(`     ${BLUE}$ opencode${RESET}`);
   console.log();
+  console.log('  5. Verify the agents are responding:');
+  console.log(`     ${BLUE}> ping all agents${RESET}`);
+  console.log();
+
   const modelsInfo =
     'Default configuration uses OpenAI models (gpt-5.4 / gpt-5.4-mini).';
-  console.log(`${BOLD}${modelsInfo}${RESET}`);
+  console.log(`${modelsInfo}`);
   const altProviders =
     'For alternative providers (Kimi, GitHub Copilot, ZAI Coding Plan)';
-  console.log(`${BOLD}${altProviders}, see:${RESET}`);
+  console.log(`${altProviders}, see:`);
   const docsUrl =
     'https://github.com/alvinunreal/oh-my-opencode-slim/' +
     'blob/master/docs/provider-configurations.md';
@@ -258,7 +255,7 @@ async function runInstall(config: InstallConfig): Promise<number> {
 
 export async function install(args: InstallArgs): Promise<number> {
   const config: InstallConfig = {
-    hasTmux: args.tmux === 'yes',
+    hasTmux: false,
     installSkills: args.skills === 'yes',
     installCustomSkills: args.skills === 'yes',
     dryRun: args.dryRun,

+ 7 - 1
src/cli/providers.test.ts

@@ -76,6 +76,12 @@ describe('providers', () => {
     // Orchestrator should always have '*'
     expect(agents.orchestrator.skills).toEqual(['*']);
 
+    // Oracle should have bundled simplify
+    expect(agents.oracle.skills).toContain('simplify');
+
+    // Explorer should have bundled cartography
+    expect(agents.explorer.skills).toContain('cartography');
+
     // Designer should have 'agent-browser'
     expect(agents.designer.skills).toContain('agent-browser');
 
@@ -107,7 +113,7 @@ describe('providers', () => {
     });
 
     const agents = (config.presets as any).openai;
-    expect(agents.orchestrator.mcps).toContain('*');
+    expect(agents.orchestrator.mcps).toEqual(['*', '!context7']);
     expect(agents.librarian.mcps).toContain('websearch');
     expect(agents.librarian.mcps).toContain('context7');
     expect(agents.librarian.mcps).toContain('grep_app');

+ 13 - 5
src/cli/providers.ts

@@ -1,4 +1,5 @@
 import { DEFAULT_AGENT_MCPS } from '../config/agent-mcps';
+import { CUSTOM_SKILLS } from './custom-skills';
 import { RECOMMENDED_SKILLS } from './skills';
 import type { InstallConfig } from './types';
 
@@ -61,11 +62,18 @@ export function generateLiteConfig(
 
     const skills = isOrchestrator
       ? ['*']
-      : RECOMMENDED_SKILLS.filter(
-          (s) =>
-            s.allowedAgents.includes('*') ||
-            s.allowedAgents.includes(agentName),
-        ).map((s) => s.skillName);
+      : [
+          ...RECOMMENDED_SKILLS.filter(
+            (s) =>
+              s.allowedAgents.includes('*') ||
+              s.allowedAgents.includes(agentName),
+          ).map((s) => s.skillName),
+          ...CUSTOM_SKILLS.filter(
+            (s) =>
+              s.allowedAgents.includes('*') ||
+              s.allowedAgents.includes(agentName),
+          ).map((s) => s.name),
+        ];
 
     if (agentName === 'designer' && !skills.includes('agent-browser')) {
       skills.push('agent-browser');

+ 1 - 1
src/cli/skills.test.ts

@@ -17,7 +17,7 @@ describe('skills permissions', () => {
     const designerPerms = getSkillPermissionsForAgent('designer');
     expect(designerPerms['agent-browser']).toBe('allow');
 
-    // Oracle should have simplify allowed by recommendation
+    // Oracle should have simplify allowed by default
     const oraclePerms = getSkillPermissionsForAgent('oracle');
     expect(oraclePerms.simplify).toBe('allow');
   });

+ 0 - 7
src/cli/skills.ts

@@ -37,13 +37,6 @@ export interface PermissionOnlySkill {
  * Add new skills here to include them in the installation flow.
  */
 export const RECOMMENDED_SKILLS: RecommendedSkill[] = [
-  {
-    name: 'simplify',
-    repo: 'https://github.com/brianlovin/claude-config',
-    skillName: 'simplify',
-    allowedAgents: ['oracle'],
-    description: 'YAGNI code simplification expert',
-  },
   {
     name: 'agent-browser',
     repo: 'https://github.com/vercel-labs/agent-browser',

+ 0 - 1
src/cli/types.ts

@@ -2,7 +2,6 @@ export type BooleanArg = 'yes' | 'no';
 
 export interface InstallArgs {
   tui: boolean;
-  tmux?: BooleanArg;
   skills?: BooleanArg;
   dryRun?: boolean;
   reset?: boolean;

+ 2 - 2
src/config/agent-mcps.test.ts

@@ -14,7 +14,7 @@ describe('parseList', () => {
     ]);
   });
 
-  test('orchestrator wildcard includes custom mcps too', () => {
+  test('orchestrator wildcard excludes context7 but includes custom mcps', () => {
     expect(
       parseList(DEFAULT_AGENT_MCPS.orchestrator, [
         'websearch',
@@ -22,7 +22,7 @@ describe('parseList', () => {
         'grep_app',
         'custom-mcp',
       ]),
-    ).toEqual(['websearch', 'context7', 'grep_app', 'custom-mcp']);
+    ).toEqual(['websearch', 'grep_app', 'custom-mcp']);
   });
 
   test('wildcard with exclusions', () => {

+ 1 - 1
src/config/agent-mcps.ts

@@ -8,7 +8,7 @@ import {
 /** Default MCPs per agent - "*" means all MCPs, "!item" excludes specific MCPs */
 
 export const DEFAULT_AGENT_MCPS: Record<AgentName, string[]> = {
-  orchestrator: ['*'],
+  orchestrator: ['*', '!context7'],
   designer: [],
   oracle: [],
   librarian: ['websearch', 'context7', 'grep_app'],

+ 15 - 0
src/config/loader.test.ts

@@ -80,6 +80,21 @@ describe('loadPluginConfig', () => {
     expect(config.balanceProviderUsage).toBe(true);
   });
 
+  test('loads showStartupToast flag when configured', () => {
+    const projectDir = path.join(tempDir, 'project');
+    const projectConfigDir = path.join(projectDir, '.opencode');
+    fs.mkdirSync(projectConfigDir, { recursive: true });
+    fs.writeFileSync(
+      path.join(projectConfigDir, 'oh-my-opencode-slim.json'),
+      JSON.stringify({
+        showStartupToast: false,
+      }),
+    );
+
+    const config = loadPluginConfig(projectDir);
+    expect(config.showStartupToast).toBe(false);
+  });
+
   test('loads manual plan structure when configured', () => {
     const projectDir = path.join(tempDir, 'project');
     const projectConfigDir = path.join(projectDir, '.opencode');

+ 6 - 0
src/config/schema.ts

@@ -237,6 +237,12 @@ export const PluginConfigSchema = z.object({
   setDefaultAgent: z.boolean().optional(),
   scoringEngineVersion: z.enum(['v1', 'v2-shadow', 'v2']).optional(),
   balanceProviderUsage: z.boolean().optional(),
+  showStartupToast: z
+    .boolean()
+    .optional()
+    .describe(
+      'Show the startup activation toast when OpenCode starts. Defaults to true.',
+    ),
   manualPlan: ManualPlanSchema.optional(),
   presets: z.record(z.string(), PresetSchema).optional(),
   agents: z.record(z.string(), AgentOverrideConfigSchema).optional(),

+ 1 - 1
src/index.ts

@@ -139,7 +139,7 @@ const OhMyOpenCodeLite: Plugin = async (ctx) => {
 
   // Initialize auto-update checker hook
   const autoUpdateChecker = createAutoUpdateCheckerHook(ctx, {
-    showStartupToast: true,
+    showStartupToast: config.showStartupToast ?? true,
     autoUpdate: true,
   });
 

+ 19 - 0
src/skills/simplify/README.md

@@ -0,0 +1,19 @@
+# Simplify Skill
+
+Behavior-preserving code simplification and readability-focused refactoring.
+
+## Overview
+
+This bundled skill helps the `oracle` agent review and simplify code without
+changing behavior. It focuses on readability, maintainability, and reducing
+unnecessary complexity.
+
+## Source
+
+Adapted from Addy Osmani's
+[`code-simplification` skill](https://github.com/addyosmani/agent-skills/blob/main/skills/code-simplification/SKILL.md).
+
+## Installation
+
+Bundled with `oh-my-opencode-slim` and installed automatically when bundled
+skills are enabled via the installer.

+ 138 - 0
src/skills/simplify/SKILL.md

@@ -0,0 +1,138 @@
+---
+name: simplify
+description: Simplifies code for clarity without changing behavior. Use for readability, maintainability, and complexity reduction after behavior is understood.
+---
+
+# Code Simplification
+
+## Overview
+
+Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass a simple test: "Would a new team member understand this faster than the original?"
+
+## When to Use
+
+- After a feature is working and tests pass, but the implementation feels heavier than it needs to be
+- During code review when readability or complexity issues are flagged
+- When you encounter deeply nested logic, long functions, or unclear names
+- When refactoring code written under time pressure
+- When consolidating related logic scattered across files
+- After merging changes that introduced duplication or inconsistency
+
+**When NOT to use:**
+
+- Code is already clean and readable — don't simplify for the sake of it
+- You don't understand what the code does yet — comprehend before you simplify
+- The code is performance-critical and the "simpler" version would be measurably slower
+- You're about to rewrite the module entirely — simplifying throwaway code wastes effort
+
+## The Five Principles
+
+### 1. Preserve Behavior Exactly
+
+Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. If you're not sure a simplification preserves behavior, don't make it.
+
+Before every change, ask:
+
+- Does this produce the same output for every input?
+- Does this maintain the same error behavior?
+- Does this preserve the same side effects and ordering?
+- Do all existing tests still pass without modification?
+
+### 2. Follow Project Conventions
+
+Simplification means making code more consistent with the codebase, not imposing external preferences.
+
+Before simplifying:
+
+1. Read `AGENTS.md` / project conventions
+2. Study how neighboring code handles similar patterns
+3. Match the project's style for imports, naming, function style, error handling, and type annotations
+
+Simplification that breaks project consistency is not simplification — it's churn.
+
+### 3. Prefer Clarity Over Cleverness
+
+Explicit code is better than compact code when the compact version requires a mental pause to parse.
+
+- Replace nested ternaries with readable control flow
+- Replace dense inline transforms with named intermediate steps when they clarify intent
+- Keep helpful names even if they cost a few extra lines
+
+### 4. Maintain Balance
+
+Watch for over-simplification:
+
+- Don't inline away names that carry meaning
+- Don't merge unrelated logic into one larger function
+- Don't remove abstractions that serve testability or extensibility
+- Don't optimize for line count over comprehension
+
+### 5. Scope to What Changed
+
+Default to simplifying recently modified code. Avoid unrelated drive-by refactors unless explicitly asked.
+
+## Process
+
+### Step 1: Understand Before Touching
+
+Before changing or removing anything, understand why it exists.
+
+Answer:
+
+- What is this code's responsibility?
+- What calls it? What does it call?
+- What are the edge cases and error paths?
+- Are there tests that define expected behavior?
+- Why might it have been written this way?
+
+If you can't answer these, read more context first.
+
+### Step 2: Look for Simplification Opportunities
+
+Signals:
+
+- Deep nesting
+- Long functions with mixed responsibilities
+- Nested ternaries
+- Boolean flag arguments
+- Repeated conditionals
+- Generic or misleading names
+- Duplicated logic
+- Dead code
+- Wrappers or abstractions that add no value
+
+### Step 3: Apply Changes Incrementally
+
+Make one simplification at a time.
+
+For each simplification:
+
+1. Make the change
+2. Run relevant tests
+3. Keep it only if behavior is preserved
+
+Separate refactoring from feature work whenever possible.
+
+### Step 4: Verify the Result
+
+After simplifying, confirm:
+
+- The code is genuinely easier to understand
+- The diff is clean and reviewable
+- Project conventions still match
+- No behavior, error handling, or side effects changed
+
+## Guidance for This Repository
+
+- Prefer straightforward TypeScript over clever compression
+- Preserve existing runtime behavior, tests, and hooks
+- Favor explicit names and smaller focused helpers when they improve readability
+- Keep refactors tightly scoped to the task or review feedback
+
+## Verification Checklist
+
+- [ ] Existing tests pass without modification
+- [ ] Build/typecheck/lint still pass
+- [ ] No unrelated files were refactored
+- [ ] No error handling was weakened or removed
+- [ ] The result is simpler to review than the original