Codex

codex-status-json

I made a small Rust CLI that prints Codex status as JSON.

The short version is that I wanted Codex conversations to know my account, model, and quota state without opening the interactive TUI and reading /status like a person.

This is mostly useful with Codex goals. I am on the Pro 20x plan, which is the $200/month tier, so sometimes I really do have quota to burn. If I can read the remaining quota first, I can make a goal with an actual target instead of guessing how ambitious I should be.

The missing command

Codex has /status in the interactive CLI. It shows useful stuff: account, model, context, writable roots, and rate limits.

That is fine when I am sitting in the TUI. It is less fine when I want another Codex conversation to ask the same question.

There is an upstream issue asking for this exact kind of thing: a non-interactive JSON/headless replacement for /status. The issue is still open as I write this. There is also codex doctor --json, which is useful, but that is a diagnostic report. It is not the same as “tell me my account/model/quota status right now.”

So I made codex-status-json.

The first version was worse

The first version did what you would expect from a tool born out of impatience: it opened Codex in a PTY, sent /status, waited for the panel to settle, captured the terminal output, stripped ANSI escapes, and parsed the text.

It worked. It was also clearly a bad long-term place to live.

Terminal scraping is annoying because every little UI change can break you. The parser has to care about box drawing, timing, update notices, trust prompts, terminal width, and whatever else the TUI happens to render that day.

Still, it was useful. It gave me JSON like this:

{
  "schema_version": 1,
  "account": {
    "email": "user@example.com",
    "plan": "Pro",
    "raw": "user@example.com (Pro)"
  },
  "model": {
    "name": "gpt-5.5",
    "details": "reasoning high",
    "raw": "gpt-5.5 (reasoning high)"
  },
  "buckets": [
    {
      "name": "default",
      "limits": [
        {
          "kind": "5h",
          "remaining_percent": 99,
          "resets": "14:44",
          "reset_at_unix": 1780350290
        },
        {
          "kind": "weekly",
          "remaining_percent": 70,
          "resets": "08:23 on 7 Jun",
          "reset_at_unix": 1780845815
        }
      ]
    }
  ]
}

That was enough to unblock the thing I wanted.

The less cursed version

A few days later, I switched the default backend to Codex’s app-server.

That is a much better source than scraping the TUI. The tool starts:

codex app-server --listen stdio://

Then it sends JSON-RPC calls for:

  • account/read
  • account/rateLimits/read
  • config/read

That gives it the same kind of account, model, and quota information without pretending a terminal status panel is an API.

Important caveat: Codex app-server is documented, but it is also described as experimental and may change. So this is still not a supported codex status --json. It is just a more sensible workaround than screen scraping.

The PTY backend is still there as a fallback:

codex-status-json --backend pty

But the default is now:

codex-status-json --backend app-server

This is a bridge

I do not expect this to be the forever answer.

Codex’s usage and billing surface is still moving. OpenAI has already introduced things like banked rate-limit resets, so the status shape is not just “two counters and call it done.” There are plans, windows, reset times, secondary buckets, and whatever else comes next.

So I can see why OpenAI might not want to commit to a stable status JSON contract yet. That is fine. I still wanted something local that worked now.

This is the same kind of bridge as a lot of these small tools: use the available pieces, make the annoying gap tolerable, and be happy if the official thing eventually replaces it.

The repo

The project is here:

https://github.com/nelsonjchen/codex-status-command

Install it locally with:

cargo install --path .

The README has the options and limitations. The tests include a captured /status fixture so the text parser can at least fail loudly when Codex changes its display.

I would still rather have an official codex status --json. Until then, this is small, local, and useful enough.

3:03 pm / Codex , Rust , CLI , JSON , Automation

Plainize Clip

I made Plainize Clip, a tiny macOS app that cleans the current clipboard and quits.

The short version is that I still wanted the old Plain Clip shape: copy weird text, launch the app, paste something boring.

Not a clipboard manager. Not a menu bar app. Not a background process sitting around in RAM forever. I launch it through Spotlight, it rewrites the pasteboard as plain text, and then it exits.

The annoying clipboard problem

Copying text on macOS is often not just copying text.

Sometimes it brings formatting. Sometimes it brings weird invisible characters. Sometimes it brings smart quotes, hard-wrapped lines, non-breaking spaces, tabs, and whatever else got dragged along from a PDF, web page, chat app, or ticketing system.

Usually I do not want a whole clipboard workflow. I just want the pasteboard to stop being annoying.

So Plainize Clip does the small version:

  1. Read the general pasteboard.
  2. If there is text, clean it.
  3. Write back plain text only.
  4. Quit.

That is the whole normal launch path.

Launch, clean, quit

The important behavior is that Plainize Clip is faceless.

There is no Dock icon to manage after the cleanup. There is no persistent process. There is no history database. If the current pasteboard has text, it cleans it with the saved preferences and replaces the pasteboard contents with text.

[... 608 words]

11:05 pm / Macos , Swift , Clipboard , Appkit , Reverse engineering , Codex

Unofficial MakerWorld PMM OpenSCAD Reference

I made an unofficial MakerWorld PMM OpenSCAD reference.

The short version is that I wanted Codex to help me make MakerWorld-customizable OpenSCAD models, and I did not want it guessing from old forum posts, UI behavior, and whatever I happened to remember at 1 AM.

This started because I wanted to use agents on my own OpenSCAD projects without re-teaching the same MakerWorld-specific weirdness every time.

The documentation problem

MakerWorld’s Parametric Model Maker is genuinely useful. OpenSCAD plus a web customizer is a great fit for 3D-printable stuff where the interesting part is “same idea, slightly different dimensions.”

If you have not run into it before, OpenSCAD is CAD by writing code. You write variables, modules, and geometry operations, and it turns that into a model. That makes it very good for customizable prints, and very annoying when a target platform has extra rules.

Unfortunately, the OpenSCAD side of PMM is documented in a very internet way. Some of it is in release posts. Some of it is in support replies. Some of it is in the actual web app. Some of it is people trying things and reporting what happened.

There is a Bambu forum thread literally titled Any Documentation on Parametric Model Maker?. The first post asks where to find the requirements for making customizable models. That felt familiar.

For a human, scattered docs are annoying. For a coding agent, they are a great way to get plausible garbage. It might write OpenSCAD that looks fine locally but misses MakerWorld’s actual rules. It might invent a PMM feature because it saw something sort of similar somewhere else.

I do not want an agent inventing // preview[...] as a PMM feature. I want it to know that // color is a thing, // font is a thing, mw_plate_N() is a thing, and default.svg is not just some random example filename.

So I made a reference.

What I collected

The repo is basically a practical map of the PMM OpenSCAD surface:

  • the PMM OpenSCAD API
  • an agent workflow for converting normal OpenSCAD into PMM-ready OpenSCAD
  • gotchas that agents are likely to mess up
  • compatibility rules
  • public source snapshots
  • patterns and checklists
  • a generated docs site

The small examples are the important ones:

accent = "#FF0000"; // color
font_name = "Roboto"; // font

module mw_plate_1() {
    // printable plate here
}

module mw_assembly_view() {
    // preview-only assembly here
}

svg_file = "default.svg";

None of that is hard once you know it. The problem is making sure the agent knows it before it starts “helping.”

I also made a PMM font index. It has 1881 MakerWorld PMM font families and 8267 exact PMM font strings. This got more elaborate than I expected, but fonts are exactly the kind of thing where an agent can confidently choose something that works on your machine and then does not work where the model actually runs.

Why agent-first

This is not meant to replace the official PMM UI or be a polished tutorial for someone’s first customizable model. It is mostly a pile of receipts and instructions for agents.

Point Codex or another coding agent at the repo, then ask it to adapt a .scad file for MakerWorld. The repo gives it rules to retrieve before it starts editing:

  • flatten local includes when PMM probably will not have them
  • do not remove bundled PMM libraries like BOSL2 just because arbitrary local includes are risky
  • use PMM upload defaults like default.svg and default.stl
  • add // color and // font only where those controls are intended
  • treat multi-plate output as a publishing decision, not just a module name
  • cite whether a claim came from an official app endpoint, official release, employee reply, community report, or inference

That last part matters. I do not want a pile of agent-generated confidence. I want the agent to say why it thinks something is true.

The repo

The project is here:

https://github.com/nelsonjchen/unofficial-makerworld-parametric-model-maker-openscad-docs

The generated docs site is here:

https://nelsonjchen.github.io/unofficial-makerworld-parametric-model-maker-openscad-docs/

This is unofficial, not endorsed by Bambu Lab or MakerWorld, and not a license grant for any font, library, model, or web asset. It is practical documentation from public sources and reverse-engineering.

It is also probably incomplete or wrong in places. PMM keeps changing, and some of this stuff only becomes obvious after someone trips over it.

Anyway, this mostly exists so my agents stop making the same MakerWorld OpenSCAD mistakes. If it saves someone else from digging through forum threads while trying to publish a customizable model, great.

8:15 am / Bambu , Makerworld , Openscad , 3d printing , Codex