Feature branches should follow:
feature/<change-name>
oscr/<change-name>
change/<change-name>
Avoid:
ai-*pattern (reserved)- Generic names like
feature-branch
<type>(<scope>): <subject>
<body>
<footer>
Types: feat, fix, docs, style, refactor, test, chore
- Explicit types for all parameters and returns
- Interfaces over type aliases for object shapes
constby default,letonly when reassignment needed- Function ordering: imports → types → constants → functions → exports
- No comments — use descriptive names
- Classes over helper functions
- Nullable (
string | null) over optional (string?) - Function declarations, not arrow functions
- No
any— useunknownwith type guards
Example:
import type { Plugin } from "@opencode-ai/plugin";
interface CardState {
changeName: string;
taskId: string | null;
status: "pending" | "launched" | "done";
}
const VERSION = "0.2.0";
function createCardState(changeName: string): CardState {
return {
changeName,
taskId: null,
status: "pending"
};
}
export { CardState, VERSION, createCardState };bun test # Run all tests
bun test --watch # Watch mode
bun run check # Type checkWrite unit tests for all public functions and tools.
src/types.ts— All interfaces and typessrc/tools/— Custom tool implementationsassets/agents/— Agent markdown filesassets/skills/— Skill SKILL.md filesassets/commands/— Slash command markdown filesassets/templates/— User-modifiable templatestests/unit/— Unit tests
The plugin exports three hooks:
export const plugin: Plugin = async (input) => {
return {
tool: {
// Custom tools registered here
},
async config(_config) {
// Asset installation on first run
},
event: async ({ event }) => {
// Lifecycle event handling
},
};
};- Strict TypeScript enabled
- No console.log in production code
- Early returns to reduce nesting
- Extract complex logic into named methods
- Handle all Promise rejections
- Never log sensitive information
- Validate file paths before operations
- Handle path traversal vulnerabilities