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
80 changes: 77 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,27 @@ curl -X POST http://localhost:8072/batch/lint \

### Production (Pre-built Images)

See `atomic-pumpkin-deploy` for production deployment using GHCR images.
```bash
# Pull pre-built images from GitHub Container Registry
docker pull ghcr.io/real-wimpsquad/code-thumbs:latest
docker pull ghcr.io/real-wimpsquad/code-thumbs-api:latest

# Run with docker-compose
docker-compose up -d

# Or run directly
docker run -d --name code-thumbs \
-v $(pwd):/workspace \
ghcr.io/real-wimpsquad/code-thumbs:latest \
tail -f /dev/null

docker run -d --name code-thumbs-api \
-p 8072:8072 \
-v $(pwd):/workspace \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CODE_THUMBS_CONTAINER=code-thumbs \
ghcr.io/real-wimpsquad/code-thumbs-api:latest
```

## API Endpoints

Expand Down Expand Up @@ -94,8 +114,9 @@ Batch response format: `path1|result1\n---\npath2|result2`

- `GET /` - API overview
- `GET /health` - Health check (includes tool availability)
- `GET /languages` - List supported languages and tools
- `GET /tools/openai` - OpenAI function schemas (structured format)
- `GET /languages` - List supported languages and tools (verbose JSON)
- `GET /tools` - **Compressed tool specs (ml-exclusive format for agents)**
- `GET /tools/openai` - OpenAI function schemas (verbose JSON for OpenAI integration)

## ML-Exclusive Response Format

Expand Down Expand Up @@ -170,6 +191,35 @@ err:timeout|code:504|msg:tool_execution_timed_out

All responses (success + error) use compressed format with `{"result": "..."}` wrapper.

## Agent Tool Discovery

**For AI agents:** Use `GET /tools` endpoint for compressed tool specification:

```bash
curl http://localhost:8072/tools
```

Returns ml-exclusive compressed format:
```json
{
"system": "code_thumbs",
"endpoints": {
"file_ops": "POST/format/file{path,lang?,tool?}→read+fmt+write|...",
"content_ops": "POST/format{lang,content,tool?,check_only?}→fmt|...",
"batch_file": "POST/batch/format/files{paths[],lang?,tool?}→multi_fmt|...",
"meta": "GET/health→status|GET/languages→17lang_list|..."
},
"languages": "py→ruff,black,pylint,mypy|js/ts→prettier,eslint,tsc|...",
"philosophy": "agent_first→prefer_file_ops_over_content→atomic_operations→...",
"usage": {
"recommended": "POST/format/file{path}→1_call_atomic",
"legacy": "Read→POST/format{content}→parse→Write→5_steps_avoid"
}
}
```

**Philosophy:** LLM-first design → semantic density → compressed syntax → direct file operations

## MCP Server

Located in `mcp-server/mcp_server_code_thumbs.py`. Example configuration (Claude Desktop):
Expand Down Expand Up @@ -209,6 +259,30 @@ Client → API (port 8072) → Docker exec → code-thumbs container (tools)
- `/health` endpoint shows tool availability status
- 30s timeout per operation to prevent hangs

## Integration

### Atomic Pumpkin (Optional)

Code Thumbs can be used as an addon with [Atomic Pumpkin](https://github.com/real-wimpsquad/atomic-pumpkin):

```bash
make dev ADDONS="code-thumbs"
```

This mounts the atomic-pumpkin workspace at `/workspace` for formatting/linting project files.

### Standalone

Code Thumbs works independently - just mount your project directory to `/workspace`:

```bash
docker run -d --name code-thumbs-api \
-p 8072:8072 \
-v /path/to/your/project:/workspace \
-v /var/run/docker.sock:/var/run/docker.sock \
ghcr.io/real-wimpsquad/code-thumbs-api:latest
```

## License

MIT - See LICENSE file
32 changes: 31 additions & 1 deletion src/api_code_thumbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,7 @@ async def root():
"version": "1.0.0",
"endpoints": {
"GET /languages": "List supported languages and tools",
"GET /tools": "Compressed tool specs (ml-exclusive format)",
"POST /format": "Format code (content)",
"POST /lint": "Lint code (content)",
"POST /fix": "Auto-fix issues (content)",
Expand All @@ -624,7 +625,7 @@ async def root():
"POST /batch/format/files": "Format multiple files by path",
"POST /batch/lint/files": "Lint multiple files by path",
"POST /batch/fix/files": "Fix multiple files by path",
"GET /tools/openai": "OpenAI function schemas",
"GET /tools/openai": "OpenAI function schemas (verbose)",
"GET /docs": "Interactive API docs (Swagger)",
"GET /redoc": "API documentation (ReDoc)",
},
Expand Down Expand Up @@ -700,6 +701,35 @@ async def list_languages():
}


@app.get("/tools")
async def agent_tools():
"""Agent-discoverable tools in compressed ml-exclusive format"""
return {
"system": "code_thumbs",
"version": "1.0.0",
"compressed": "ml_exclusive_format→max_semantic_density",
"endpoints": {
"file_ops": "POST/format/file{path,lang?,tool?}→read+fmt+write|POST/lint/file{path,lang?,tool?}→read+lint+report|POST/fix/file{path,lang?,tool?}→read+fix+write|POST/check/file{path,lang?,tool?}→read+check+report",
"content_ops": "POST/format{lang,content,tool?,check_only?}→fmt|POST/lint{lang,content,tool?}→issues|POST/fix{lang,content,tool?}→fixed|POST/check{lang,content}→fmt+lint",
"batch_file": "POST/batch/format/files{paths[],lang?,tool?}→multi_fmt|POST/batch/lint/files{paths[],lang?,tool?}→multi_lint|POST/batch/fix/files{paths[],lang?,tool?}→multi_fix",
"batch_content": "POST/batch/format{lang,files:[{path,content}],tool?}→multi_fmt|POST/batch/lint{lang,files:[{path,content}],tool?}→multi_lint|POST/batch/fix{lang,files:[{path,content}],tool?}→multi_fix",
"meta": "GET/health→status|GET/languages→17lang_list|GET/tools→this|GET/tools/openai→verbose_schemas",
},
"languages": "py→ruff,black,pylint,mypy|js/ts→prettier,eslint,tsc|go→gofmt,goimports,golangci-lint|rust→rustfmt,clippy|c/cpp→clang-format,clang-tidy|cs→csharpier,dotnet-format|java→google-java-format,checkstyle|kt→ktlint|swift→swiftformat|php→php-cs-fixer,phpstan|rb→rubocop|sh→shfmt,shellcheck|sql→sqlfluff|md→prettier,markdownlint|yaml→prettier,yamllint",
"response_format": "compressed→tool:ruff|changed:yes\\n\\n{code}|errors→err:type|code:NNN|msg:compressed",
"workspace": "/workspace→mounted_project_root",
"lang_detection": "auto_via_extension→.py=python,.ts=typescript,.go=go",
"philosophy": "agent_first→prefer_file_ops_over_content→atomic_operations→auto_detect_lang→compressed_responses",
"usage": {
"recommended": "POST/format/file{path}→1_call_atomic",
"legacy": "Read→POST/format{content}→parse→Write→5_steps_avoid",
"batch": "POST/batch/format/files{paths[]}→efficient_multi",
},
"health": "GET/health→{status,container,tools:{ruff:available,...}}",
"tools_available": "17lang|35+tools|format+lint+fix→see_GET/languages_for_detail",
}


@app.post("/format")
async def format_code(req: FormatRequest):
"""Format code using specified or default formatter"""
Expand Down
Loading