- README: forum section with curl examples + nav link - CHANGELOG: v1.2.0 entry with forum features - CONTRIBUTING: forum link alongside Discord Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.3 KiB
Contributing to Clodds
Thanks for your interest in contributing! Clodds is open-source and welcomes contributions.
Getting Started
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/clodds cd clodds - Install dependencies:
npm install - Create a branch:
git checkout -b feature/my-feature
Development
# Run in dev mode (hot reload)
npm run dev
# Type check
npm run typecheck
# Build
npm run build
Project Structure
src/
├── index.ts # Entry point
├── types.ts # TypeScript types
├── gateway/ # WebSocket server
├── channels/ # Telegram, Discord adapters
├── feeds/ # Market data (Polymarket, Kalshi, etc.)
├── agents/ # Claude AI integration
├── skills/ # Agent skills (SKILL.md)
├── sessions/ # Per-user state
├── cron/ # Scheduled tasks
├── db/ # SQLite persistence
└── cli/ # CLI commands
Adding a New Market Feed
- Create
src/feeds/your-platform/index.ts - Implement the feed interface:
export interface YourPlatformFeed extends EventEmitter { start(): Promise<void>; stop(): void; searchMarkets(query: string): Promise<Market[]>; getMarket(id: string): Promise<Market | null>; } - Register in
src/feeds/index.ts - Add to types in
src/types.ts
Adding a New Channel
- Create
src/channels/your-channel/index.ts - Implement message handling and sending
- Register in
src/channels/index.ts
Adding a New Skill
CLI Skill Handler (required)
- Create
src/skills/bundled/your-skill/index.tswith a default export:export default { name: 'your-skill', description: 'What this skill does', commands: ['/your-skill'], // Optional: declare env vars needed before handler runs requires: { env: ['API_KEY'] }, handle: async (args: string): Promise<string> => { // ... }, }; - Add the directory name to
SKILL_MANIFESTinsrc/skills/executor.ts(alphabetical order) - Add the skill name to
COMMAND_CATEGORIESinsrc/commands/registry.tswith its category (e.g.'your-skill': 'Tools') - Run
npm run typecheckto verify
Skills are lazy-loaded via await import() on first use. Each skill loads in its own try/catch, so a missing dependency only disables that one skill. If requires.env is set, the executor checks those vars before calling the handler and returns a clear message if any are missing.
Agent Context (optional)
To also give the AI agent context about your skill, create src/skills/bundled/your-skill/SKILL.md with YAML frontmatter:
---
name: your-skill
description: "What this skill does"
---
# Your Skill
Instructions for the AI...
Pull Request Guidelines
- Keep changes focused and atomic
- Update types when needed
- Add comments for complex logic
- Test manually before submitting
- Describe what changed and why
Code Style
- Use TypeScript strict mode
- Prefer
async/awaitover callbacks - Use descriptive variable names
- Keep functions small and focused
Security Guidelines
When contributing code that involves command execution:
-
Never use string interpolation with
execSync():// BAD - vulnerable to command injection execSync(`which ${cmd}`); // GOOD - safe with array arguments execFileSync('which', [cmd]); -
Use
execFileSyncwith array arguments for all shell commands -
Validate and sanitize user-provided paths and inputs
-
Report vulnerabilities via GitHub Security Advisories, not public issues
-
Run security checks before submitting:
npm audit npm run typecheck
See docs/SECURITY_AUDIT.md for our security practices.
Reporting Issues
Please include:
- Node.js version
- Steps to reproduce
- Expected vs actual behavior
- Error messages/logs
Questions?
Open an issue, join our Discord, or visit the Agent Forum where AI agents discuss strategies and features.
License
By contributing, you agree that your contributions will be licensed under MIT.