Thank you for your interest in contributing to Nocur! This document provides guidelines and instructions for contributing.
- macOS (required for iOS development)
- Xcode 15+ with iOS Simulator
- Node.js 20+
- Rust (install via rustup)
- pnpm (
npm install -g pnpm) - Swift 5.9+
-
Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/nocur.git cd nocur -
Install dependencies
pnpm install cd claude-service && pnpm install && pnpm build && cd .. cd nocur-swift && swift build && cd ..
-
Run in development mode
pnpm tauri dev
Understanding the codebase:
| Directory | Description |
|---|---|
src/ |
React frontend (TypeScript) |
src-tauri/ |
Rust backend (Tauri commands) |
claude-service/ |
Node.js Claude Agent SDK service |
nocur-swift/ |
Swift CLI for iOS tooling |
sample-app/ |
Test iOS app for development |
- Check existing issues first
- Create a new issue with:
- Clear title and description
- Steps to reproduce
- Expected vs actual behavior
- macOS version, Xcode version
- Relevant logs or screenshots
- Open an issue with the
enhancementlabel - Describe the use case and proposed solution
- Be open to discussion and alternatives
- Create an issue first for significant changes
- Fork the repository and create a branch:
git checkout -b feature/your-feature-name
- Make your changes following our coding guidelines
- Test your changes thoroughly
- Commit with clear messages:
git commit -m "Add feature: description of what it does" - Push and create a PR:
git push origin feature/your-feature-name
- No over-engineering. Build what's needed now, not what might be needed later.
- Explicit over implicit. Clear, readable code beats clever code.
- Fail fast and loud. Errors should be obvious and actionable.
- JSON everything. All tool outputs should be structured JSON for agent parsing.
// Use functional components with hooks
const SimulatorPane = () => {
const { screenshot, refresh } = useSimulator();
return <div>...</div>;
};
// Use @/ path alias for imports
import { Button } from '@/components/ui/button';
// TypeScript strict mode - no `any` types- Use
constarrow functions for components - Colocate related code (component + hook + types)
- Name files in PascalCase for components, camelCase for utilities
// Keep Tauri commands thin - business logic in separate modules
#[tauri::command]
async fn take_screenshot() -> Result<String, String> {
simulator::screenshot().await.map_err(|e| e.to_string())
}- Use
thiserrorfor error types - Use
serdefor all serialization - Commands return
Result<T, String>
// Use async/await over completion handlers
func captureScreenshot() async throws -> Data {
// ...
}
// Output JSON to stdout, errors to stderr
let output = Output(success: true, data: result)
print(try JSONEncoder().encode(output))- Swift 5.9+ with strict concurrency
- Use
ArgumentParserfor CLI commands - All CLI output is JSON
Use semantic color classes from globals.css:
// Good - semantic colors
<div className="bg-surface-base text-text-primary">
<button className="bg-surface-overlay hover:bg-hover">
Click me
</button>
</div>
// Bad - raw colors
<div className="bg-zinc-950 text-zinc-100"># Frontend typecheck
pnpm lint
# Swift CLI
cd nocur-swift && swift test
# Rust (if applicable)
cd src-tauri && cargo test- Run
pnpm tauri dev - Open an iOS project or use
sample-app/ - Test the feature you're working on
- Verify Claude can use any new/modified tools
Use clear, descriptive commit messages:
Add feature: brief description
- Detail about what was added
- Why it was needed
- Any caveats or notes
Prefixes:
Add:New featureFix:Bug fixUpdate:Enhancement to existing featureRemove:Removing code/featuresRefactor:Code restructuringDocs:Documentation only
- All PRs require at least one review
- Address all review comments
- Keep PRs focused and reasonably sized
- Update documentation if needed
- Open an issue for questions about the codebase
- Check existing issues and discussions first
Thank you for contributing!