Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .claude/skills/development-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,16 @@ This skill provides all commands and best practices for building, developing, an
## Development Guidelines

### Commit Strategy

Keep commits tiny but meaningful:

- Use git hunks (`-p` flag) to selectively commit changes
- Write detailed commit messages
- Ensure each commit is logically complete
- Use English for all commit messages

### Git Workflow

- **Never push directly to main** without permission
- Create a new branch for changes
- Create a pull request to merge into main
Expand All @@ -53,6 +56,7 @@ Keep commits tiny but meaningful:
### When to Rebuild

Always run `pnpm rebuild` when:

- Updating OpenAPI specifications
- After pulling spec changes
- Before committing generated files
Expand All @@ -72,16 +76,19 @@ Always run `pnpm rebuild` when:
## Troubleshooting

### Command Failures

If `pnpm exec <command>` fails, try `pnpm dlx <command>` instead.

If bash commands fail, try running with fish shell:

```bash
fish -c "<command>"
```

## Commit Message Best Practices

### Guidelines

- Keep each commit as tiny as possible
- Write detailed commit messages explaining the "why"
- Each commit should be meaningful (not just a single line change)
Expand All @@ -90,9 +97,11 @@ fish -c "<command>"
- Reference issues and PRs when relevant

### Commit Structure

Format: `type(scope): description`

Example:

```
feat(parser): add support for custom parameter transformers

Expand All @@ -102,28 +111,34 @@ feat(parser): add support for custom parameter transformers
```

### When Committing

1. Run `git diff` to review all changes
2. Use `git add -p` to review and stage hunks selectively
3. Write comprehensive message explaining the purpose
4. Verify with `git status` before committing

### TypeScript Issues

Use the TypeScript exhaustiveness pattern (`satisfies never`) when branching on unions. See `typescript-patterns` skill for examples.

## Pull Request Guidelines

### PR Title Format

Use the same format as commit messages: `type(scope): description`

Types: `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, `ci`, `perf`

Examples:

- `feat(tools): add support for custom OpenAPI specs`
- `fix(parser): handle empty response bodies`
- `refactor(skills): unify cursor rules and claude skills`

### PR Body

Include:

- **Summary**: 1-3 bullet points describing changes
- **Test plan**: How to verify the changes work
- Reference related issues with `Closes #123` or `Fixes #123`
Expand Down Expand Up @@ -156,6 +171,7 @@ Include:
## Publishing & Deployment

When ready to release:

1. Ensure all tests pass: `pnpm test`
2. Verify type checking: `pnpm typecheck`
3. Build documentation: `pnpm docs:build`
Expand Down
5 changes: 5 additions & 0 deletions .claude/skills/file-operations/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ async function fetchData(url: string): Promise<unknown> {
- Simply use the globally available `fetch` function

2. **Always check response.ok**:

```typescript
if (!response.ok) {
throw new Error(`API error: ${response.status} for ${url}`);
Expand All @@ -61,6 +62,7 @@ async function fetchData(url: string): Promise<unknown> {
### Examples

**GET with JSON response**:

```typescript
async function getUser(userId: string): Promise<User> {
try {
Expand All @@ -78,6 +80,7 @@ async function getUser(userId: string): Promise<User> {
```

**POST with JSON body**:

```typescript
async function createUser(data: CreateUserInput): Promise<User> {
try {
Expand All @@ -101,6 +104,7 @@ async function createUser(data: CreateUserInput): Promise<User> {
```

**With Authorization**:

```typescript
async function getProtectedData(token: string): Promise<Data> {
try {
Expand All @@ -124,6 +128,7 @@ async function getProtectedData(token: string): Promise<Data> {
## When to Use Direct HTTP Clients

Only use specialised HTTP clients when:

- You need advanced features not covered by fetch (e.g., interceptors, retries)
- You're integrating with a framework that requires it
- Document why you're not using native fetch
18 changes: 18 additions & 0 deletions .claude/skills/typescript-patterns/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Guidelines for writing clean, type-safe TypeScript code in this repository.
When branching on string unions, use the `satisfies never` pattern to guarantee compile-time exhaustiveness without introducing temporary variables.

**Pattern**:

```typescript
switch (bodyType) {
case 'json':
Expand All @@ -33,6 +34,7 @@ switch (bodyType) {
```

**Benefits**:

- Adding a new union member will trigger a compile-time error
- Keeps union definition and switch statement in sync automatically
- No temporary variables needed
Expand All @@ -43,13 +45,15 @@ switch (bodyType) {
Always use specific types instead of `any` when possible.

**Bad**:

```typescript
function processData(data: any): any {
return data.value;
}
```

**Good**:

```typescript
function processData<T extends { value: U }, U>(data: T): U {
return data.value;
Expand All @@ -65,6 +69,7 @@ function processData(data: unknown): unknown {
```

**Alternatives to `any`**:

- Use `unknown` when type is truly not known, then narrow with type guards
- Use `Record<string, unknown>` for objects with unknown property values
- Use union types to represent multiple possible types
Expand All @@ -75,6 +80,7 @@ function processData(data: unknown): unknown {
Never use non-null assertions. Instead, use proper null checking.

**Bad**:

```typescript
function getConfig(configMap: Map<string, Config>): Config {
const config = configMap.get('default');
Expand All @@ -83,6 +89,7 @@ function getConfig(configMap: Map<string, Config>): Config {
```

**Good**:

```typescript
function getConfig(configMap: Map<string, Config>): Config {
const config = configMap.get('default');
Expand All @@ -103,6 +110,7 @@ function getConfig(configMap: Map<string, Config>): Config {
Create new variables instead of reassigning function parameters.

**Bad**:

```typescript
function mergeOptions(options: Options, overrides?: Options): Options {
options = { ...options, ...overrides }; // Reassignment
Expand All @@ -111,6 +119,7 @@ function mergeOptions(options: Options, overrides?: Options): Options {
```

**Good**:

```typescript
function mergeOptions(options: Options, overrides?: Options): Options {
const mergedOptions = { ...options, ...overrides };
Expand All @@ -123,6 +132,7 @@ function mergeOptions(options: Options, overrides?: Options): Options {
Use namespaces or simple exported functions instead.

**Bad**:

```typescript
export class Utils {
public static formatDate(date: Date): string {
Expand All @@ -136,6 +146,7 @@ export class Utils {
```

**Good - Namespace**:

```typescript
export namespace Utils {
export const formatDate = (date: Date): string => {
Expand All @@ -149,6 +160,7 @@ export namespace Utils {
```

**Better - Simple exports**:

```typescript
export const formatDate = (date: Date): string => {
return date.toISOString();
Expand All @@ -164,13 +176,15 @@ export const parseDate = (dateStr: string): Date => {
Always specify return types for functions.

**Bad**:

```typescript
const calculateTotal = (items: Item[]) => {
return items.reduce((sum, item) => sum + item.price, 0);
};
```

**Good**:

```typescript
const calculateTotal = (items: Item[]): number => {
return items.reduce((sum, item) => sum + item.price, 0);
Expand All @@ -187,6 +201,7 @@ function calculateTotal(items: Item[]): number {
Use proper type-safe methods to remove properties instead of setting to `undefined` or using `delete`.

**Bad**:

```typescript
function removeProperty(obj: Record<string, JSONSchema7Definition>): void {
obj['propertyToRemove'] = undefined; // Type error!
Expand All @@ -195,6 +210,7 @@ function removeProperty(obj: Record<string, JSONSchema7Definition>): void {
```

**Good - Destructuring (Immutable)**:

```typescript
function removeProperty(obj: Record<string, JSONSchema7Definition>): Record<string, JSONSchema7Definition> {
const { propertyToRemove, ...rest } = obj;
Expand All @@ -203,6 +219,7 @@ function removeProperty(obj: Record<string, JSONSchema7Definition>): Record<stri
```

**Good - Delete (In-place)**:

```typescript
function removeProperty(obj: Record<string, JSONSchema7Definition>): void {
delete obj['propertyToRemove'];
Expand All @@ -212,6 +229,7 @@ function removeProperty(obj: Record<string, JSONSchema7Definition>): void {
## Remove Unused Code

After refactoring, always remove unused code:

- Delete unused variables, parameters, functions, classes, imports
- Don't comment out old code - delete it (git history preserves it)
- Remove unreachable code paths
Expand Down
1 change: 1 addition & 0 deletions .claude/skills/typescript-testing/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This skill guides testing practices for the StackOne SDK using Vitest test runne
## Testing Framework

The project uses **Vitest** as the test runner. Run tests with:

- `pnpm test` - Run all tests (unit, examples, scripts)
- `pnpm vitest src/path/to/file.test.ts` - Run a specific test file
- `pnpm vitest -t "test name"` - Run tests matching a pattern
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-title.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "Check PR title"
name: 'Check PR title'

on:
pull_request:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/claude.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ jobs:
uses: anthropics/claude-code-action@6337623ebba10cf8c8214b507993f8062fd4ccfb # v1.0.22
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
allowed_tools: "Bash,mcp__context7__resolve-library-id,mcp__context7__get-library-docs"
allowed_tools: 'Bash,mcp__context7__resolve-library-id,mcp__context7__get-library-docs'
custom_instructions: |
"This is a toolset for the StackOne API. StackOne is an integrations company which provides a unified api for many SaaS companies. This toolset allows AI agent developers to use the StackOne API through a tools interface. It provides developer friendly transformations and shims to allow agents to work with the api. These largely revolve around handling of documents eg. getting them from a local or remote file system and converting them to a format that can be used by the api. The package is written in typescript using Bun and released with release-please to NPM. It should be usable in Node.js and Bun. Never use any Bun specific features. The repo contains examples for every new feature. All examples should be runnable and are used to build the docs."
4 changes: 2 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ jobs:
- name: Setup Node.js for npm
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
with:
node-version: "latest"
registry-url: "https://registry.npmjs.org"
node-version: 'latest'
registry-url: 'https://registry.npmjs.org'

- name: 💫 Install dependencies
run: nix develop --command pnpm install --frozen-lockfile
Expand Down
20 changes: 10 additions & 10 deletions .mcp.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"mcpServers": {
"context7": {
"type": "http",
"url": "https://mcp.context7.com/mcp"
},
"grep": {
"type": "http",
"url": "https://mcp.grep.app"
}
}
"mcpServers": {
"context7": {
"type": "http",
"url": "https://mcp.context7.com/mcp"
},
"grep": {
"type": "http",
"url": "https://mcp.grep.app"
}
}
}
6 changes: 6 additions & 0 deletions .oxfmtrc.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"useTabs": true,
"semi": true,
"singleQuote": true,
}
Loading
Loading