Skip to content
Closed
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
136 changes: 99 additions & 37 deletions docs/reference/file-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,118 @@ This is Rulesync, a Node.js CLI tool that automatically generates configuration

Hooks run scripts at lifecycle events (e.g. session start, before tool use). Events use **canonical camelCase** in this file; Cursor uses them as-is; Claude Code gets PascalCase in `.claude/settings.json`; OpenCode hooks are generated as a JavaScript plugin at `.opencode/plugins/rulesync-hooks.js`; Gemini CLI gets PascalCase (with some specific name mappings) in `.gemini/settings.json`.

**Hook definition fields:**

| Field | Type | Description |
|-------|------|-------------|
| `command` | string | Shell command to execute (for command-type hooks) |
| `type` | `"command"` \| `"prompt"` | Hook type (default: `"command"`) |
| `timeout` | number | Timeout in milliseconds |
| `matcher` | string | Pattern to match against (e.g. tool names for `preToolUse`/`postToolUse`) |
| `prompt` | string | Prompt text (for prompt-type hooks) |
| `loop_limit` | number \| null | Maximum number of loop iterations (`null` for unlimited) |
| `name` | string | Hook name identifier |
| `description` | string | Human-readable description of the hook |

**Event support:**

- **Cursor:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `sessionEnd`, `beforeSubmitPrompt`, `subagentStop`, `preCompact`, `afterFileEdit`, `afterShellExecution`, `postToolUseFailure`, `subagentStart`, `beforeShellExecution`, `beforeMCPExecution`, `afterMCPExecution`, `beforeReadFile`, `afterAgentResponse`, `afterAgentThought`, `beforeTabFileRead`, `afterTabFileEdit`
- **Claude Code:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `sessionEnd`, `beforeSubmitPrompt`, `subagentStop`, `preCompact`, `permissionRequest`, `notification`, `setup`, `worktreeCreate`, `worktreeRemove`
- **Cursor:** `sessionStart`, `sessionEnd`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`, `subagentStop`, `preCompact`, `postToolUseFailure`, `subagentStart`, `beforeShellExecution`, `afterShellExecution`, `beforeMCPExecution`, `afterMCPExecution`, `beforeReadFile`, `afterFileEdit`, `afterAgentResponse`, `afterAgentThought`, `beforeTabFileRead`, `afterTabFileEdit`
- **Claude Code:** `sessionStart`, `sessionEnd`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`, `subagentStop`, `preCompact`, `permissionRequest`, `notification`, `setup`, `worktreeCreate`, `worktreeRemove`

> **Note:** `worktreeCreate` and `worktreeRemove` are Claude Code-specific events and do not support the `matcher` field. Any matcher defined in the config will be ignored for these events.

- **OpenCode:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `afterFileEdit`, `afterShellExecution`, `permissionRequest`
- **Kilo:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `afterFileEdit`, `afterShellExecution`, `permissionRequest`
- **GitHub Copilot:** `sessionStart`, `sessionEnd`, `beforeSubmitPrompt`, `preToolUse`, `postToolUse`, `afterError`
- **Gemini CLI:** `sessionStart`, `sessionEnd`, `beforeSubmitPrompt`, `stop`, `beforeAgentResponse`, `afterAgentResponse`, `beforeToolSelection`, `preToolUse`, `postToolUse`, `preCompact`, `notification`
- **Codex CLI:** `sessionStart`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`
- **Factory Droid:** `sessionStart`, `sessionEnd`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`, `subagentStop`, `preCompact`, `permissionRequest`, `notification`, `setup`
- **DeepAgents:** `sessionStart`, `sessionEnd`, `beforeSubmitPrompt`, `permissionRequest`, `postToolUseFailure`, `stop`, `preCompact`

> **Note:** Rulesync implements OpenCode hooks as a plugin, so importing from OpenCode to rulesync is not supported. OpenCode only supports command-type hooks (not prompt-type).

> **Note:** GitHub Copilot's format uses separate `powershell` and `bash` fields for hooks. Rulesync supports only a single `command` field and resolves this by emitting the command under the `powershell` key on Windows, and under the `bash` key on all other platforms.

Use optional **override keys** so tool-specific events and config live in one file without leaking to others: `cursor.hooks` for Cursor-only events, `claudecode.hooks` for Claude Code-only, `opencode.hooks` for OpenCode-only, `kilo.hooks` for Kilo-only, `copilot.hooks` for GitHub Copilot-only, `geminicli.hooks` for Gemini CLI-only, `codexcli.hooks` for Codex CLI-only, `factorydroid.hooks` for Factory Droid-only, `deepagents.hooks` for DeepAgents-only. Events in shared `hooks` that a tool does not support are skipped for that tool (and a warning is logged at generate time).

Example:

```json
{
"version": 1,
"hooks": {
"sessionStart": [
{
"type": "command",
"command": ".rulesync/hooks/session-start.sh",
"name": "session-init",
"description": "Initialize session environment"
}
],
"preToolUse": [
{
"matcher": "Bash",
"type": "prompt",
"prompt": "Review the command before execution for safety",
"description": "Safety check for shell commands"
}
],
"postToolUse": [
{
"matcher": "Write|Edit",
"command": ".rulesync/hooks/format.sh",
"timeout": 10000
}
],
"stop": [
{
"command": ".rulesync/hooks/audit.sh",
"loop_limit": null
}
]
},
"claudecode": {
"hooks": {
"worktreeCreate": [{ "command": ".claude/hooks/worktree-setup.sh" }]
}
}
}
```

> **Note:** The `claudecode.hooks` override is shown above because `worktreeCreate` and `worktreeRemove` are Claude Code-specific events that do not support the `matcher` field. Use tool-specific override keys only for events exclusive to that tool; shared events belong in the top-level `hooks` section.

**Field support by tool:**

Not all tools support every hook definition field. Fields listed as unsupported are silently dropped during generation.

| Field | Cursor | Claude Code | Copilot | Gemini CLI | OpenCode | Kilo | Codex CLI | Factory Droid | DeepAgents |
|-------|--------|-------------|---------|------------|----------|------|-----------|---------------|------------|
| `command` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `type` | ✓ | ✓ | ✗ ^1 | ✓ | ✗ ^1 | ✗ ^1 | ✗ ^1 | ✓ | ✗ ^1 |
| `timeout` | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ ^2 |
| `matcher` | ✓ | ✓ ^3 | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| `prompt` | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ ^4 | ✗ |
| `loop_limit` | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| `name` | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| `description` | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |

1. Only `"command"` type is supported; `"prompt"` type hooks are skipped.
2. Hardcoded to 5 seconds; custom timeout is not supported.
3. Except `worktreeCreate`/`worktreeRemove` events, which ignore `matcher`.
4. Rulesync outputs the field, but Factory Droid only supports `"command"` type natively.

**Tool-specific output transformations:**

| Tool | Unique output keys / behavior |
|------|-------------------------------|
| **GitHub Copilot** | `command` is emitted as `bash` (non-Windows) or `powershell` (Windows); `timeout` is emitted as `timeoutSec` |
| **Gemini CLI** | Hooks are grouped by `matcher` in output; relative commands (starting with `./`) are prefixed with `$GEMINI_PROJECT_DIR/` |
| **Claude Code** | Relative commands are prefixed with `$CLAUDE_PROJECT_DIR/`; `worktreeCreate`/`worktreeRemove` ignore `matcher` |
| **Factory Droid** | Relative commands are prefixed with `$FACTORY_PROJECT_DIR/` |
| **OpenCode / Kilo** | Generated as a JavaScript plugin file (not JSON); only `command`-type hooks are supported |
| **Codex CLI** | Hooks are grouped by `matcher` in output; only `command`-type hooks; generates `.codex/config.toml` with feature flag |
| **DeepAgents** | Output uses flat array structure; `command` is emitted as `["bash", "-c", "..."]`; `matcher` is not supported |

## `.copilot/mcp-config.json`

Example:
Expand Down Expand Up @@ -85,41 +182,6 @@ This file is used by the GitHub Copilot CLI for MCP server configuration. Rulesy

Rulesync preserves explicit `type` values for `http`, `sse`, and `local` servers. For command-based servers that omit a transport type, Rulesync emits the mandatory `"type": "stdio"` field required by the Copilot CLI.

Use optional **override keys** so tool-specific events and config live in one file without leaking to others: `cursor.hooks` for Cursor-only events, `claudecode.hooks` for Claude-only, `opencode.hooks` for OpenCode-only, `copilot.hooks` for GitHub Copilot-only, `geminicli.hooks` for Gemini CLI-only. Events in shared `hooks` that a tool does not support are skipped for that tool (and a warning is logged at generate time).

Example:

```json
{
"version": 1,
"hooks": {
"sessionStart": [{ "type": "command", "command": ".rulesync/hooks/session-start.sh" }],
"postToolUse": [{ "matcher": "Write|Edit", "command": ".rulesync/hooks/format.sh" }],
"stop": [{ "command": ".rulesync/hooks/audit.sh" }]
},
"cursor": {
"hooks": {
"afterFileEdit": [{ "command": ".cursor/hooks/format.sh" }]
}
},
"claudecode": {
"hooks": {
"notification": [
{
"matcher": "permission_prompt",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/notify.sh"
}
]
}
},
"opencode": {
"hooks": {
"afterShellExecution": [{ "command": ".rulesync/hooks/post-shell.sh" }]
}
}
}
```

## `rulesync/commands/*.md`

Example:
Expand Down
136 changes: 99 additions & 37 deletions skills/rulesync/file-formats.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,118 @@ This is Rulesync, a Node.js CLI tool that automatically generates configuration

Hooks run scripts at lifecycle events (e.g. session start, before tool use). Events use **canonical camelCase** in this file; Cursor uses them as-is; Claude Code gets PascalCase in `.claude/settings.json`; OpenCode hooks are generated as a JavaScript plugin at `.opencode/plugins/rulesync-hooks.js`; Gemini CLI gets PascalCase (with some specific name mappings) in `.gemini/settings.json`.

**Hook definition fields:**

| Field | Type | Description |
|-------|------|-------------|
| `command` | string | Shell command to execute (for command-type hooks) |
| `type` | `"command"` \| `"prompt"` | Hook type (default: `"command"`) |
| `timeout` | number | Timeout in milliseconds |
| `matcher` | string | Pattern to match against (e.g. tool names for `preToolUse`/`postToolUse`) |
| `prompt` | string | Prompt text (for prompt-type hooks) |
| `loop_limit` | number \| null | Maximum number of loop iterations (`null` for unlimited) |
| `name` | string | Hook name identifier |
| `description` | string | Human-readable description of the hook |

**Event support:**

- **Cursor:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `sessionEnd`, `beforeSubmitPrompt`, `subagentStop`, `preCompact`, `afterFileEdit`, `afterShellExecution`, `postToolUseFailure`, `subagentStart`, `beforeShellExecution`, `beforeMCPExecution`, `afterMCPExecution`, `beforeReadFile`, `afterAgentResponse`, `afterAgentThought`, `beforeTabFileRead`, `afterTabFileEdit`
- **Claude Code:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `sessionEnd`, `beforeSubmitPrompt`, `subagentStop`, `preCompact`, `permissionRequest`, `notification`, `setup`, `worktreeCreate`, `worktreeRemove`
- **Cursor:** `sessionStart`, `sessionEnd`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`, `subagentStop`, `preCompact`, `postToolUseFailure`, `subagentStart`, `beforeShellExecution`, `afterShellExecution`, `beforeMCPExecution`, `afterMCPExecution`, `beforeReadFile`, `afterFileEdit`, `afterAgentResponse`, `afterAgentThought`, `beforeTabFileRead`, `afterTabFileEdit`
- **Claude Code:** `sessionStart`, `sessionEnd`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`, `subagentStop`, `preCompact`, `permissionRequest`, `notification`, `setup`, `worktreeCreate`, `worktreeRemove`

> **Note:** `worktreeCreate` and `worktreeRemove` are Claude Code-specific events and do not support the `matcher` field. Any matcher defined in the config will be ignored for these events.

- **OpenCode:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `afterFileEdit`, `afterShellExecution`, `permissionRequest`
- **Kilo:** `sessionStart`, `preToolUse`, `postToolUse`, `stop`, `afterFileEdit`, `afterShellExecution`, `permissionRequest`
- **GitHub Copilot:** `sessionStart`, `sessionEnd`, `beforeSubmitPrompt`, `preToolUse`, `postToolUse`, `afterError`
- **Gemini CLI:** `sessionStart`, `sessionEnd`, `beforeSubmitPrompt`, `stop`, `beforeAgentResponse`, `afterAgentResponse`, `beforeToolSelection`, `preToolUse`, `postToolUse`, `preCompact`, `notification`
- **Codex CLI:** `sessionStart`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`
- **Factory Droid:** `sessionStart`, `sessionEnd`, `preToolUse`, `postToolUse`, `beforeSubmitPrompt`, `stop`, `subagentStop`, `preCompact`, `permissionRequest`, `notification`, `setup`
- **DeepAgents:** `sessionStart`, `sessionEnd`, `beforeSubmitPrompt`, `permissionRequest`, `postToolUseFailure`, `stop`, `preCompact`

> **Note:** Rulesync implements OpenCode hooks as a plugin, so importing from OpenCode to rulesync is not supported. OpenCode only supports command-type hooks (not prompt-type).

> **Note:** GitHub Copilot's format uses separate `powershell` and `bash` fields for hooks. Rulesync supports only a single `command` field and resolves this by emitting the command under the `powershell` key on Windows, and under the `bash` key on all other platforms.

Use optional **override keys** so tool-specific events and config live in one file without leaking to others: `cursor.hooks` for Cursor-only events, `claudecode.hooks` for Claude Code-only, `opencode.hooks` for OpenCode-only, `kilo.hooks` for Kilo-only, `copilot.hooks` for GitHub Copilot-only, `geminicli.hooks` for Gemini CLI-only, `codexcli.hooks` for Codex CLI-only, `factorydroid.hooks` for Factory Droid-only, `deepagents.hooks` for DeepAgents-only. Events in shared `hooks` that a tool does not support are skipped for that tool (and a warning is logged at generate time).

Example:

```json
{
"version": 1,
"hooks": {
"sessionStart": [
{
"type": "command",
"command": ".rulesync/hooks/session-start.sh",
"name": "session-init",
"description": "Initialize session environment"
}
],
"preToolUse": [
{
"matcher": "Bash",
"type": "prompt",
"prompt": "Review the command before execution for safety",
"description": "Safety check for shell commands"
}
],
"postToolUse": [
{
"matcher": "Write|Edit",
"command": ".rulesync/hooks/format.sh",
"timeout": 10000
}
],
"stop": [
{
"command": ".rulesync/hooks/audit.sh",
"loop_limit": null
}
]
},
"claudecode": {
"hooks": {
"worktreeCreate": [{ "command": ".claude/hooks/worktree-setup.sh" }]
}
}
}
```

> **Note:** The `claudecode.hooks` override is shown above because `worktreeCreate` and `worktreeRemove` are Claude Code-specific events that do not support the `matcher` field. Use tool-specific override keys only for events exclusive to that tool; shared events belong in the top-level `hooks` section.

**Field support by tool:**

Not all tools support every hook definition field. Fields listed as unsupported are silently dropped during generation.

| Field | Cursor | Claude Code | Copilot | Gemini CLI | OpenCode | Kilo | Codex CLI | Factory Droid | DeepAgents |
|-------|--------|-------------|---------|------------|----------|------|-----------|---------------|------------|
| `command` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| `type` | ✓ | ✓ | ✗ ^1 | ✓ | ✗ ^1 | ✗ ^1 | ✗ ^1 | ✓ | ✗ ^1 |
| `timeout` | ✓ | ✓ | ✓ | ✓ | ✗ | ✗ | ✓ | ✓ | ✗ ^2 |
| `matcher` | ✓ | ✓ ^3 | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ | ✗ |
| `prompt` | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ ^4 | ✗ |
| `loop_limit` | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| `name` | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
| `description` | ✗ | ✗ | ✗ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |

1. Only `"command"` type is supported; `"prompt"` type hooks are skipped.
2. Hardcoded to 5 seconds; custom timeout is not supported.
3. Except `worktreeCreate`/`worktreeRemove` events, which ignore `matcher`.
4. Rulesync outputs the field, but Factory Droid only supports `"command"` type natively.

**Tool-specific output transformations:**

| Tool | Unique output keys / behavior |
|------|-------------------------------|
| **GitHub Copilot** | `command` is emitted as `bash` (non-Windows) or `powershell` (Windows); `timeout` is emitted as `timeoutSec` |
| **Gemini CLI** | Hooks are grouped by `matcher` in output; relative commands (starting with `./`) are prefixed with `$GEMINI_PROJECT_DIR/` |
| **Claude Code** | Relative commands are prefixed with `$CLAUDE_PROJECT_DIR/`; `worktreeCreate`/`worktreeRemove` ignore `matcher` |
| **Factory Droid** | Relative commands are prefixed with `$FACTORY_PROJECT_DIR/` |
| **OpenCode / Kilo** | Generated as a JavaScript plugin file (not JSON); only `command`-type hooks are supported |
| **Codex CLI** | Hooks are grouped by `matcher` in output; only `command`-type hooks; generates `.codex/config.toml` with feature flag |
| **DeepAgents** | Output uses flat array structure; `command` is emitted as `["bash", "-c", "..."]`; `matcher` is not supported |

## `.copilot/mcp-config.json`

Example:
Expand Down Expand Up @@ -85,41 +182,6 @@ This file is used by the GitHub Copilot CLI for MCP server configuration. Rulesy

Rulesync preserves explicit `type` values for `http`, `sse`, and `local` servers. For command-based servers that omit a transport type, Rulesync emits the mandatory `"type": "stdio"` field required by the Copilot CLI.

Use optional **override keys** so tool-specific events and config live in one file without leaking to others: `cursor.hooks` for Cursor-only events, `claudecode.hooks` for Claude-only, `opencode.hooks` for OpenCode-only, `copilot.hooks` for GitHub Copilot-only, `geminicli.hooks` for Gemini CLI-only. Events in shared `hooks` that a tool does not support are skipped for that tool (and a warning is logged at generate time).

Example:

```json
{
"version": 1,
"hooks": {
"sessionStart": [{ "type": "command", "command": ".rulesync/hooks/session-start.sh" }],
"postToolUse": [{ "matcher": "Write|Edit", "command": ".rulesync/hooks/format.sh" }],
"stop": [{ "command": ".rulesync/hooks/audit.sh" }]
},
"cursor": {
"hooks": {
"afterFileEdit": [{ "command": ".cursor/hooks/format.sh" }]
}
},
"claudecode": {
"hooks": {
"notification": [
{
"matcher": "permission_prompt",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/notify.sh"
}
]
}
},
"opencode": {
"hooks": {
"afterShellExecution": [{ "command": ".rulesync/hooks/post-shell.sh" }]
}
}
}
```

## `rulesync/commands/*.md`

Example:
Expand Down
Loading
Loading