Brad Zacher

Brad Zacher

@brad.zacher.com.au

Computer scientist. Cider drinker. Dungeon Master. Maintainer of @typescript-eslint.io Software Engineer @ Cursor (prev Canva, Meta). https://zacher.com.au

815 followers188 following136 posts

15.5B tokens. 266 pull requests. 3,878,930 lines added. 5,278,449 lines removed. First month at Cursor and it was big, to say the least. It's the first time I've really leant into agents and needless to say you really can get a lot done. I landed a LOT of build infra clean ups.

This month was a lot of standardisation work - 3 FE formatters down to 1 (oxfmt), 3 FE linters down to 2 (on the way to 1, oxlint). 4 package managers down to 1 (pnpm). Next month the focus will be CI - bazel across the frontend to help standardise infra and improve build times.

Today is my last day at Canva. It's been a blast and I've thoroughly enjoyed working there for the past 4 years. But it's time for the next adventure. Sunday I fly to SF and next week I'll be joining Cursor working on developer productivity. I couldn't be more excited!!!

Used an agent for profiling for the first time today. It was pretty cool to let it just run some tools and try to find some potential improvements. It came up with some vague suggestions I was able to grow and iterate on for some decent wins!

View full thread

Pro: I got some (okay) recommendations for work, quickly. The good leads mostly just confirmed suspicions I had, but it felt good to get a 2nd opinion. Con: Many of the recommendations were obviously flat-out wrong -- if I wasn't as experienced I might have wasted a lot of time!

I guess if I was one of the vibers I'd have just gone "full ralph" and fired off agents on each task and then only really wasted tokens, rather than time on the useless leads... There's definite value here as a tool in the toolchain, but I still think human-first is hard to beat

Used an agent for profiling for the first time today. It was pretty cool to let it just run some tools and try to find some potential improvements. It came up with some vague suggestions I was able to grow and iterate on for some decent wins!

Pro: I didn't have to learn the profiling tools or analyse the data Con: I didn't learn anything about the tools I know I can read the history to see what it did -- but it doesn't help me learn the steps. EG It wrote a python script to analyse the dump from the tools... but why?

We added a fixer for unused imports to no-unused-vars! By default it's a suggestion fixer - but you can swap it to an autofixer (for autofix-on-save or --fix). Please try it out today!

Brad Zacher reposted

📝 New blog post: Revamping the `ban-types` rule. For many years, ban-types was one of our more prominent rules. We split it into targeted rules that better addressed common user needs. Read on for how it came to be & what those new rules do better! typescript-eslint.io/blog/revampi...

typescript-eslint.ioRevamping the `ban-types` rule | typescript-eslintHow the now-deprecated `ban-types` rule evolved over time to what is now several newer, targeted rules.

I have setup my first "home lab" with proxmox! For my first VM I setup a remote devbox! It took waaaay longer to get it working than I'd care to admit... But I can connect to it via vscode and everything! Now to spin up a few more VMs for things I've always wanted to run...

Has anyone got a good guide to setting up a Ubuntu machine to accept (local) SSH connections? Configuring the base image from scratch is not super easy when you've never done it before :harold:

Okay I just got a Beelink SER9 for use as my remote devbox and server host. Now to figure out how to install linux on it... boy it's been a long while since I've done this.

If I ever see someone's comment and it says "you're absolutely right" I now automatically assume that they are either an LLM bot or that they're copy pasting from one. It's such a shame that we have to deal with this slop contribution in our opensource projects.

View full thread

This isn't just limited to PR either - we've seen the same behaviour with issues. I recently saw one user file a few issues that were clear and obvious output from asking the agent to plan out a piece of work. They filed an issue with well over 1000 words! And the responses...

We don't want your contribution if you're just a middleman! We could tag copilot on issues and let it run and create a PR without you in the middle pretending to be part of the process. Don't pretend you're contributing. Do the work (with the AI sure) and learn and contribute!

If I ever see someone's comment and it says "you're absolutely right" I now automatically assume that they are either an LLM bot or that they're copy pasting from one. It's such a shame that we have to deal with this slop contribution in our opensource projects.

We've seen a number of people that are literally just acting as an agent middleman. They're asking an LLM to file a PR and then when we leave review comments they're copy pasting our comments into a chat window and copy pasting the responses. It's disappointing, honestly.

One major issue I've found with package.json imports over tsconfig paths is usage across "boundaries". A package.json import spec cannot include a file outside the current dir -- eg it can't start with `../`! They also don't "bubble" through nested package.jsons!

If you have a workspace you can't define package.json imports in the root and have them work in all your child packages. Nor can you have the child packages access paths from the sibling packages. This, OFC, makes sense to avoid publishing broken npm packages. But sucks for non-publishing projects

For example if you have a package.json in a folder to declare some local scripts -- then all files in that folder lose the import mapping! OTOH tsconfig paths work just fine in this setup as they place no restrictions on what you can target.

It's been a great few days in Atlanta for #BazelCon. Met lots of great people. Learned a bunch about bazel and the community around it. And (finally) gave my first conference talk!

Brad Zacher reposted

Been seeing an uptick in what are clearly vibe-coded PRs. On the surface this seems great -- more contributors! But in the reality it's often AI slop that the person hasn't reviewed and instead the burden of review is on us, the maintainers -- which is a horrible trade.

There's also been some mild concern because some of these PRs has come from brand new GH accounts with few or no other contributions. Kind of makes me think unscrupulous individuals are using AI to make fake accounts look more legitimate with very little effort.

I asked cursor's AI agent to try to create a small TUI form. It went HORRIBLY. After a while it declared the task as done despite numerous compiler errors. When I told it that it wasn't done. This was the agent's response:

> I see we have an issue - we accidentally removed the actual implementation of the TUI when trying to fix the imports. Yes, that's right -- the AI wrote a bunch of code AND THEN DELETED ALL OF ITS CODE *ACCIDENTALLY*. Don't worry folks -- our jobs are safe.

I've been doing a bunch of work on a meta-linter of sorts and so I need to ingest results from many different linters. A really painful problem I've discovered recently is that nobody is consistent about how to define a "location" in text. It's a surprisingly complex space to try and reconcile!

View full thread

The other report style is a line + column pair. Immediately we run into the same issues: - are the two numbers 0-indexed or 1-indexed? Thankfully the definition of a "line" is consistent from what I've seen. But a column is just another ill-defined index with no consistent definition 😭

This is all exacerbated by the fact that you cannot convert one form to the other without the original source code to iterate and count. Who knew that underlining and replacing text could be so damn difficult!?!

I've been doing a bunch of work on a meta-linter of sorts and so I need to ingest results from many different linters. A really painful problem I've discovered recently is that nobody is consistent about how to define a "location" in text. It's a surprisingly complex space to try and reconcile!

Some linters report as a position -- a number representing an index from the start of the file. Seems simple enough but we immediately run into our first problem: is it a 0-index or a 1-index..? Few linters clearly define this yet it can completely break your reports and fixes!

Next what does the index count? "A character" is the usual answer but what is a "character"!? Is it a UTF8 character? UTF16? Unicode? Unicode Grapheme? In most code they're all the same until the code contains a non-ascii character (eg ¹²³) or an emoji (eg ☠️🏳️‍🌈) at which point everything will break!