rig-opencode 0.1.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/README.md +63 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# rig-opencode
|
|
2
|
+
|
|
3
|
+
OpenCode plugin that records skill usage to a local JSONL file for Rig.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
Add the npm package to your OpenCode config.
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"$schema": "https://opencode.ai/config.json",
|
|
12
|
+
"plugin": ["rig-opencode"]
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
OpenCode installs npm plugins automatically with Bun at startup.
|
|
17
|
+
|
|
18
|
+
## What It Records
|
|
19
|
+
|
|
20
|
+
When OpenCode executes the native `skill` tool, the plugin appends one JSON line:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{"source":"opencode","skillName":"typescript-fix-null-safety","usedAt":"2026-05-30T01:12:00.000Z"}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Default log path:
|
|
27
|
+
|
|
28
|
+
```txt
|
|
29
|
+
~/.rig/usage.jsonl
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Rig reads this file to show skill usage counts and dashboard summaries.
|
|
33
|
+
|
|
34
|
+
## Environment Variables
|
|
35
|
+
|
|
36
|
+
The plugin works without any environment variables. Use these only when you want
|
|
37
|
+
to customize where logs are written or temporarily disable tracking.
|
|
38
|
+
|
|
39
|
+
| Name | Default | Description |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| `RIG_USAGE_LOG_PATH` | `~/.rig/usage.jsonl` | JSONL file path to append usage events to. |
|
|
42
|
+
| `RIG_USAGE_SOURCE` | `opencode` | Source value written into each event. |
|
|
43
|
+
| `RIG_USAGE_DISABLED` | unset | Set to `1` or `true` to disable recording. |
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Write usage logs somewhere else
|
|
49
|
+
RIG_USAGE_LOG_PATH=./.rig/usage/rig-usage.jsonl opencode
|
|
50
|
+
|
|
51
|
+
# Override the source field
|
|
52
|
+
RIG_USAGE_SOURCE=opencode-local opencode
|
|
53
|
+
|
|
54
|
+
# Temporarily disable tracking
|
|
55
|
+
RIG_USAGE_DISABLED=1 opencode
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Local Development
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pnpm --filter rig-opencode check-ts
|
|
62
|
+
pnpm --filter rig-opencode build
|
|
63
|
+
```
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{appendFile as a,mkdir as g}from"node:fs/promises";import{homedir as c}from"node:os";import{dirname as f,resolve as u}from"node:path";var k="~/.rig/usage.jsonl",p="opencode",E=async()=>({"tool.execute.after":async(n,r)=>{if(d()||!S(n))return;let e=y(n,r);e&&await m({source:process.env.RIG_USAGE_SOURCE||p,skillName:e,usedAt:new Date().toISOString()})}}),m=async n=>{let r=w(process.env.RIG_USAGE_LOG_PATH||k);await g(f(r),{recursive:!0}),await a(r,`${JSON.stringify(n)}
|
|
2
|
+
`,"utf8")},d=()=>{let n=process.env.RIG_USAGE_DISABLED?.toLowerCase();return n==="1"||n==="true"},S=n=>t(n,"tool")==="skill",y=(n,r)=>{let e=[n,r,s(n,"args"),s(r,"args"),s(n,"input"),s(r,"input")];for(let o of e){let l=t(o,"skillName")??t(o,"skill_name")??t(o,"name")??t(o,"skill");if(l)return l}return null},s=(n,r)=>{if(!i(n))return null;let e=n[r];return i(e)?e:null},t=(n,r)=>{if(!i(n))return null;let e=n[r];return typeof e=="string"&&e.trim().length>0?e:null},i=n=>typeof n=="object"&&n!==null,w=n=>n==="~"?c():n.startsWith("~/")?u(c(),n.slice(2)):u(n);export{E as RigSkillUsagePlugin};
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { appendFile, mkdir } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, resolve } from 'node:path';\nimport type { Plugin } from '@opencode-ai/plugin';\n\nconst DEFAULT_LOG_PATH = '~/.rig/usage.jsonl';\nconst DEFAULT_SOURCE = 'opencode';\n\nexport interface RigSkillUsageLogEntry {\n source: string;\n skillName: string;\n usedAt: string;\n}\n\nexport const RigSkillUsagePlugin: Plugin = async () => {\n return {\n 'tool.execute.after': async (input, output) => {\n if (isDisabled()) {\n return;\n }\n\n if (!isSkillTool(input)) {\n return;\n }\n\n const skillName = getSkillName(input, output);\n\n if (!skillName) {\n return;\n }\n\n await appendUsage({\n source: process.env.RIG_USAGE_SOURCE || DEFAULT_SOURCE,\n skillName,\n usedAt: new Date().toISOString(),\n });\n },\n };\n};\n\nconst appendUsage = async (entry: RigSkillUsageLogEntry) => {\n const logPath = expandPath(\n process.env.RIG_USAGE_LOG_PATH || DEFAULT_LOG_PATH,\n );\n\n await mkdir(dirname(logPath), { recursive: true });\n await appendFile(logPath, `${JSON.stringify(entry)}\\n`, 'utf8');\n};\n\nconst isDisabled = () => {\n const value = process.env.RIG_USAGE_DISABLED?.toLowerCase();\n\n return value === '1' || value === 'true';\n};\n\nconst isSkillTool = (input: unknown) => {\n return getStringProperty(input, 'tool') === 'skill';\n};\n\nconst getSkillName = (input: unknown, output: unknown) => {\n const candidates = [\n input,\n output,\n getObjectProperty(input, 'args'),\n getObjectProperty(output, 'args'),\n getObjectProperty(input, 'input'),\n getObjectProperty(output, 'input'),\n ];\n\n for (const candidate of candidates) {\n const skillName =\n getStringProperty(candidate, 'skillName') ??\n getStringProperty(candidate, 'skill_name') ??\n getStringProperty(candidate, 'name') ??\n getStringProperty(candidate, 'skill');\n\n if (skillName) {\n return skillName;\n }\n }\n\n return null;\n};\n\nconst getObjectProperty = (value: unknown, key: string) => {\n if (!isRecord(value)) {\n return null;\n }\n\n const property = value[key];\n\n return isRecord(property) ? property : null;\n};\n\nconst getStringProperty = (value: unknown, key: string) => {\n if (!isRecord(value)) {\n return null;\n }\n\n const property = value[key];\n\n return typeof property === 'string' && property.trim().length > 0\n ? property\n : null;\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === 'object' && value !== null;\n};\n\nconst expandPath = (path: string) => {\n if (path === '~') {\n return homedir();\n }\n\n if (path.startsWith('~/')) {\n return resolve(homedir(), path.slice(2));\n }\n\n return resolve(path);\n};\n"],"mappings":"AAAA,OAAS,cAAAA,EAAY,SAAAC,MAAa,mBAClC,OAAS,WAAAC,MAAe,UACxB,OAAS,WAAAC,EAAS,WAAAC,MAAe,YAGjC,IAAMC,EAAmB,qBACnBC,EAAiB,WAQVC,EAA8B,UAClC,CACL,qBAAsB,MAAOC,EAAOC,IAAW,CAK7C,GAJIC,EAAW,GAIX,CAACC,EAAYH,CAAK,EACpB,OAGF,IAAMI,EAAYC,EAAaL,EAAOC,CAAM,EAEvCG,GAIL,MAAME,EAAY,CAChB,OAAQ,QAAQ,IAAI,kBAAoBR,EACxC,UAAAM,EACA,OAAQ,IAAI,KAAK,EAAE,YAAY,CACjC,CAAC,CACH,CACF,GAGIE,EAAc,MAAOC,GAAiC,CAC1D,IAAMC,EAAUC,EACd,QAAQ,IAAI,oBAAsBZ,CACpC,EAEA,MAAMJ,EAAME,EAAQa,CAAO,EAAG,CAAE,UAAW,EAAK,CAAC,EACjD,MAAMhB,EAAWgB,EAAS,GAAG,KAAK,UAAUD,CAAK,CAAC;AAAA,EAAM,MAAM,CAChE,EAEML,EAAa,IAAM,CACvB,IAAMQ,EAAQ,QAAQ,IAAI,oBAAoB,YAAY,EAE1D,OAAOA,IAAU,KAAOA,IAAU,MACpC,EAEMP,EAAeH,GACZW,EAAkBX,EAAO,MAAM,IAAM,QAGxCK,EAAe,CAACL,EAAgBC,IAAoB,CACxD,IAAMW,EAAa,CACjBZ,EACAC,EACAY,EAAkBb,EAAO,MAAM,EAC/Ba,EAAkBZ,EAAQ,MAAM,EAChCY,EAAkBb,EAAO,OAAO,EAChCa,EAAkBZ,EAAQ,OAAO,CACnC,EAEA,QAAWa,KAAaF,EAAY,CAClC,IAAMR,EACJO,EAAkBG,EAAW,WAAW,GACxCH,EAAkBG,EAAW,YAAY,GACzCH,EAAkBG,EAAW,MAAM,GACnCH,EAAkBG,EAAW,OAAO,EAEtC,GAAIV,EACF,OAAOA,CAEX,CAEA,OAAO,IACT,EAEMS,EAAoB,CAACH,EAAgBK,IAAgB,CACzD,GAAI,CAACC,EAASN,CAAK,EACjB,OAAO,KAGT,IAAMO,EAAWP,EAAMK,CAAG,EAE1B,OAAOC,EAASC,CAAQ,EAAIA,EAAW,IACzC,EAEMN,EAAoB,CAACD,EAAgBK,IAAgB,CACzD,GAAI,CAACC,EAASN,CAAK,EACjB,OAAO,KAGT,IAAMO,EAAWP,EAAMK,CAAG,EAE1B,OAAO,OAAOE,GAAa,UAAYA,EAAS,KAAK,EAAE,OAAS,EAC5DA,EACA,IACN,EAEMD,EAAYN,GACT,OAAOA,GAAU,UAAYA,IAAU,KAG1CD,EAAcS,GACdA,IAAS,IACJxB,EAAQ,EAGbwB,EAAK,WAAW,IAAI,EACftB,EAAQF,EAAQ,EAAGwB,EAAK,MAAM,CAAC,CAAC,EAGlCtB,EAAQsB,CAAI","names":["appendFile","mkdir","homedir","dirname","resolve","DEFAULT_LOG_PATH","DEFAULT_SOURCE","RigSkillUsagePlugin","input","output","isDisabled","isSkillTool","skillName","getSkillName","appendUsage","entry","logPath","expandPath","value","getStringProperty","candidates","getObjectProperty","candidate","key","isRecord","property","path"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rig-opencode",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "OpenCode plugin for tracking Rig skill usage locally",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist",
|
|
9
|
+
"README.md"
|
|
10
|
+
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"main": "./dist/index.js",
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"check-ts": "tsc --noEmit",
|
|
24
|
+
"prepublishOnly": "pnpm build"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"opencode",
|
|
28
|
+
"opencode-plugin",
|
|
29
|
+
"rig",
|
|
30
|
+
"skills",
|
|
31
|
+
"usage-tracking"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@opencode-ai/plugin": "^1.15.13",
|
|
39
|
+
"@types/node": "catalog:types",
|
|
40
|
+
"tsup": "catalog:build",
|
|
41
|
+
"typescript": "catalog:types"
|
|
42
|
+
}
|
|
43
|
+
}
|