opencode plugin with skills setup - continuation of this blog https://mitzen.blogspot.com/2026/04/opencode-creating-plugin-and.html

In the previous post, we learned how to setup plugin so we can call it from opencode. In this post, we are going to add a skill - bragging skills - as I find it really important arsenal to have especially in an interview. 



So we only need to update our config object for opencode. Let's see an example of how to do it with skills

 config: async (config: any) => {
      config.skills = config.skills || {};
      config.skills.paths = config.skills.paths || [];
      if (!config.skills.paths.includes(skillsDir)) {
        config.skills.paths.push(skillsDir);
      }

And that's it. Once you have restart opencode, it will load my new skills. 

The full code is here and the repo here: https://github.com/kepungnzai/appcoreopc-num-mastery.git

import { type Plugin } from "@opencode-ai/plugin"
import { tool } from "@opencode-ai/plugin/tool"
import path from 'path';
import fs from 'fs';
import os from 'os';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const normalizePath = (p: string, homeDir: string) => {
  if (!p || typeof p !== 'string') return null;
  let normalized = p.trim();
  if (!normalized) return null;
  if (normalized.startsWith('~/')) {
    normalized = path.join(homeDir, normalized.slice(2));
  } else if (normalized === '~') {
    normalized = homeDir;
  }
  return path.resolve(normalized);
};

export const AppcoreopcNumMastery: Plugin = async () => {

  const homeDir = os.homedir();
  const skillsDir = path.resolve(__dirname, '../skills');

  const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR as string, homeDir);
  const configDir = envConfigDir || path.join(homeDir, '.config/opencode');

  const myTool = tool({
    description: "A simple plugin.",
    args: {
      query: tool.schema.string().describe("Question or topic to submit to Google AI Mode"),
      timeout: tool.schema.number().min(5).max(120).optional().describe("Timeout in seconds (default: 30, max: 120)"),
      followUp: tool.schema.boolean().optional().describe("Treat the query as a follow-up in the same session"),
    },
    async execute(args, _ctx) {
      return `Hello ${args.query} winner!`
    },
  })

  return {
    tool: {
      "appcoreopc-num-mastery": myTool,
    },
    config: async (config: any) => {
      config.skills = config.skills || {};
      config.skills.paths = config.skills.paths || [];
      if (!config.skills.paths.includes(skillsDir)) {
        config.skills.paths.push(skillsDir);
      }
    }
  }
}


And your opencode has new skills. Abit more complicated that what we would have liked. 



Comments

Popular posts from this blog

vllm : Failed to infer device type

android studio kotlin source is null error

NodeJS: Error: spawn EINVAL in window for node version 20.20 and 18.20