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
13 changes: 9 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ The CLI provides Julia installation and execution with JuliaHub configuration:
- Installs latest stable Julia version

### Julia Credentials
- **Authentication file**: Automatically creates `~/.julia/servers/<server>/auth.toml`
- **Authentication file**: Automatically creates `$JULIA_DEPOT_PATH/servers/<server>/auth.toml` (or `~/.julia/servers/<server>/auth.toml` if `JULIA_DEPOT_PATH` is not set)
- **Depot path detection**: Respects `JULIA_DEPOT_PATH` environment variable, uses first path if multiple are specified
- **Atomic writes**: Uses temporary file + rename for safe credential updates
- **Automatic updates**: Credentials are automatically refreshed when:
- User runs `jh auth login`
Expand Down Expand Up @@ -252,7 +253,7 @@ jh run -- --project=. --threads=4 script.jl # Run with flags
```bash
jh run setup
```
- Creates/updates `~/.julia/servers/<server>/auth.toml` with current credentials
- Creates/updates `$JULIA_DEPOT_PATH/servers/<server>/auth.toml` with current credentials (or `~/.julia/servers/<server>/auth.toml` if not set)
- Does not start Julia
- Useful for explicitly updating credentials

Expand All @@ -265,6 +266,7 @@ jh run setup
- File uploads use multipart form data with proper content types
- Julia auth files use TOML format with `preferred_username` from JWT claims
- Julia auth files use atomic writes (temp file + rename) to prevent corruption
- Julia credentials respect `JULIA_DEPOT_PATH` environment variable (uses first path if multiple are specified)
- Julia credentials are automatically updated after login and token refresh
- Git commands use `http.extraHeader` for authentication and pass through all arguments
- Git credential helper provides seamless authentication for standard Git commands
Expand All @@ -281,7 +283,9 @@ jh run setup
The Julia credentials system consists of three main functions:

1. **`createJuliaAuthFile(server, token)`**:
- Creates `~/.julia/servers/<server>/auth.toml` with TOML-formatted credentials
- Determines depot path from `JULIA_DEPOT_PATH` environment variable (uses first path if multiple)
- Falls back to `~/.julia` if `JULIA_DEPOT_PATH` is not set
- Creates `{depot}/servers/<server>/auth.toml` with TOML-formatted credentials
- Uses atomic writes: writes to temporary file, syncs, then renames
- Includes all necessary fields: tokens, expiration, refresh URL, user info
- Called by `setupJuliaCredentials()` and `updateJuliaCredentialsIfNeeded()`
Expand All @@ -306,7 +310,8 @@ The Julia credentials system consists of three main functions:

The `updateJuliaCredentialsIfNeeded(server, token)` function:
- Called automatically by `ensureValidToken()` after token refresh
- Checks if `~/.julia/servers/<server>/auth.toml` exists
- Determines depot path from `JULIA_DEPOT_PATH` (same logic as `createJuliaAuthFile`)
- Checks if `{depot}/servers/<server>/auth.toml` exists
- If exists, updates it with refreshed token
- If not exists, does nothing (user hasn't used Julia integration yet)
- Errors are silently ignored to avoid breaking token operations
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ jh run -- --project=. --threads=4 script.jl
```

Note: Arguments after `--` are passed directly to Julia. The `jh run` command:
1. Sets up JuliaHub credentials in `~/.julia/servers/<server>/auth.toml`
1. Sets up JuliaHub credentials in `$JULIA_DEPOT_PATH/servers/<server>/auth.toml` (or `~/.julia/servers/<server>/auth.toml` if `JULIA_DEPOT_PATH` is not set)
2. Configures `JULIA_PKG_SERVER` environment variable
3. Starts Julia with your specified arguments

Expand Down
5 changes: 3 additions & 2 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,14 @@ func ensureValidToken() (*StoredToken, error) {
// updateJuliaCredentialsIfNeeded updates Julia credentials if the auth file exists
// This is called after token refresh to keep credentials in sync
func updateJuliaCredentialsIfNeeded(server string, token *StoredToken) error {
homeDir, err := os.UserHomeDir()
// Determine Julia depot path
Copy link
Member

@vdayanand vdayanand Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe its simpler rely on Base.DEPOT_PATH?. Oops, Didnt realize this was go

depotPath, err := getJuliaDepotPath()
if err != nil {
return err
}

// Check if the auth.toml file exists
authFilePath := filepath.Join(homeDir, ".julia", "servers", server, "auth.toml")
authFilePath := filepath.Join(depotPath, "servers", server, "auth.toml")
if _, err := os.Stat(authFilePath); os.IsNotExist(err) {
// File doesn't exist, so user hasn't used Julia integration yet
return nil
Expand Down
31 changes: 26 additions & 5 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,36 @@ import (
"path/filepath"
)

func getJuliaDepotPath() (string, error) {
var depotPath string
if juliaDepot := os.Getenv("JULIA_DEPOT_PATH"); juliaDepot != "" {
// Use first path from JULIA_DEPOT_PATH (paths are separated by : on Unix, ; on Windows)
depotPaths := filepath.SplitList(juliaDepot)
if len(depotPaths) > 0 {
depotPath = depotPaths[0]
}
}

// Fall back to ~/.julia if JULIA_DEPOT_PATH is not set
if depotPath == "" {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("failed to get user home directory: %w", err)
}
depotPath = filepath.Join(homeDir, ".julia")
}

return depotPath, nil
}

func createJuliaAuthFile(server string, token *StoredToken) error {
// Get user home directory
homeDir, err := os.UserHomeDir()
depotPath, err := getJuliaDepotPath()
if err != nil {
return fmt.Errorf("failed to get user home directory: %w", err)
return err
}

// Create ~/.julia/servers/{server}/ directory
serverDir := filepath.Join(homeDir, ".julia", "servers", server)
// Create {depot}/servers/{server}/ directory
serverDir := filepath.Join(depotPath, "servers", server)
if err := os.MkdirAll(serverDir, 0755); err != nil {
return fmt.Errorf("failed to create server directory: %w", err)
}
Expand Down