|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a Go-based CLI tool for interacting with JuliaHub, a platform for Julia computing. The CLI provides commands for authentication, dataset management, project management, user information, Git integration, and Julia integration. |
| 8 | + |
| 9 | +## Architecture |
| 10 | + |
| 11 | +The application follows a command-line interface pattern using the Cobra library with a modular file structure: |
| 12 | + |
| 13 | +- **main.go**: Core CLI structure with command definitions and configuration management |
| 14 | +- **auth.go**: OAuth2 device flow authentication with JWT token handling |
| 15 | +- **datasets.go**: Dataset operations (list, download, upload, status) with REST API integration |
| 16 | +- **projects.go**: Project management using GraphQL API with user filtering |
| 17 | +- **user.go**: User information retrieval using GraphQL API |
| 18 | +- **git.go**: Git integration (clone, push, fetch, pull) with JuliaHub authentication |
| 19 | +- **julia.go**: Julia installation and management |
| 20 | +- **run.go**: Julia execution with JuliaHub configuration |
| 21 | +- **Configuration**: Uses `~/.juliahub` file for server and token storage |
| 22 | + |
| 23 | +### Key Components |
| 24 | + |
| 25 | +1. **Authentication System** (`auth.go`): |
| 26 | + - Implements OAuth2 device flow for JuliaHub authentication |
| 27 | + - JWT token parsing and validation with automatic refresh |
| 28 | + - Supports multiple server environments (juliahub.com, custom servers) |
| 29 | + - Stores tokens securely in `~/.juliahub` with 0600 permissions |
| 30 | + |
| 31 | +2. **API Integration**: |
| 32 | + - **REST API**: Used for dataset operations (`/api/v1/datasets`, `/datasets/{uuid}/url/{version}`) |
| 33 | + - **GraphQL API**: Used for projects and user info (`/v1/graphql`) |
| 34 | + - **Headers**: All GraphQL requests require `X-Hasura-Role: jhuser` header |
| 35 | + - **Authentication**: Uses ID tokens (`token.IDToken`) for API calls |
| 36 | + |
| 37 | +3. **Command Structure**: |
| 38 | + - `jh auth`: Authentication commands (login, refresh, status, env) |
| 39 | + - `jh dataset`: Dataset operations (list, download, upload, status) |
| 40 | + - `jh project`: Project management (list with GraphQL, supports user filtering) |
| 41 | + - `jh user`: User information (info with GraphQL) |
| 42 | + - `jh clone`: Git clone with JuliaHub authentication and project name resolution |
| 43 | + - `jh push/fetch/pull`: Git operations with JuliaHub authentication |
| 44 | + - `jh git-credential`: Git credential helper for seamless authentication |
| 45 | + - `jh julia`: Julia installation management |
| 46 | + - `jh run`: Julia execution with JuliaHub configuration |
| 47 | + |
| 48 | +4. **Data Models**: |
| 49 | + - UUID strings for most entity IDs (projects, datasets, resources) |
| 50 | + - Integer IDs for user-related entities |
| 51 | + - Custom JSON unmarshaling for flexible date parsing (`CustomTime`) |
| 52 | + - GraphQL request/response structures with proper operation names |
| 53 | + |
| 54 | +## Development Commands |
| 55 | + |
| 56 | +### Build and Run |
| 57 | +```bash |
| 58 | +go build -o jh |
| 59 | +./jh --help |
| 60 | +``` |
| 61 | + |
| 62 | +### Run directly |
| 63 | +```bash |
| 64 | +go run . --help |
| 65 | +``` |
| 66 | + |
| 67 | +### Code quality checks (always run before commits) |
| 68 | +```bash |
| 69 | +go fmt ./... |
| 70 | +go vet ./... |
| 71 | +go build |
| 72 | +``` |
| 73 | + |
| 74 | +### Test authentication flow |
| 75 | +```bash |
| 76 | +go run . auth login -s juliahub.com |
| 77 | +``` |
| 78 | + |
| 79 | +### Test dataset operations |
| 80 | +```bash |
| 81 | +go run . dataset list |
| 82 | +go run . dataset download <dataset-name> |
| 83 | +go run . dataset upload --new ./file.tar.gz |
| 84 | +``` |
| 85 | + |
| 86 | +### Test project and user operations |
| 87 | +```bash |
| 88 | +go run . project list |
| 89 | +go run . project list --user |
| 90 | +go run . project list --user john |
| 91 | +go run . user info |
| 92 | +``` |
| 93 | + |
| 94 | +### Test Git operations |
| 95 | +```bash |
| 96 | +go run . clone john/my-project |
| 97 | +go run . push |
| 98 | +go run . fetch |
| 99 | +go run . pull |
| 100 | +``` |
| 101 | + |
| 102 | +### Test Git credential helper |
| 103 | +```bash |
| 104 | +# Setup credential helper (one-time setup) |
| 105 | +go run . git-credential setup |
| 106 | + |
| 107 | +# Test credential helper manually |
| 108 | +echo -e "protocol=https\nhost=juliahub.com\npath=git/projects/test/test\n" | go run . git-credential get |
| 109 | + |
| 110 | +# After setup, standard Git commands work seamlessly |
| 111 | +git clone https://juliahub.com/git/projects/username/project.git |
| 112 | +``` |
| 113 | + |
| 114 | +## Dependencies |
| 115 | + |
| 116 | +- `github.com/spf13/cobra`: CLI framework |
| 117 | +- Standard library packages for HTTP, JSON, file I/O, multipart uploads |
| 118 | + |
| 119 | +## Server Configuration |
| 120 | + |
| 121 | +The CLI supports multiple JuliaHub environments: |
| 122 | +- Default: `juliahub.com` (uses `auth.juliahub.com` for auth) |
| 123 | +- Custom servers: Direct server specification |
| 124 | +- Server normalization: Automatically appends `.juliahub.com` to short names |
| 125 | + |
| 126 | +## Authentication Flow |
| 127 | + |
| 128 | +The application uses OAuth2 device flow: |
| 129 | +1. Request device code from `/dex/device/code` |
| 130 | +2. Present verification URL to user |
| 131 | +3. Poll `/dex/token` endpoint until authorization complete |
| 132 | +4. Store tokens in configuration file with JWT claims extraction |
| 133 | + |
| 134 | +## API Patterns |
| 135 | + |
| 136 | +### GraphQL Integration |
| 137 | +- **Endpoint**: `https://server/v1/graphql` |
| 138 | +- **Required headers**: `Authorization: Bearer <id_token>`, `X-Hasura-Role: jhuser` |
| 139 | +- **Request structure**: `{operationName: "...", query: "...", variables: {...}}` |
| 140 | +- **User ID retrieval**: Projects use actual user ID from `getUserInfo()` call |
| 141 | + |
| 142 | +### REST API Integration |
| 143 | +- **Dataset operations**: Use presigned URLs for upload/download |
| 144 | +- **Authentication**: Bearer token with ID token |
| 145 | +- **Upload workflow**: 3-step process (request presigned URL, upload to URL, close upload) |
| 146 | + |
| 147 | +### Data Type Handling |
| 148 | +- Project/dataset IDs are UUID strings, not integers |
| 149 | +- User IDs are integers |
| 150 | +- Custom time parsing handles multiple date formats |
| 151 | +- Flexible dataset identifier resolution (UUID, name, user/name) |
| 152 | + |
| 153 | +## Git Integration |
| 154 | + |
| 155 | +The CLI provides seamless Git integration with JuliaHub authentication through two approaches: |
| 156 | + |
| 157 | +### Method 1: JuliaHub CLI Wrapper Commands |
| 158 | +- **Clone**: `jh clone username/project` - resolves project names to UUIDs and clones with authentication |
| 159 | +- **Push/Fetch/Pull**: `jh push/fetch/pull [args...]` - wraps Git commands with authentication headers |
| 160 | +- **Authentication**: Uses `http.extraHeader="Authorization: Bearer <id_token>"` for Git operations |
| 161 | +- **Argument passthrough**: All Git arguments are passed through to underlying commands |
| 162 | +- **Folder naming**: Clone automatically renames UUID folders to project names |
| 163 | +- **Conflict resolution**: Handles folder naming conflicts with automatic numbering |
| 164 | + |
| 165 | +### Method 2: Git Credential Helper (Recommended) |
| 166 | +- **Setup**: `jh git-credential setup` - configures Git to use JuliaHub CLI as credential helper |
| 167 | +- **Multi-server support**: Automatically handles different JuliaHub instances |
| 168 | +- **Automatic authentication**: Prompts for authentication when server doesn't match stored config |
| 169 | +- **Standard Git commands**: Use `git clone`, `git push`, `git pull`, etc. directly without `jh` wrapper |
| 170 | +- **Non-intrusive**: Only handles JuliaHub URLs, other URLs passed to other credential helpers |
| 171 | +- **Protocol compliance**: Follows Git credential helper protocol with `get`, `store`, `erase` actions |
| 172 | + |
| 173 | +#### Git Credential Helper Usage: |
| 174 | +```bash |
| 175 | +# One-time setup |
| 176 | +jh git-credential setup |
| 177 | + |
| 178 | +# Then use standard Git commands |
| 179 | +git clone https://juliahub.com/git/projects/username/project.git |
| 180 | +git push origin main |
| 181 | +git pull origin main |
| 182 | + |
| 183 | +# Works with multiple JuliaHub servers automatically |
| 184 | +git clone https://internal.juliahub.com/git/projects/user/repo.git # Auto-prompts for auth |
| 185 | +git clone https://custom.juliahub.com/git/projects/user/repo.git # Auto-prompts for auth |
| 186 | +git clone https://github.com/user/repo.git # Ignored by helper |
| 187 | +``` |
| 188 | + |
| 189 | +#### Git Credential Helper Implementation: |
| 190 | +- **Domain detection**: Recognizes `*.juliahub.com` and configured custom servers |
| 191 | +- **Server matching**: Compares requested host against `~/.juliahub` server field |
| 192 | +- **Automatic login**: Runs OAuth2 device flow when server mismatch detected |
| 193 | +- **Token management**: Stores and refreshes tokens per server automatically |
| 194 | +- **Error handling**: Graceful fallback to other credential helpers for non-JuliaHub URLs |
| 195 | + |
| 196 | +## Julia Integration |
| 197 | + |
| 198 | +The CLI provides Julia installation and execution with JuliaHub configuration: |
| 199 | +- Cross-platform installation (Windows via winget, Unix via official installer) |
| 200 | +- Authentication file creation (`~/.julia/servers/<server>/auth.toml`) |
| 201 | +- Package server configuration (`JULIA_PKG_SERVER`) |
| 202 | +- Project activation (`--project=.`) |
| 203 | + |
| 204 | +## Development Notes |
| 205 | + |
| 206 | +- All ID fields in GraphQL responses should be typed correctly (string for UUIDs, int64 for user IDs) |
| 207 | +- GraphQL queries are embedded as strings (consider external .gql files for complex queries) |
| 208 | +- Error handling includes both HTTP and GraphQL error responses |
| 209 | +- Token refresh is automatic via `ensureValidToken()` |
| 210 | +- File uploads use multipart form data with proper content types |
| 211 | +- Julia auth files use TOML format with `preferred_username` from JWT claims |
| 212 | +- Git commands use `http.extraHeader` for authentication and pass through all arguments |
| 213 | +- Git credential helper provides seamless authentication for standard Git commands |
| 214 | +- Multi-server authentication handled automatically via credential helper |
| 215 | +- Project filtering supports `--user` parameter for showing specific user's projects or own projects |
| 216 | +- Clone command automatically resolves `username/project` format to project UUIDs |
| 217 | +- Folder naming conflicts are resolved with automatic numbering (project-1, project-2, etc.) |
| 218 | +- Credential helper follows Git protocol: responds only to JuliaHub URLs, ignores others |
0 commit comments