Ruby gem
Rails ActiveJobs, Sidekiq workers, Rake tasks.
Pure Ruby gem - zero runtime deps beyond stdlib (`net/http`, `json`). `Chirp.track(name:) { |agent| ... }` is the canonical pattern: opens an activity, yields the agent to the block, closes on block exit. Block exceptions close the activity red automatically.
Designed for the three places long-running Ruby code lives: ActiveJobs (Rails), Sidekiq workers, and Rake tasks. Each pattern has a one-liner - see steps below.
Prerequisites
- Ruby 3.0+.
- A Chirp account.
Setup
- 1
Install the gem
Either bundle it or install globally.
shell# Gemfile gem "chirp", "~> 0.5" # OR globally # gem install chirp - 2
Pair your laptop / server
chirp loginwrites~/.chirp/credentials. For Heroku / Render / Railway-style deploys without an interactive shell, setCHIRP_API_KEYas a config var instead - the SDK falls back to the env var.shellchirp login # or: export CHIRP_API_KEY=chirp_sk_... - 3
Wrap a Sidekiq job
Block-based API drops into Sidekiq's perform method cleanly. The agent ID is automatic; no class-level setup.
app/workers/nightly_backup_worker.rbrequire "chirp" class NightlyBackupWorker include Sidekiq::Worker def perform Chirp.track(name: "nightly backup", schema: "@agent") do |agent| agent.update("dumping postgres") Backup.run! agent.update("uploading to S3") S3.upload! end end end - 4
Wrap a Rake task
Same pattern. Rake task description doubles as the activity name.
lib/tasks/migrate.rakenamespace :db do desc "Backfill v3 schema" task backfill_v3: :environment do Chirp.track(name: "db:backfill_v3") do |agent| User.find_each.with_index do |user, i| user.migrate_to_v3! agent.update("user #{i + 1}/#{User.count}") if (i % 1000).zero? end end end end - 5
Wrap an ActiveJob
ActiveJob is more convention-driven - you can monkey-patch
perform_now/perform_laterif you want every job tracked, or just wrap individual jobs. Recommended: wrap individually so you control which jobs are noisy.
What you’ll see
Card header: Ruby diamond logo + "Ruby · WORKING" + agent name. Action line shows the most recent `update()` argument. Closes green on block exit, red on block raise (with the exception class + message). Sidekiq retries: each retry opens a new card by default; pass `key: jid` to coalesce on the Sidekiq job ID so retries share a single card.
Troubleshooting
- Net::OpenTimeout in production but works locally.
- Production hosts often block outbound HTTPS by default. Whitelist
api.chirpapp.devin your egress rules. The SDK has a 5s connect timeout to fail fast if the network is wrong. - Activity stuck "working" after Sidekiq job dies (segfault, kill -9).
- Sidekiq's hard-kill doesn't run finalizers. The activity auto-expires after 4h. To avoid the 4h hangtime, pair Sidekiq with
Sidekiq::DeathHandlers- callChirp.client.end(activity_id, outcome: :failure)in the death handler. - I want to track Sidekiq's whole queue, not individual jobs.
- Add a Sidekiq middleware that wraps every perform with Chirp.track. The gem's README has a copy-paste middleware snippet.