From 2669058d78acae638df8d5ae2449fdcd16bd44c2 Mon Sep 17 00:00:00 2001 From: dawid-ai Date: Mon, 20 Jul 2026 15:16:35 +0700 Subject: [PATCH] docs: agent-optimize README + add AGENTS.md/CLAUDE.md and IDE pointer files Add agent-facing docs so AI coding agents and LLMs can discover the gem, know when to use it vs sibling packages, and use it correctly. Docs only, no source/dependency/build changes; examples verified against current source. - README.md: lean quickstart shape in Cloudinary's SDK docs voice - AGENTS.md: build/test/lint commands, entry points, conventions, gotchas - CLAUDE.md: thin @AGENTS.md pointer - .github/copilot-instructions.md + .cursor/rules/cloudinary.mdc: pointers to AGENTS.md --- .cursor/rules/cloudinary.mdc | 8 ++ .github/copilot-instructions.md | 5 + AGENTS.md | 63 ++++++++++++ CLAUDE.md | 29 ++++++ README.md | 167 ++++++++++++++------------------ 5 files changed, 180 insertions(+), 92 deletions(-) create mode 100644 .cursor/rules/cloudinary.mdc create mode 100644 .github/copilot-instructions.md create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/.cursor/rules/cloudinary.mdc b/.cursor/rules/cloudinary.mdc new file mode 100644 index 00000000..f3218080 --- /dev/null +++ b/.cursor/rules/cloudinary.mdc @@ -0,0 +1,8 @@ +--- +description: Cloudinary cloudinary_gem — agent guide +alwaysApply: true +--- + +Read and follow `AGENTS.md` in the repository root. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..efced1c3 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,5 @@ +# Cloudinary cloudinary_gem — instructions for AI coding agents + +Read `AGENTS.md` in the repository root and follow it. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..ed0e40f9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,63 @@ +# AGENTS.md — cloudinary_gem + +## What this package is (one line) +Official Cloudinary Ruby/Rails server SDK: upload assets, build transformation and delivery URLs/tags, call the Admin API, and wire Cloudinary into Active Storage or CarrierWave — all from a backend where the `api_secret` stays private. + +## When to use this / when NOT to use this +- **Use this when:** you are in a Ruby or Rails server runtime (Rails app, Sinatra service, background job, plain script) and need signed uploads, asset administration, view tags (`cl_image_tag`, `cl_video_tag`), or signed delivery URLs. +- **Do NOT use this when:** you need browser-side delivery URLs in a JS frontend — use [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen), which builds URLs without exposing a secret. For a no-code/autonomous agent path, use the [Cloudinary MCP server](https://github.com/cloudinary/mcp-servers). +- **Sibling packages:** `@cloudinary/url-gen` = browser URL builder; [`attachinary`](https://github.com/cloudinary/attachinary) = legacy Rails attachment gem (prefer Active Storage for new apps). Stay on this gem's `1.x` line only for Ruby 1.9.3/2.x. + +## Setup +```bash +gem install cloudinary # or add `gem "cloudinary"` to your Gemfile, then: bundle install +``` +Required configuration / credentials — the SDK reads `CLOUDINARY_URL` automatically: +```bash +export CLOUDINARY_URL=cloudinary://:@ +``` + +## Minimal runnable example +```ruby +require 'cloudinary' # CLOUDINARY_URL is picked up from the environment + +# Upload a local file from the server (uses the api_secret — server-side only) +result = Cloudinary::Uploader.upload("my_picture.jpg") +puts result["public_id"] + +# Build a 100x150 fill-crop delivery URL for an uploaded asset +puts Cloudinary::Utils.cloudinary_url("sample.jpg", width: 100, height: 150, crop: "fill") +``` +In Rails views, prefer the `cl_image_tag("sample.jpg", width: 100, height: 150, crop: "fill")` helper. + +## Build / test commands (run these after editing) +```bash +bundle install # install gem + dev dependencies +export CLOUDINARY_URL=cloudinary://:@ +bundle exec rspec --format documentation --color # full suite (exactly what CI runs) +bundle exec rspec -f d # shorthand the project's CONTRIBUTING uses +bundle exec rspec spec/uploader_spec.rb # a single spec file +``` +- No linter is configured (no `.rubocop.yml`, no rubocop in `cloudinary.gemspec`). Do not invent a `lint` task. +- `rake` / `rake spec` is the default Rake task and also runs the suite. `rake build` first runs `cloudinary:fetch_assets`. + +## Conventions & gotchas +- **The test suite hits the live Cloudinary API.** Specs require a real `CLOUDINARY_URL` and a network connection — they are not fully hermetic. Use a throwaway/test cloud; some specs create and delete real assets. `rspec-retry` is enabled for flaky network specs. +- **Code must work both with and without Rails.** Rails-specific code lives in `lib/cloudinary/helper.rb`, `engine.rb`, `railtie.rb`, and `lib/active_storage/service/cloudinary_service.rb`; core API code (`uploader.rb`, `api.rb`, `utils.rb`, `search.rb`) must load in plain Ruby too. +- Source lives under `lib/cloudinary/`; the version is in `lib/cloudinary/version.rb`. Bump it there, not in the gemspec. +- HTTP goes through Faraday (`faraday`, `faraday-multipart`, `faraday-follow_redirects`) — keep new request code on that stack. +- **Never expose `api_secret` to a browser.** Signed uploads and signed URLs are exactly why this gem is server-side; do not port that logic to a frontend bundle. +- **Supported versions (2.x):** Ruby `>= 3, < 5`; Rails 6/7/8. CI matrix runs Ruby 3.1.7, 3.2.9, 3.3.10, 3.4.8, and 4.0.0. + +## Canonical docs (leave the repo for depth) +- Ruby on Rails SDK guide: https://cloudinary.com/documentation/rails_integration +- Transformation & REST API reference: https://cloudinary.com/documentation/cloudinary_references +- MCP server (agent/no-code path): https://github.com/cloudinary/mcp-servers + +## Agent / MCP note +If this capability is also exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for code generation. See cloudinary/mcp-servers. + +## Commit / PR conventions +- Default branch is `master`; branch from it and open a PR against it (CI runs on pushes/PRs to `master`). +- Provide test code covering new behavior, and make sure it works **both with and without Rails** (per `CONTRIBUTING.md`). +- PR description must clearly state the bug/feature and reference the relevant issue number when applicable. The CI check "Ruby Test 💎" must pass across the Ruby matrix. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..26b1e505 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,29 @@ +@AGENTS.md + +# CLAUDE.md — cloudinary_gem + +## What this repo is + +The official Cloudinary Ruby/Rails server SDK (`cloudinary` gem): signed uploads, Admin/Search API, transformation URL generation, Rails view helpers (`cl_image_tag`, `cl_video_tag`), and Active Storage / CarrierWave integration — all on the server where the `api_secret` stays private. + +## Key constraints and gotchas + +- **Test suite hits the live API.** Specs require a real `CLOUDINARY_URL` and network access — not hermetic. Use a throwaway cloud; some specs create and delete real assets. `rspec-retry` is enabled for flaky network specs. +- **`CLOUDINARY_URL` vs discrete vars conflict.** If `CLOUDINARY_CLOUD_NAME` is present in the environment, the gem ignores `CLOUDINARY_URL` and reads the discrete `CLOUDINARY_*` vars instead. Pick one style — don't mix them. +- **Rails-only helpers.** `cl_image_tag` / `cl_video_tag` load via Railtie and are only available where Action View helpers are (controllers, views, helpers). In a plain Ruby script or background job, use `Cloudinary::Utils.cloudinary_url(…)` instead. +- **No linter configured.** No `.rubocop.yml`, no rubocop in the gemspec. Don't invent a `lint` task. +- **Default branch is `master`.** Branch from it; CI ("Ruby Test 💎") runs on pushes/PRs to `master` across the Ruby matrix (3.1, 3.2, 3.3, 3.4, 4.0). +- **HTTP stack is Faraday.** Keep new request code on `faraday` / `faraday-multipart` / `faraday-follow_redirects` — don't add a second HTTP client. +- **Version bump:** edit `lib/cloudinary/version.rb` — not the gemspec. +- **Supported versions (2.x):** Ruby `>= 3, < 5`; Rails 6/7/8. For Ruby 1.9.3/2.x, stay on the 1.x line. + +## Verified build and test commands + +```bash +bundle install # install gem + dev dependencies +export CLOUDINARY_URL=cloudinary://:@ +bundle exec rspec --format documentation --color # full suite (what CI runs) +bundle exec rspec -f d # shorthand the project uses +bundle exec rspec spec/uploader_spec.rb # single spec file +rake spec # equivalent via Rake +``` diff --git a/README.md b/README.md index d802d50e..91284803 100644 --- a/README.md +++ b/README.md @@ -1,129 +1,112 @@ -[![Build Status](https://app.travis-ci.com/cloudinary/cloudinary_gem.svg?branch=master)](https://app.travis-ci.com/github/cloudinary/cloudinary_gem) -[![Gem Version](https://badge.fury.io/rb/cloudinary.svg)](https://rubygems.org/gems/cloudinary) -[![Gem Version](https://badgen.net/rubygems/dt/cloudinary)](https://rubygems.org/gems/cloudinary) +# Cloudinary Ruby and Rails SDK -Cloudinary Ruby on Rails SDK -=================== +[![Gem Version](https://img.shields.io/gem/v/cloudinary.svg)](https://rubygems.org/gems/cloudinary) +[![license](https://img.shields.io/badge/license-MIT-green.svg)](https://rubygems.org/gems/cloudinary) +[![CI](https://github.com/cloudinary/cloudinary_gem/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/cloudinary/cloudinary_gem/actions/workflows/ci.yml) -## About +The `cloudinary` gem is the server-side Cloudinary SDK for Ruby and Rails. Use it in a Rails app, a Sinatra service, a background job, or a plain Ruby script to upload assets, build transformation and delivery URLs, render view tags, and call the Admin API. It holds the API secret, so it handles the operations that can't run in a browser: signed uploads, signed delivery URLs, and asset administration. The current release (2.4.5) requires Ruby 3.x or 4.x. -The Cloudinary Ruby on Rails SDK allows you to quickly and easily integrate your application with Cloudinary. -Effortlessly optimize, transform, upload and manage your cloud's assets. - -#### Note - -This Readme provides basic installation and usage information. For the complete documentation, see -the [Ruby on Rails SDK Guide](https://cloudinary.com/documentation/rails_integration). - -## Table of Contents - -- [Key Features](#key-features) -- [Version Support](#Version-Support) -- [Installation](#installation) -- [Usage](#usage) - - [Setup](#Setup) - - [Transform and Optimize Assets](#Transform-and-Optimize-Assets) - - [CarrierWave Integration](#CarrierWave-Integration) - - [Active Storage Integration](#Active-Storage-Integration) - -## Key Features - -- [Transform](https://cloudinary.com/documentation/rails_video_manipulation#video_transformation_examples) and - [optimize](https://cloudinary.com/documentation/rails_image_manipulation#image_optimizations) assets. -- Generate [image](https://cloudinary.com/documentation/rails_image_manipulation#deliver_and_transform_images) and - [video](https://cloudinary.com/documentation/rails_video_manipulation#rails_video_transformation_code_examples) tags. -- [Asset Management](https://cloudinary.com/documentation/rails_asset_administration). -- [Secure URLs](https://cloudinary.com/documentation/video_manipulation_and_delivery#generating_secure_https_urls_using_sdks) - . - -## Version Support +## Installation -| SDK Version | Ruby 1.9.3 | Ruby 2.x | Ruby 3.x | Ruby 4.x | -|-------------|------------|----------|----------|----------| -| 2.x | ✘ | ✘ | ✔ | ✔ | -| 1.x | ✔ | ✔ | ✔ | ✘ | +Add the gem to your `Gemfile`: -| SDK Version | Rails 5.x | Rails 6.x | Rails 7.x | Rails 8.x | -|-------------|-----------|-----------|-----------|-----------| -| 2.x | ✘ | ✔ | ✔ | ✔ | -| 1.x | ✔ | ✔ | ✔ | ✘ | +```ruby +gem "cloudinary" +``` -## Installation +Then run `bundle install`. To install it directly: ```bash gem install cloudinary ``` -# Usage +## Configuration -### Setup +The SDK reads credentials automatically from the `CLOUDINARY_URL` environment variable: -```ruby -require 'cloudinary' +```bash +export CLOUDINARY_URL=cloudinary://:@ ``` -### Transform and Optimize Assets -- [See full documentation](https://cloudinary.com/documentation/rails_image_manipulation). +To set them in code instead, call `Cloudinary.config`: ```ruby - cl_image_tag("sample.jpg", width: 100, height: 150, crop: "fill") +require "cloudinary" + +Cloudinary.config do |config| + config.cloud_name = "my_cloud_name" + config.api_key = "my_key" + config.api_secret = "my_secret" + config.secure = true +end ``` -### Upload -- [See full documentation](https://cloudinary.com/documentation/rails_image_and_video_upload). -- [Learn more about configuring your uploads with upload presets](https://cloudinary.com/documentation/upload_presets). +Keep the API secret on the server. Don't put it in client-side code or commit it to version control. + +## Quick examples + +### Upload a file with the Ruby SDK + +`Cloudinary::Uploader.upload` takes a local path, a remote URL, an IO or `File` object, or a data URI as its first argument. It's synchronous and returns a `Hash` of the parsed JSON response, including `public_id` and `secure_url`: ```ruby -Cloudinary::Uploader.upload("my_picture.jpg") +require "cloudinary" +# Credentials come from CLOUDINARY_URL in the environment. + +result = Cloudinary::Uploader.upload("my_picture.jpg", + public_id: "cms/hero") # optional: where the asset lives in your media library +puts result["public_id"] +puts result["secure_url"] ``` -### CarrierWave Integration -- [See full documentation](https://cloudinary.com/documentation/rails_carrierwave). +### Transform and optimize a delivery URL + +`Cloudinary::Utils.cloudinary_url` is synchronous and returns a string — no network call. This one resizes to a 100x150 fill crop and lets Cloudinary pick the format and quality for the requesting browser (`f_auto`, `q_auto`): -### Active Storage Integration -- [See full documentation](https://cloudinary.com/documentation/rails_activestorage). +```ruby +require "cloudinary" + +url = Cloudinary::Utils.cloudinary_url("sample.jpg", + width: 100, height: 150, crop: "fill", + fetch_format: :auto, quality: :auto) +# https://res.cloudinary.com/demo/image/upload/c_fill,f_auto,h_150,q_auto,w_100/sample.jpg +``` -### Security options -- [See full documentation](https://cloudinary.com/documentation/solution_overview#security). +In a Rails view, the `cl_image_tag` helper renders a full `` tag with the same options: -### Samples - - See [samples folder](https://github.com/cloudinary/cloudinary_gem/tree/master/samples). +```erb +<%= cl_image_tag("sample.jpg", width: 100, height: 150, crop: "fill", fetch_format: :auto, quality: :auto) %> +``` -## Contributions - - See [CONTRIBUTING](CONTRIBUTING.md). +### Retrieve asset details -## Get Help +`Cloudinary::Api.resource` takes a public ID and returns the asset's metadata as a `Hash`, including its dimensions, format, and `secure_url`: -If you run into an issue or have a question, you can either: +```ruby +require "cloudinary" +# Credentials come from CLOUDINARY_URL in the environment. -- Issues related to the SDK: [Open a GitHub issue](https://github.com/cloudinary/cloudinary_gem/issues). -- Issues related to your account: [Open a support ticket](https://cloudinary.com/contact) +asset = Cloudinary::Api.resource("sample") +puts [asset["format"], asset["width"], asset["height"], asset["secure_url"]].join(" ") +``` -## About Cloudinary +## For AI agents -Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently -manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive -and personalized visual-media experiences—irrespective of the viewing device. +`cloudinary` is the Ruby and Rails server-side SDK. Choose it for backend upload, asset administration, view-tag and signed-URL generation, and Active Storage or CarrierWave integration, where the API secret stays private. The core classes (`Cloudinary::Uploader`, `Cloudinary::Api`, `Cloudinary::Utils`, `Cloudinary::Search`) load in plain Ruby; the `cl_image_tag` and `cl_video_tag` view helpers require Rails. For tasks this gem doesn't cover, choose a different package: -## Additional Resources +| Task | Package | +|---|---| +| Build delivery URLs in the browser | [`@cloudinary/url-gen`](https://github.com/cloudinary/js-url-gen) | +| Legacy Rails attachment handling | [`attachinary`](https://github.com/cloudinary/attachinary) — deprecated; prefer Active Storage | +| Run Cloudinary operations as agent tools | [Cloudinary MCP servers](https://github.com/cloudinary/mcp-servers) | -- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references): - Comprehensive references, including syntax and examples for all SDKs. -- [MediaJams.dev](https://mediajams.dev/): Bite-size use-case tutorials written by and for Cloudinary Developers -- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on - YouTube. -- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and - on-site courses. -- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop - for all code explorers, Postman collections, and feature demos found in the docs. -- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should - develop next. -- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to - other Cloudinary developers. -- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration. -- [Cloudinary Website](https://cloudinary.com): Learn about Cloudinary's products, partners, customers, pricing, and - more. +## Links -## Licence +- [Ruby on Rails SDK guide](https://cloudinary.com/documentation/rails_integration) +- [Upload](https://cloudinary.com/documentation/rails_image_and_video_upload) +- [Asset administration (Admin API)](https://cloudinary.com/documentation/rails_asset_administration) +- [Transformation and API references](https://cloudinary.com/documentation/cloudinary_references) +- [Documentation llms.txt index](https://cloudinary.com/documentation/llms.txt) +- [Gem on RubyGems](https://rubygems.org/gems/cloudinary) Released under the MIT license.