Skip to contents

claudeplot brings the visual language of Anthropic and Claude to ggplot2: a publication-ready theme, color palettes from Anthropic’s brand and its data-visualization style, color/fill scales, and palette helpers.

The theme

theme_claude() gives a light background, light horizontal grid lines, strong axis lines, a bold Poppins title, and a serif Lora subtitle.

ggplot(mtcars, aes(wt, mpg, color = factor(cyl))) +
  geom_point(size = 3) +
  scale_color_claude_d() +
  labs(
    title = "Fuel efficiency by weight",
    subtitle = "Heavier cars travel fewer miles per gallon",
    x = "Weight (1000 lbs)", y = "Miles per gallon", color = "Cylinders"
  ) +
  theme_claude()
#> Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): Unable to load
#> font: Lora
#> Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): Unable to load
#> font: Lora
#> Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora

You can control the grid ("y", "x", "xy", "none"), toggle the axis lines, and switch to Anthropic’s warm off-white background:

ggplot(mpg, aes(displ, hwy)) +
  geom_point(color = claude_colors[["viz_blue"]]) +
  labs(title = "Engine size vs. highway mileage") +
  theme_claude(grid = "xy", background = "cloud")

Color scales

Every scale comes in discrete (_d) and continuous (_c) forms, for both color/colour and fill.

df <- data.frame(
  model = c("Opus 4.6", "Opus 4.7", "Opus 4.8", "Fable 5"),
  score = c(58.6, 69.2, 80.3, 88.4)
)

ggplot(df, aes(model, score, fill = model)) +
  geom_col(width = 0.7) +
  geom_text(aes(label = score), vjust = -0.5, fontface = "bold") +
  scale_fill_claude_d() +
  scale_y_continuous(limits = c(0, 100), expand = expansion(mult = c(0, 0.05))) +
  labs(title = "Agentic coding", subtitle = "SWE-Bench Pro (%)", x = NULL, y = NULL) +
  theme_claude() +
  theme(legend.position = "none")
#> Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora

Rounded bars

Anthropic’s benchmark charts often use bars with softly rounded tops. The ggrounded package pairs nicely with claudeplot: swap geom_col() for geom_col_rounded() for the same look.

library(ggrounded)

ggplot(df, aes(model, score, fill = model)) +
  geom_col_rounded(width = 0.7, radius = 0.3) +
  geom_text(aes(label = score), vjust = -0.5, fontface = "bold") +
  scale_fill_claude_d() +
  scale_y_continuous(limits = c(0, 100), expand = expansion(mult = c(0, 0.05))) +
  labs(title = "Agentic coding", subtitle = "SWE-Bench Pro (%)", x = NULL, y = NULL) +
  theme_claude() +
  theme(legend.position = "none")
#> Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora
#> Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
#> Unable to load font: Lora

Continuous scales interpolate the sequential and diverging palettes:

ggplot(faithfuld, aes(waiting, eruptions, fill = density)) +
  geom_raster() +
  scale_fill_claude_c(palette = "oranges") +
  labs(title = "Old Faithful eruptions") +
  theme_claude(grid = "none")

Palettes

List the palettes, draw one, or draw them all:

claude_palette_names()
#>  [1] "claude"       "brand"        "warm"         "cool"         "neutral"     
#>  [6] "oranges"      "blues"        "greens"       "grays"        "orange_blue" 
#> [11] "green_orange" "spectral"
show_claude_palette("spectral", n = 9, type = "continuous")

The qualitative families are claude (the vivid benchmark palette), brand (muted Anthropic accents), warm, cool, and neutral. Sequential families are oranges, blues, greens, and grays; diverging families are orange_blue, green_orange, and spectral.

Fonts

claudeplot bundles Poppins and Lora and registers them with systemfonts on load. They render on ragg and svglite devices; check availability with:

claude_font_status()
#> 
#> ── claudeplot font status ──────────────────────────────────────────────────────
#>  Poppins (headings): available
#>  Lora (body/subtitle): available
#>  systemfonts: installed
#>  ragg: installed
#>  `theme_claude()` will use Poppins and Lora automatically.

If a font is unavailable, theme_claude() falls back to generic "sans" and "serif" families, so plots always render.