Skip to content

Application · DevRel & Growth Operations · 3-month contract

Hi, I’m Reet. I tried Cyberwave before writing to you, and I’d love to run DevRel for you.

I did what a new developer would do. Here’s how that went.

  1. 01
    Install
    pip install cyberwave
  2. 02
    Copy
    the first Quickstart example
  3. 03
    Crash
    TypeError on the first twin call
  4. 04
    Fix
    a PR, a question, a checker
01Open, 24 September 2026

Your Quickstart's first example stops on its first twin call

I wanted to try Cyberwave properly before writing to you, so I did what a new developer would do. pip install cyberwave, open the Quickstart, copy the first example. It stopped on its first twin call.

opencyberwave-os/docs-mintlify #105opened 24 September 2026

docs(quickstart): fix cw.twins() and set_joint() so the first example runs

overview/index.mdx+6 −6open on GitHub
before
what a new developer sees
$ python quickstart.py
Traceback (most recent call last):
drone = cw.twins("dji/dji-mini-4-pro")
TypeError: 'TwinManager' object is not callable
after PR #105
what the PR changes it to
# the fixed example, PR #105
drone = cw.twin("dji/dji-mini-4-pro")
arm.joints.set("1", 30, degrees=True)
# both calls exist in cyberwave 0.7.2

Why it’s confusing: cw.twins is real. It’s a TwinManager, so you get an error about a class you’ve never heard of instead of a clean “no such method”. The method you want is cw.twin(), singular.

overview/index.mdx
− drone = cw.twins("dji/dji-mini-4-pro")
+ drone = cw.twin("dji/dji-mini-4-pro")
drone.takeoff()
...
− arm = cw.twins("the-robot-studio/so101")
− arm.set_joint("1", 30)
+ arm = cw.twin("the-robot-studio/so101")
+ arm.joints.set("1", 30, degrees=True) # radians unless degrees=True

The sneaky second bug

that’s almost 5 full spins!

set_joint doesn’t exist, and the real joints.set() takes radians by default. Fix only the name and keep the 30, and the arm gets told this:

what you meant
30°
joints.set("1", 30, degrees=True)
what you sent
30 rad ≈ 1,719°
joints.set("1", 30)
Why the PR is only 6 lines

The PR is small on purpose: 6 lines, one file. The repo looks like a mirror of a monorepo, so I said in the description that it may need porting, rather than pretend I didn't notice.

02Asked, not guessed

The one I didn't fix, because the answer is yours

Six lines across three pages hand control to a human or a model with robot.use_controller(). No Twin class has that method. The only use_controller in the SDK lives on robot.navigation and takes a policy UUID, not "keyboard".

open issuecyberwave-os/docs-mintlify #104opened 24 September 2026

Docs call robot.use_controller(...), which no Twin class in the Python SDK has

open on GitHub
from the Controllers section
robot = cw.twin("unitree/go2")
robot.use_controller("keyboard") # AttributeError
robot.use_controller("my-vla-policy") # AttributeError

I could have written a PR here too, but there are two right answers and only you know which one is true:

A
twin.use_controller() is coming

Then the docs are just early. The SDK catches up and nothing on the page changes.

B
It isn't on the roadmap

Then the Controllers sections show the dashboard for keyboard control, and navigation.use_controller() for handing a robot to a policy.

03reetbatra/cyberwave-quickstart-check

So the next one gets caught the week it happens

Fixing one page is nice. Knowing the next mismatch the week it happens is more useful. So I wrote a script that reads every Python example on your docs pages and checks each call against the SDK you actually get from PyPI.

cyberwave-quickstart-checkPython · ast · weekly CI · 9 tests

One file, no dependencies beyond your SDK. It’s the same idea as docsParity, a tool I built that diffs any repo’s code against its docs, pointed at one product and kept running.

151 docs calls, one square each

spot the red ones
139 match the SDK 12 don’t exist

Where they live

All 12 sit on three pages. The big one is spotless.

  • tools/python-sdk 129 of 129 correct
    your SDK reference: every single call is right
  • overview (Quickstart)8 broken of 15
  • features/teleoperation3 broken of 5
  • features/models-and-datasets1 broken of 2

How it works

  1. 1

    Pull the python blocks out of each page's markdown.

  2. 2

    Parse them with Python's ast and follow two kinds of variable: clients from Cyberwave() and twins from cw.twin(). Names carry across blocks, because your pages define cw once and reuse it.

  3. 3

    Check client calls against a real Cyberwave instance (the client constructs offline), and twin calls against all 26 Twin classes, including attributes set in __init__ and sensor families like twin.camera that you resolve in __getattr__.

python check.py
BROKEN overview/index:38 cw.twins("dji/dji-mini-4-pro")
<- cw.twins is a TwinManager, not callable
OK overview/index:39 drone.takeoff()
BROKEN overview/index:48 arm.set_joint("1", 30)
<- no Twin class has 'set_joint'
...
$ 151 calls checked, 12 broken
It keeps running
It runs every Monday on GitHub Actions against the live docs and the latest SDK. The badge is red today. It turns green on its own once #105 and #104 are settled, and goes red again the first week an example drifts.
What it can't tell you

It's lenient on purpose. Which Twin class a catalog asset turns into is only known at runtime, with an API key, so a method counts as fine if any Twin class has it. It can miss a method on the wrong class, but it shouldn't flag one that exists. The camera story below is the one time it did, and why it doesn't now.

One thing I couldn't settle without an account: your Quickstart names the SO-101's joints "1" to "6", which matches the URDF in your Catalog repo, while the SDK page uses names like "shoulder_pan". One of them is probably wrong for the catalog arm, but I can't prove which without a live twin, so it's a question and not a finding.

04Method

Two ways I nearly sent you something false

Both of these looked completely reasonable and were wrong. I’m including them because I think how someone checks their own work says more than the result does.

  1. 01

    I wrote down the wrong error

    AttributeError → TypeErroroops

    I read the source, predicted AttributeError, and was wrong.

    What actually happened

    My first note said cw.twins would raise AttributeError, because I'd only checked the class. When I actually ran it, cw.twins was there, created in __init__ as a TwinManager, and the real error was TypeError. It's a small difference, but it's the exact text a developer pastes into Discord, so it's the one that has to be right. Now I run every claim before I write it down.

  2. 02

    My checker cried wolf about the camera

    16 → 12 brokenwhoops

    It flagged robot.camera.read() on the SDK page as broken. It works.

    What actually happened

    The first full run reported 16 broken calls, including four uses of twin.camera. I nearly put that in the issue. Then I read Twin.__getattr__: camera, lidar, gps, compass, imu and flashlight are sensor families you resolve at runtime, so they never show up in dir(). The docs were right and my checker was wrong. It reads that list from the SDK now, and there's a test that pins it.

05Zero to 4,800 developers

Ideas for Chapters, from someone who has done the community half before

I've built a developer community from nothing once already. Zero to 4,800 developers in India, for zero-knowledge proofs, back when nobody here had heard of them: 11 events, a 5-week bootcamp with 600+ students, and a $21,000 grants program. Your Chapters applications closed on 14 September, so I'm guessing that's the program that needs an owner right now. Four things did the work last time, and you've already got the bones of most of them.

  1. 01

    Be in the room

    You don't build a developer community from a Discord.

    You have: Leads running meetups, workshops and hackathons, plus a browser Playground and a live SO-101 in Milan, so nobody needs hardware to start.
    +I’d add: every event opens with a starter that was tested that week. The first hour is where people quit.
    How I did it last time

    Offline, in colleges, constantly. Either a one-day hackathon or a three-hour lecture where I took the technology apart until everyone in the room understood it. Not a talk. A lesson. With real rewards, so there was a reason to stay to the end.

    Your Leads run exactly this. The thing I'd add is that every event opens with something that already runs. Your browser Playground and the live SO-101 in Milan mean nobody needs hardware to start, which is a gift. The first hour of a workshop is where people quit, so the starter should be tested the week before, which is the checker's whole job.

  2. 02

    Pay for building, not attendance

    Showing up isn't the thing. Shipping is.

    You have: credits earned per event where 60 people build and deploy something real. That’s exactly right.
    +I’d add: every deployed project becomes a Built with Cyberwave entry, so a Lead’s work shows in public.
    How I did it last time

    An online bootcamp where the reward wasn't for turning up. Finish the lectures, land an open source contribution, then you get paid.

    You already got this right: credits are earned per event where 60 people build and deploy something real, not per head in the room. I'd make that count visible. Every deployed project gets a Built with Cyberwave entry, so a Lead's work shows up in public and the next Lead can see what good looks like.

  3. 03

    Send something real

    Never underestimate an actual object turning up at somebody's door.

    You have: one good event earns a month renting an SO-101. Better than any swag box.
    +I’d add: keep the list of everyone who deployed. It’s who you call first when something new ships.
    How I did it last time

    Everyone who finished the lectures, assignments and quiz got a physical swag box posted to them. It sounds small. It was the most talked-about thing we did. People finished a whole bootcamp for a box.

    Yours is better than a box: one good event earns a month renting an SO-101. The unglamorous part is the list it builds, everyone who deployed something real on your platform. That list is who you call first when a new capability ships.

  4. 04

    Hold people to milestones

    A program is only as good as its follow-up.

    You have: two weeks of training and a certificate for every Lead.
    +I’d add: a short checklist per term and a weekly call with each Lead, with blockers going to engineering that same week.
    How I did it last time

    Nothing in my $21,000 grants program went out as a lump sum. Milestones, a checklist I could actually hold a team to, and a call with every team every week to see what they were stuck on.

    Same shape for Leads. A short checklist per term, a weekly call with each one, and whatever they got stuck on goes back to your engineers the same week, because it will be the thing the next Lead gets stuck on too. Done well, that loop means the first Lead to hit a broken example is also the last.

One more thing

None of this was asked for. I just enjoyed doing it, and it seemed like a better way to introduce myself than a cover letter. If any of it is useful to you, please just take it, whatever happens with the role.

I'd love to own the community program for the three months. I'm in Bangalore, happy to work on your hours, and I've done this exact job once already.

Fastest way to judge me: read PR #105, then run the checker.

Thank you for reading this far. I hope you like it, and I hope we can chat soon.