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.
- 01Installpip install cyberwave
- 02Copythe first Quickstart example
- 03CrashTypeError on the first twin call
- 04Fixa PR, a question, a checker
- Your Quickstart's first example crashed, so I sent a 6-line fix. PR #105.
- One part needed your product call, so I asked instead of guessing. Issue #104.
- A checker now tests all 151 docs examples against the SDK every Monday.
- I've built a developer community from 0 to 4,800 before. Here's how I'd run Chapters.
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.
docs(quickstart): fix cw.twins() and set_joint() so the first example runs
$ python quickstart.pyTraceback (most recent call last):drone = cw.twins("dji/dji-mini-4-pro")TypeError: 'TwinManager' object is not callable
# the fixed example, PR #105drone = 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.
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:
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.
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".
Docs call robot.use_controller(...), which no Twin class in the Python SDK has
robot = cw.twin("unitree/go2")robot.use_controller("keyboard") # AttributeErrorrobot.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:
Then the docs are just early. The SDK catches up and nothing on the page changes.
Then the Controllers sections show the dashboard for keyboard control, and navigation.use_controller() for handing a robot to a policy.
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.
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 onesWhere they live
All 12 sit on three pages. The big one is spotless.
- tools/python-sdk 129 of 129 correctyour 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
Pull the python blocks out of each page's markdown.
- 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
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__.
BROKEN overview/index:38 cw.twins("dji/dji-mini-4-pro")<- cw.twins is a TwinManager, not callableOK 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
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.
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.
- 01
I wrote down the wrong error
AttributeError → TypeErroroopsI 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.
- 02
My checker cried wolf about the camera
16 → 12 brokenwhoopsIt 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.
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.
- 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.
- 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.
- 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.
- 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.