feat: add Cursor project rules for Grok CLI (#143)
Add .cursor/rules/ with MDC rule files covering: - project-overview.mdc: architecture, tech stack, key patterns - typescript-conventions.mdc: ESM imports, naming, type practices - react-ink-components.mdc: Ink terminal UI component guidelines - tools-and-agent.mdc: agent loop, tool interface, adding new tools - development-workflow.mdc: scripts, env vars, CI checklist Update .gitignore to clarify .cursor/ is tracked. Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Ismail Pelaseyed <homanp@users.noreply.github.com>
This commit is contained in:
6 files changed
+285
-1
No files matched your search
@@ -0,0 +1,62 @@
|
||||
---
|
||||
description: Development workflow, scripts, and common tasks
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Development Workflow
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 18+ (required)
|
||||
- Bun 1.0+ (preferred, npm as fallback)
|
||||
|
||||
## Common Commands
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
bun install # preferred
|
||||
npm install # fallback
|
||||
|
||||
# Development (runs from source)
|
||||
bun run dev # uses Bun runtime
|
||||
bun run dev:node # uses tsx (Node.js + TypeScript)
|
||||
|
||||
# Build (compile TypeScript to dist/)
|
||||
bun run build
|
||||
|
||||
# Type checking (no emit)
|
||||
bun run typecheck
|
||||
|
||||
# Linting
|
||||
bun run lint
|
||||
|
||||
# Run the built CLI
|
||||
bun run start # Node.js
|
||||
bun run start:bun # Bun runtime
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `GROK_API_KEY` | Yes | API key for Grok / OpenAI-compatible provider |
|
||||
| `GROK_BASE_URL` | No | Custom API endpoint (default: `https://api.x.ai/v1`) |
|
||||
| `GROK_MODEL` | No | Model override (default: `grok-code-fast-1`) |
|
||||
| `GROK_MAX_TOKENS` | No | Max tokens per response (default: 1536) |
|
||||
| `MORPH_API_KEY` | No | Enables Morph Fast Apply editing |
|
||||
|
||||
Copy `.env.example` to `.env` and fill in your values.
|
||||
|
||||
## Before Submitting Changes
|
||||
|
||||
1. Run `bun run typecheck` — CI enforces this on every PR.
|
||||
2. Run `bun run lint` — fix any ESLint errors.
|
||||
3. Ensure no secrets or `.env` files are committed.
|
||||
4. Follow the PR template in `.github/pull_request_template.md`.
|
||||
|
||||
## Project Structure Conventions
|
||||
|
||||
- Source code lives in `src/`, compiled output in `dist/` (gitignored).
|
||||
- No test framework is configured yet — if adding tests, prefer Vitest for ESM compatibility.
|
||||
- The CLI entry point is `src/index.ts` which uses Commander.js for argument parsing.
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
description: Project overview and architecture for Grok CLI
|
||||
globs:
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Grok CLI — Project Overview
|
||||
|
||||
Grok CLI (`@vibe-kit/grok-cli`) is an open-source conversational AI CLI tool powered by Grok that brings AI assistance directly into the terminal.
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Language**: TypeScript (ES2022, ESNext modules)
|
||||
- **Runtime**: Node.js 18+ (Bun preferred)
|
||||
- **UI Framework**: React with [Ink](https://github.com/vadimdemedes/ink) for terminal rendering
|
||||
- **Build**: `tsc` (TypeScript compiler)
|
||||
- **Package Manager**: Bun (primary), npm (fallback)
|
||||
- **Linting**: ESLint with `@typescript-eslint`
|
||||
- **API Client**: OpenAI SDK (used for OpenAI-compatible APIs including Grok)
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
src/
|
||||
├── index.ts # CLI entry point (Commander.js)
|
||||
├── agent/ # GrokAgent — orchestrates client, tools, MCP
|
||||
├── grok/ # Grok API client and tool definitions
|
||||
├── mcp/ # Model Context Protocol integration
|
||||
├── commands/ # CLI subcommands (e.g. mcp)
|
||||
├── tools/ # Built-in tools (bash, text-editor, search, etc.)
|
||||
├── ui/ # Ink-based terminal UI
|
||||
│ ├── app.tsx
|
||||
│ ├── components/ # Chat interface, diff renderer, inputs, etc.
|
||||
│ └── utils/ # Colors, markdown rendering, code colorizer
|
||||
├── hooks/ # React hooks for input handling
|
||||
├── utils/ # Settings, token counting, custom instructions
|
||||
└── types/ # Shared TypeScript type definitions
|
||||
```
|
||||
|
||||
## Key Patterns
|
||||
|
||||
- **Agent loop**: `GrokAgent` runs an iterative tool-call loop — the LLM responds, tools execute, results feed back until no more tool calls remain or the round limit is hit.
|
||||
- **Streaming**: `processUserMessageStream` is an async generator that yields chunks for real-time UI updates.
|
||||
- **Settings hierarchy**: User-level (`~/.grok/user-settings.json`) → Project-level (`.grok/settings.json`) → System defaults.
|
||||
- **MCP**: External tools are integrated via Model Context Protocol servers (stdio, HTTP, SSE transports).
|
||||
- **ESM only**: The project uses `"type": "module"` — all imports use `.js` extensions for compiled output.
|
||||
|
||||
## CI/CD
|
||||
|
||||
- **typecheck.yml**: Runs `tsc --noEmit` on push/PR to `main`/`develop`.
|
||||
- **security.yml**: Runs `npm audit` and TruffleHog secret scanning.
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
description: Guidelines for React components using Ink for terminal UI
|
||||
globs: "src/ui/**/*.tsx,src/hooks/**/*.ts"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# React + Ink Terminal UI
|
||||
|
||||
## Framework
|
||||
|
||||
This project uses [Ink](https://github.com/vadimdemedes/ink) v4 to render React components in the terminal. Ink provides `<Box>`, `<Text>`, and other primitives instead of HTML elements.
|
||||
|
||||
## Component Patterns
|
||||
|
||||
- Use **functional components** with hooks — no class components.
|
||||
- JSX is compiled with `"jsx": "react"` (classic transform), so `import React from "react"` is required in every `.tsx` file.
|
||||
- Components are in `src/ui/components/` and follow kebab-case naming (`chat-interface.tsx`, `diff-renderer.tsx`).
|
||||
|
||||
## Key Components
|
||||
|
||||
| Component | Purpose |
|
||||
|-----------|---------|
|
||||
| `ChatInterface` | Main chat loop, orchestrates agent interaction |
|
||||
| `ChatHistory` | Renders conversation entries |
|
||||
| `ChatInput` | User text input with key bindings |
|
||||
| `DiffRenderer` | Displays file diffs |
|
||||
| `ModelSelection` | Model picker UI |
|
||||
| `LoadingSpinner` | Animated loading indicator |
|
||||
| `ConfirmationDialog` | User confirmation prompts for tool operations |
|
||||
| `McpStatus` | MCP server connection status |
|
||||
| `CommandSuggestions` | Autocomplete suggestions |
|
||||
| `ApiKeyInput` | API key entry prompt |
|
||||
|
||||
## Ink-Specific Guidelines
|
||||
|
||||
- Use `<Box>` for layout (flexbox model) and `<Text>` for styled text.
|
||||
- Use Ink's `useInput` hook for keyboard handling.
|
||||
- Use `chalk` for color utilities in `src/ui/utils/colors.ts`.
|
||||
- Markdown rendering for chat output uses `marked` + `marked-terminal`.
|
||||
- The app is rendered via `render(React.createElement(ChatInterface, { agent, initialMessage }))` in the entry point.
|
||||
|
||||
## Hooks
|
||||
|
||||
- Custom hooks live in `src/hooks/`.
|
||||
- Follow the `use` prefix convention (`useInput`, `useChat`, etc.).
|
||||
@@ -0,0 +1,69 @@
|
||||
---
|
||||
description: Guidelines for the agent system and tool implementations
|
||||
globs: "src/agent/**/*.ts,src/tools/**/*.ts,src/grok/**/*.ts"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Agent & Tools System
|
||||
|
||||
## GrokAgent
|
||||
|
||||
`GrokAgent` (in `src/agent/grok-agent.ts`) is the core orchestrator. It extends `EventEmitter` and manages:
|
||||
|
||||
- The Grok API client (`GrokClient`)
|
||||
- Built-in tools (text editor, bash, search, todo, confirmation)
|
||||
- Optional Morph Fast Apply editor
|
||||
- MCP server integration
|
||||
- Chat history and message accumulation
|
||||
- Abort/cancellation support
|
||||
|
||||
### Agent Loop
|
||||
|
||||
The agent uses an iterative tool-call pattern:
|
||||
|
||||
1. Send messages to the LLM.
|
||||
2. If the response contains `tool_calls`, execute each tool.
|
||||
3. Append tool results to the message history.
|
||||
4. Repeat until no tool calls remain or `maxToolRounds` is reached.
|
||||
|
||||
Both `processUserMessage` (non-streaming) and `processUserMessageStream` (async generator) implement this loop.
|
||||
|
||||
## Tool Interface
|
||||
|
||||
All tools return a `ToolResult`:
|
||||
|
||||
```typescript
|
||||
interface ToolResult {
|
||||
success: boolean;
|
||||
output?: string;
|
||||
error?: string;
|
||||
data?: any;
|
||||
}
|
||||
```
|
||||
|
||||
Tools should never throw — wrap errors in `{ success: false, error: "..." }`.
|
||||
|
||||
## Built-in Tools
|
||||
|
||||
| Tool | File | Purpose |
|
||||
|------|------|---------|
|
||||
| `TextEditorTool` | `src/tools/text-editor.ts` | View, create, and str_replace files |
|
||||
| `MorphEditorTool` | `src/tools/morph-editor.ts` | Fast Apply editing (requires MORPH_API_KEY) |
|
||||
| `BashTool` | `src/tools/bash.ts` | Execute shell commands |
|
||||
| `SearchTool` | `src/tools/search.ts` | Unified text/file search (uses ripgrep) |
|
||||
| `TodoTool` | `src/tools/todo-tool.ts` | Create/update visual todo lists |
|
||||
| `ConfirmationTool` | `src/tools/confirmation-tool.ts` | User confirmation for operations |
|
||||
|
||||
## Adding a New Tool
|
||||
|
||||
1. Create a new file in `src/tools/` implementing the tool class.
|
||||
2. Export it from `src/tools/index.ts`.
|
||||
3. Register the tool schema in `src/grok/tools.ts` (add to `GROK_TOOLS` array).
|
||||
4. Add the execution case in `GrokAgent.executeTool()`.
|
||||
5. Update the system prompt in the `GrokAgent` constructor to document the tool.
|
||||
|
||||
## MCP Integration
|
||||
|
||||
- MCP tools are prefixed with `mcp__` and dispatched through `executeMCPTool`.
|
||||
- MCP config is loaded from `.grok/settings.json` under `mcpServers`.
|
||||
- Supported transports: stdio, HTTP, SSE (defined in `src/mcp/transports.ts`).
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
description: TypeScript coding conventions and style guidelines
|
||||
globs: "**/*.ts,**/*.tsx"
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# TypeScript Conventions
|
||||
|
||||
## Module System
|
||||
|
||||
- This is an ESM project (`"type": "module"` in package.json).
|
||||
- Always use ES module `import`/`export` syntax — never `require()`.
|
||||
- When importing local modules, include the `.js` extension (TypeScript compiles `.ts` → `.js`):
|
||||
```typescript
|
||||
import { GrokAgent } from "./agent/grok-agent.js";
|
||||
```
|
||||
|
||||
## TypeScript Configuration
|
||||
|
||||
- Target: ES2022, Module: ESNext, JSX: react
|
||||
- `strict: false` and `noImplicitAny: false` — the codebase does not enforce strict mode.
|
||||
- `moduleResolution: "Bundler"` is used.
|
||||
- Source files live in `src/`, compiled output goes to `dist/`.
|
||||
|
||||
## Type Practices
|
||||
|
||||
- Prefer explicit interfaces for public API boundaries (e.g. `ChatEntry`, `ToolResult`, `GrokToolCall`).
|
||||
- Use `type` imports when importing only types:
|
||||
```typescript
|
||||
import type { ChatCompletionMessageParam } from "openai/resources/chat";
|
||||
```
|
||||
- `any` is acceptable where strict typing would add friction, but prefer narrower types when practical.
|
||||
- Shared types belong in `src/types/index.ts`.
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
- **Files**: kebab-case (`grok-agent.ts`, `chat-interface.tsx`, `settings-manager.ts`).
|
||||
- **Classes**: PascalCase (`GrokAgent`, `TextEditorTool`, `BashTool`).
|
||||
- **Interfaces/Types**: PascalCase (`ChatEntry`, `ToolResult`, `StreamingChunk`).
|
||||
- **Functions/variables**: camelCase (`processUserMessage`, `loadApiKey`).
|
||||
- **Constants**: camelCase or UPPER_SNAKE_CASE for true constants (`GROK_TOOLS`).
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Catch errors as `error: any` and access `.message` for display.
|
||||
- Tool execution methods return `ToolResult` objects (`{ success, output?, error? }`) rather than throwing.
|
||||
- Use `process.exit(1)` for fatal CLI errors.
|
||||
|
||||
## ESLint Rules
|
||||
|
||||
- `@typescript-eslint/no-unused-vars`: error
|
||||
- `@typescript-eslint/no-explicit-any`: warn
|
||||
|
||||
Run `bun run lint` to check and `bun run typecheck` to verify types.
|
||||
+4
-1
@@ -99,4 +99,7 @@ temp/
|
||||
|
||||
# Coding agents
|
||||
.claude/
|
||||
.grok/
|
||||
.grok/
|
||||
|
||||
# Cursor config (tracked — do not ignore)
|
||||
# .cursor/
|
||||
Reference in new issue
Block a user