@alexgorbatchev/pi-skill-library 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alex Gorbatchev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,88 @@
1
+ # @alexgorbatchev/pi-skill-library
2
+
3
+ [pi](https://pi.dev) extension that discovers `skills-library` roots and exposes their skills through `/library:<skill-name>` commands. This extension solves the problem of too many skills. There are skills that you need only occasionally and maybe don't even need them discoverable.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pi install npm:@alexgorbatchev/pi-skill-library
9
+ ```
10
+
11
+ ## What it does
12
+
13
+ This package does **not** register bundled skills through Pi's normal skill loader.
14
+ Instead, it discovers `skills-library` directories, loads the skills from those roots itself, and expands:
15
+
16
+ ```text
17
+ /library:<skill-name>
18
+ ```
19
+
20
+ into the same `<skill ...>...</skill>` block format Pi uses for built-in `/skill:<name>` expansion.
21
+
22
+ That keeps these skills out of Pi's default skill discovery flow while still making them explicitly invokable.
23
+
24
+ ## Library root locations
25
+
26
+ The extension looks for `skills-library` in these places:
27
+
28
+ - `<cwd>/.pi/skills-library`
29
+ - `<cwd>` and ancestor `.agents/skills-library` directories, stopping at the git root (or filesystem root when no git root exists)
30
+ - `~/.pi/agent/cskills-library`
31
+ - `~/.agents/skills-library`
32
+ - package-local `skills-library` directories derived from discovered package skill roots
33
+ - extra paths configured via Pi settings under `@alexgorbatchev/pi-skills-library.paths`
34
+
35
+ ## Settings
36
+
37
+ Use a namespaced block in Pi settings:
38
+
39
+ ```json
40
+ {
41
+ "@alexgorbatchev/pi-skills-library": {
42
+ "paths": [
43
+ "./skills-library",
44
+ "~/shared/pi-skills-library"
45
+ ]
46
+ }
47
+ }
48
+ ```
49
+
50
+ Path resolution follows normal Pi settings behavior:
51
+
52
+ - paths in `~/.pi/agent/settings.json` resolve relative to `~/.pi/agent`
53
+ - paths in `.pi/settings.json` resolve relative to `.pi`
54
+ - absolute paths are supported
55
+ - `~/...` is supported
56
+
57
+ ## Directory layout
58
+
59
+ Each library root should contain normal skill directories:
60
+
61
+ ```text
62
+ skills-library/
63
+ ├── my-skill/
64
+ │ └── SKILL.md
65
+ └── another-skill/
66
+ ├── SKILL.md
67
+ └── references/
68
+ ```
69
+
70
+ ## Commands
71
+
72
+ Invoke a library skill directly:
73
+
74
+ ```text
75
+ /library:my-skill
76
+ /library:my-skill additional context here
77
+ ```
78
+
79
+ Discovered library skills are registered as real extension slash commands at startup and reload, so they show up in slash-command autocomplete like other commands.
80
+
81
+ On startup, the extension prints a library-discovery message into the transcript listing each discovered library root and its skills. Home-directory paths are rendered with the `~/` convention.
82
+
83
+ Use the package info command to print the same report again:
84
+
85
+ ```text
86
+ /pi-skill-library
87
+ ```
88
+
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@alexgorbatchev/pi-skill-library",
3
+ "version": "0.1.0",
4
+ "description": "Pi extension that exposes skills-library roots through /library:<skill-name> commands.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "packageManager": "bun@1.3.10",
8
+ "keywords": [
9
+ "pi-package",
10
+ "pi-extension",
11
+ "skills",
12
+ "skill",
13
+ "library"
14
+ ],
15
+ "files": [
16
+ "src",
17
+ "skills-library",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "pi": {
25
+ "extensions": [
26
+ "./src/index.ts"
27
+ ]
28
+ },
29
+ "peerDependencies": {
30
+ "@mariozechner/pi-coding-agent": "*"
31
+ },
32
+ "devDependencies": {
33
+ "@mariozechner/pi-coding-agent": "0.64.0",
34
+ "@types/node": "24.7.2",
35
+ "@typescript/native-preview": "7.0.0-dev.20260330.1",
36
+ "dprint": "0.53.0",
37
+ "oxlint": "1.56.0",
38
+ "typescript": "6.0.2"
39
+ },
40
+ "scripts": {
41
+ "dev": "bun x pi -e ./src/index.ts",
42
+ "check": "bun run typecheck && bun run lint && bun run format:check && bun run verify:pi-load",
43
+ "typecheck": "tsgo --noEmit -p tsconfig.json",
44
+ "lint": "oxlint --config oxlintrc.json .",
45
+ "format": "dprint fmt",
46
+ "format:check": "dprint check",
47
+ "verify:pi-load": "PI_OFFLINE=1 bun x pi --no-extensions -e ./src/index.ts --list-models > /dev/null 2>&1"
48
+ }
49
+ }
File without changes
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: opencode-config
3
+ description: >-
4
+ Set up and configure opencode.jsonc for OpenCode projects. Use when creating a
5
+ new opencode.jsonc configuration file, adding instruction file paths, or
6
+ configuring OpenCode settings for a repository.
7
+ targets:
8
+ - '*'
9
+ ---
10
+
11
+ # OpenCode Config
12
+
13
+ ## Overview
14
+
15
+ Create and configure `opencode.jsonc` in the repository root to customize OpenCode behavior per project.
16
+
17
+ ## Setup
18
+
19
+ 1. Create `opencode.jsonc` in the repository root
20
+ 2. Add the schema reference for validation and autocompletion
21
+ 3. Add instruction file paths to the `instructions` array
22
+
23
+ ### Minimal Configuration
24
+
25
+ ```jsonc
26
+ {
27
+ "$schema": "https://opencode.ai/config.json",
28
+ }
29
+ ```
30
+
31
+ ### .github Instructions
32
+
33
+ If there is `.github/instructions` folder update config to include `instructions` field, like so:
34
+
35
+ ```jsonc
36
+ "instructions": [
37
+ ".github/instructions/*.instructions.md",
38
+ ],
39
+ ```
40
+
41
+ ### .github Skills
42
+
43
+ If there is `.github/skills` folder update config to include `skills` field, like so:
44
+
45
+ ```jsonc
46
+ "skills": {
47
+ "paths": [
48
+ ".github/skills",
49
+ ]
50
+ }
51
+ ```
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: react-development
3
+ description: >-
4
+ Build and modify React components, hooks, context providers, and JSX render
5
+ trees. Use when implementing or refactoring React UI code, component APIs,
6
+ render branches, shared primitives, hook-driven state, DOM structure, or test
7
+ ID conventions. Covers the required `data-testid` naming contract and the ban
8
+ on using `createElement` from React in regular application code.
9
+ ---
10
+
11
+ # React Development
12
+
13
+ Use existing React patterns before introducing new ones. Preserve accessibility, composability, and readable JSX.
14
+
15
+ ## Workflow
16
+
17
+ 1. Inspect the existing component, shared primitives, hooks, and nearby tests before editing.
18
+ 2. Reuse an existing component or hook when one already expresses the pattern.
19
+ 3. Keep rendering in JSX. Extract helpers or hooks instead of switching to `createElement`.
20
+ 4. Apply the test ID contract exactly when a tagged element is needed.
21
+ 5. Run the narrowest relevant validation first, then broader lint and test commands.
22
+
23
+ ## Non-negotiable rules
24
+
25
+ ### 1. Use the test ID contract exactly
26
+
27
+ Apply these rules exactly unless the repository documents a different contract:
28
+
29
+ - Use the plain component name on the root rendered element of a component.
30
+ - Use `ComponentName--thing` for tagged child elements inside that component.
31
+ - Use kebab-case for `thing`.
32
+ - Use semantic targets, not positional names.
33
+ - Use the local helper component name when a helper component renders its own tagged root.
34
+ - Do not invent `--root` or other suffixes on the root unless the repository explicitly requires them.
35
+
36
+ Valid:
37
+
38
+ ```tsx
39
+ export function PlanChat() {
40
+ return (
41
+ <section data-testid='PlanChat'>
42
+ <div data-testid='PlanChat--thread-viewport' />
43
+ </section>
44
+ );
45
+ }
46
+ ```
47
+
48
+ ```tsx
49
+ function ReasoningPart() {
50
+ return <ToolCallCard testId='ReasoningPart' />;
51
+ }
52
+ ```
53
+
54
+ Invalid:
55
+
56
+ ```tsx
57
+ <section data-testid='PlanChat--root' />
58
+ ```
59
+
60
+ ```tsx
61
+ <div data-testid='thread-viewport' />
62
+ ```
63
+
64
+ ```tsx
65
+ function ReasoningPart() {
66
+ return <ToolCallCard testId='PlanChat--reasoning-card' />;
67
+ }
68
+ ```
69
+
70
+ Prefer accessible queries in tests. Add `data-testid` only when the element is not reliably targetable through role, label, text, or stable semantic structure.
71
+
72
+ ### 2. Keep regular React code in JSX
73
+
74
+ Do not use `createElement` or `React.createElement` in ordinary application code.
75
+
76
+ Use JSX for:
77
+
78
+ - normal component bodies
79
+ - conditional rendering
80
+ - lists and mapping
81
+ - wrapper composition
82
+ - provider trees
83
+ - tool or widget registries that can be expressed directly in JSX
84
+
85
+ Allow `createElement` only when a specific domain constraint requires it and that requirement is documented explicitly at the use site or in adjacent documentation. Typical exceptions are rare and include cases such as:
86
+
87
+ - schema-driven renderers
88
+ - AST or MDX renderers
89
+ - plugin systems that receive component types dynamically
90
+ - framework integration points that require raw element factory calls
91
+
92
+ Do not introduce `createElement` just to:
93
+
94
+ - avoid JSX syntax
95
+ - build dynamic props more mechanically
96
+ - mimic framework internals
97
+ - shorten code that JSX already expresses clearly
98
+
99
+ When an exception is truly required, isolate it, document why JSX is insufficient, and test it.
100
+
101
+ ## Component design rules
102
+
103
+ - Prefer function components and hooks over class components unless the codebase already requires a class boundary.
104
+ - Keep props narrow and typed.
105
+ - Extract pure transforms into helpers instead of embedding large calculations in render.
106
+ - Extract repeated stateful behavior into hooks only when more than one caller needs it or the component becomes hard to read.
107
+ - Reuse shared primitives for buttons, inputs, dialogs, cards, and layout shells before adding one-off markup.
108
+ - Keep render branches explicit. Make loading, empty, error, and success states easy to read.
109
+ - Preserve accessible names and roles when refactoring structure.
110
+
111
+ ## Review checklist
112
+
113
+ Before finishing a React change, verify all of the following:
114
+
115
+ - root test IDs use the plain component name
116
+ - child test IDs use `ComponentName--thing`
117
+ - helper components with their own tagged roots use their own names
118
+ - no new `createElement` usage was introduced without an explicit documented exception
119
+ - shared primitives were reused where appropriate
120
+ - accessible queries remain possible for user-facing controls
121
+ - relevant lint, type, and test commands were run
122
+
123
+ ## References
124
+
125
+ - Read `references/oxlint.md` when adding or changing React-specific lint rules, custom Oxlint plugins, test ID enforcement, or `createElement` bans.
126
+ - Read `references/reactPolicyPlugin.js` for a concrete local Oxlint plugin example.
127
+ - Read `references/reactPolicyPlugin.test.ts` for a concrete Bun test harness for the plugin.
128
+ - Read `references/oxlintrc.json` for a concrete scoped config example.
129
+
130
+ ## Companion skills
131
+
132
+ Use related skills when the task goes deeper in those areas:
133
+
134
+ - `react-testing` for Storybook stories, play functions, and interaction coverage
135
+ - `typescript-code-quality` when TypeScript structure and type-safety rules matter heavily
@@ -0,0 +1,144 @@
1
+ # Oxlint for React Repositories
2
+
3
+ Read this file when the task involves adding, tightening, or debugging React lint rules, custom Oxlint plugins, or CI enforcement.
4
+
5
+ ## Enforcement strategy
6
+
7
+ Use Oxlint for fast editor and CI feedback.
8
+
9
+ Split enforcement into two groups:
10
+
11
+ 1. **Built-in rules** for generic quality and correctness
12
+ 2. **Local JS plugins** for repository-specific React contracts
13
+
14
+ Prefer built-in rules when they express the requirement directly. Use a local plugin only when the rule is specific to the repository and cannot be expressed well with built-ins.
15
+
16
+ ## High-value React policies to enforce
17
+
18
+ ### 1. Ban `createElement` in regular application code
19
+
20
+ Use a linter rule or repo-local plugin to reject:
21
+
22
+ - `import { createElement } from 'react'`
23
+ - `React.createElement(...)`
24
+
25
+ Scope exceptions explicitly to:
26
+
27
+ - tests
28
+ - Storybook setup/mocks
29
+ - documented framework boundaries
30
+ - documented schema/plugin renderers
31
+
32
+ If the repository allows a rare production exception, require a short comment at the use site explaining why JSX is insufficient.
33
+
34
+ ## 2. Enforce the test ID naming contract
35
+
36
+ If the repository uses test IDs, prefer a custom plugin for exact policy enforcement.
37
+
38
+ Example policy:
39
+
40
+ - component root: `ComponentName`
41
+ - child elements: `ComponentName--thing`
42
+ - helper components with their own tagged roots use their own names
43
+
44
+ Use a local plugin when the policy depends on component names, render branches, or JSX structure.
45
+
46
+ ## 3. Scope rules by file type
47
+
48
+ Do not run React-specific rules on the whole repository.
49
+
50
+ Use `overrides` to target the file types the policy actually governs.
51
+
52
+ For repositories where every `.tsx` file is in scope for React UI policy, prefer this broad pattern so new files are not missed:
53
+
54
+ ```json
55
+ {
56
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
57
+ "jsPlugins": ["./scripts/oxlint/reactPolicyPlugin.js"],
58
+ "overrides": [
59
+ {
60
+ "files": ["**/*.tsx"],
61
+ "rules": {
62
+ "repo-react/no-regular-create-element": "error",
63
+ "repo-react/require-component-root-testid": "error"
64
+ }
65
+ }
66
+ ]
67
+ }
68
+ ```
69
+
70
+ Use narrower globs only when the repository deliberately excludes some `.tsx` categories from the policy.
71
+
72
+ ## Local plugin guidance
73
+
74
+ Implement a local plugin when the repository needs React-specific contracts that built-ins do not cover.
75
+
76
+ Concrete reference files in this skill:
77
+
78
+ - `references/reactPolicyPlugin.js` — example plugin with `no-regular-create-element` and `require-component-root-testid`
79
+ - `references/reactPolicyPlugin.test.ts` — Bun tests that run Oxlint against temp fixtures
80
+ - `references/oxlintrc.json` — scoped config example wiring the plugin into Oxlint
81
+
82
+ Typical cases:
83
+
84
+ - test ID naming derived from component names
85
+ - banning `createElement` except in scoped files
86
+ - repository-specific wrapper conventions
87
+ - enforcing root render wrappers for provider-only components
88
+
89
+ Keep plugins small and exact. One repository contract per rule is usually the right granularity.
90
+
91
+ ## Rule design guidance
92
+
93
+ ### `no-regular-create-element`
94
+
95
+ The rule should:
96
+
97
+ - flag `createElement` imports from `react`
98
+ - flag `React.createElement(...)`
99
+ - ignore test files and documented exception paths through config scoping, not heuristics
100
+ - report a direct message: use JSX instead of `createElement` in regular React code
101
+
102
+ ### `require-component-root-testid`
103
+
104
+ The rule should:
105
+
106
+ - detect exported PascalCase components
107
+ - inspect all non-null render branches
108
+ - require exact root test IDs
109
+ - validate child test IDs against the component name
110
+ - ignore nested functions and nested classes while traversing one component body
111
+
112
+ Use a repository-level test in addition to the plugin when the rule performs AST-heavy structural checks.
113
+
114
+ ## Validation workflow
115
+
116
+ When adding or changing React lint rules:
117
+
118
+ 1. Run the targeted Oxlint command on the affected files first.
119
+ 2. Run the plugin tests if a local plugin changed.
120
+ 3. Run the type checker.
121
+ 4. Run adjacent React tests.
122
+ 5. Run the broader repo lint command last.
123
+
124
+ Example:
125
+
126
+ ```bash
127
+ bun x oxlint -c oxlintrc.json --deny-warnings src/components
128
+ bun test scripts/oxlint/__tests__/reactPolicyPlugin.test.ts
129
+ bun x tsgo -p . --noEmit
130
+ bun test src/components --max-concurrency=1
131
+ ```
132
+
133
+ ## Failure policy
134
+
135
+ Do not weaken a React lint rule just to get a change through.
136
+
137
+ If the rule blocks valid code, fix one of these instead:
138
+
139
+ - the component structure
140
+ - the rule implementation
141
+ - the file scope in config
142
+ - the documented policy
143
+
144
+ Do not add blanket ignores when a scoped override or a better rule is the correct solution.
@@ -0,0 +1,16 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "jsPlugins": ["./scripts/oxlint/reactPolicyPlugin.js"],
4
+ "rules": {
5
+ "eqeqeq": "error"
6
+ },
7
+ "overrides": [
8
+ {
9
+ "files": ["**/*.tsx"],
10
+ "rules": {
11
+ "repo-react/no-regular-create-element": "error",
12
+ "repo-react/require-component-root-testid": "error"
13
+ }
14
+ }
15
+ ]
16
+ }