❌

Vue normale

  • ✇The Pragmatic Engineer
  • Building Codex with Tibo Sottiaux
    Stream the latest episodeListen and watch now on YouTube, Apple, and Spotify. See the episode transcript at the top of this page, and timestamps for the episode at the bottom.Brought to You by• turbopuffer – a vector and full-text search engine built on object storage. It’s fast, cheap, and extremely scalable. The teams building the smartest AI products out there — Anthropic, Cognition, Notion, Harvey — all run on turbopuffer. Check it out• Antithesis – use AI agents to work on critical systems
     

Building Codex with Tibo Sottiaux

9 septembre 2026 à 17:57

Stream the latest episode

Listen and watch now on YouTube, Apple, and Spotify. See the episode transcript at the top of this page, and timestamps for the episode at the bottom.

Brought to You by

• turbopuffer – a vector and full-text search engine built on object storage. It’s fast, cheap, and extremely scalable. The teams building the smartest AI products out there — Anthropic, Cognition, Notion, Harvey — all run on turbopuffer. Check it out

• Antithesis – use AI agents to work on critical systems without worrying about correctness. Antithesis runs your complete system in a hostile environment, analyzes its behavior, and reproduces every issue perfectly. Learn more

• Entire – Git hosting, rebuilt for the agentic era. Entire hosts your code in-region, and is up to 89x faster than any other competitor. Mirror from GitHub with a single click – I’ve already done so.

In this episode

Tibo Sottiaux is one of the engineers who created Codex, and today, he heads up the Core Products & Platform org at OpenAI which also includes Codex. He’s also one of the most public faces of Codex due to his frequent – and generous – usage reset announcements, like this one yesterday.

In this episode of the Pragmatic Engineer Podcast, Tibo and I discuss how Codex was built and continues to be iterated upon. We explore why the Codex CLI is written in Rust and was released as open source, how the harness and models have evolved, and why Codex supports models from multiple providers.

Tibo also shares details about how the OpenAI team uses Codex throughout the software development lifecycle, including code reviews, maintenance, and system rearchitecture. We look into how AI is lowering the cost of changing code – and some interesting side effects of this – the merger of ChatGPT and Codex, and also how Tibo uses the tools in his own work.

Takeaways from the conversation with Tibo

1. A shock cancellation proved to be an important lesson. While at Google in London, Tibo spent two enjoyable years working on a project in the Ads organization – right up until a VP flew in from California and abruptly cancelled the whole thing. Tibo was shocked: there were hundreds of users and he was having a great time solving engineering challenges. Reflecting later, he realized he’d been blind to the fact that the product had no product-market fit and the feedback loop from users was poor. Tibo also learned that just because a product manager says a project is going well, doesn’t mean it is! That experience means he now always questions the impact of his work, and the importance of projects to which he contributes. Looking at Tibo’s career since, it seems like a well-timed lesson!

2. Google had a “ChatGPT-like” project a year before OpenAI. At the start of the decade, DeepMind was largely focused on games and reinforcement learning, but some members, including Tibo, reckoned that scaling language models might lead to artificial general intelligence (AGI). Their “chat with an LLM” project spread like wildfire internally, but for some reason the product was never launched. Who knows what would have happened if Google had beaten OpenAI to the public launch of AI chatbots in 2022.

3. Tibo was drawn to OpenAI because only 20 people worked on ChatGPT. Tibo had a great run at Google, but missed working somewhere where Research and Product collaborated more closely than at the search giant. When he learned in 2023 that ChatGPT was built and maintained by around 20 engineers – despite its massive popularity – he was very surprised and wanted to join.

4. Codex is built using Rust, even though the AI models were much better at writing Python and TypeScript at the time. The Codex team had a vision of Codex instances running on millions of cloud machines, which meant performance, security, and engineering for efficiency and scale were the first design principles. This led to Rust, despite AI models then not being the strongest at writing Rust. The team’s decision to choose a performant language upfront and avoid a rewrite later reminds me of Casey Muratori’s point about the need to architect for performance, upfront.

5. Codex is open source, which has upsides and downsides. Codex’s biggest competitor, Claude Code, is closed source, so I find it inspiring that the Codex team chose the open source path. Tibo says the upsides are trust and the community of contributors who are an energizing influence. A less discussed downside of open source is that the Codex team’s work sometimes gets copied and released in other tools before Codex. Tibo told me this stings, but it’s the price of working in the open.

6. Open source is a big reason why Codex supports working with other AI models. Claude Code can only be used with Anthropic’s models, whereas Codex is usable with any model, not just OpenAI’s. Being open source means that even if Codex were locked down to a model, anyone could still fork the harness and change a few lines of code to support a different model. Tibo believes in winning by letting users use the best models; the Codex team themselves also try other models in the same harness. Personally, I appreciate this approach of encouraging competition from a frontier lab!

7. Cloud development environments (CDEs) never took off outside of Big Tech because of setup costs – but AI agents could change this. Tibo predicts a resurgence of fully cloud-orchestrated machines, where agents like Codex can configure and stay in sync with your local machine setup.

8. The Codex harness is always slightly ahead of OpenAI’s latest model. The harness provides the model with crutches: guardrails, safety, efficiency, steerability, and the developer message injected into context at the start of each turn. As models improve, some “crutches” are discarded and the harness shrinks. This has been the development cycle between Codex and OpenAI’s new models to date.

9. Codex “knows” a staggering amount because it’s plugged into pretty much every OpenAI system. I asked Tibo what pointers he’d give a new joiner on the Codex team. His answer: “have you asked Codex?” At OpenAI, it’s plugged into Slack, every document, and all code, by default. New starters are surprised about being able to ask it anything, including who’s working on something, or why a decision was made. The team purposely work in public channels and open documents with broad permissions.

10. Correctness checks and security reviews will be automated with AI. With code review changing under AI’s influence, Tibo believes that discussion about the intent of code doesn’t have to happen inside a code review, which is mostly about correctness, information exchange, and providing a forcing function for conversations that should’ve happened sooner. With AI code review, conversations about what the system should do still matter, and are probably best had before the code is written. This echoes the theme of this week’s Tuesday article about what is happening with code reviews.

11. Maintaining and re-architecting code is becoming very cheap with agents, especially time-wise. Maintenance tasks like dependency upgrades can be handled by a model blasting through the codebase within a couple of hours. Meanwhile, re-architecting for new tradeoffs that used to take years can now take days, at most. Tibo adds a caveat: quality code, good abstractions, and good test suites greatly affect how easy – or not – a codebase change is to make.

12. Being “in the zone” is history; Tibo sees code as a tool for solving problems. During the podcast recording, we bonded over remembering the “good old days” of pulling late nighters and staying “in the zone” to solve difficult problems with code. These days, Tibo has adapted, like most people at OpenAI. He still opens an editor and writes a little code because it feels nice, but says that an upside of AI agents is being able to gather more data faster – meaning there’s less need for the lengthy coding sessions of yore. Instead of making gut calls, he can fire off an agent and get the data within a minute to make much better decisions with.

The Pragmatic Engineer deepdives relevant for this episode

• How Codex is built

• How Claude Code is built

• How Cursor was built

• What is “loop engineering?”

• How Uber uses AI for development: inside look

• Why Ramp built its own in-house coding agent, Inspect

• “I ship code I don’t read”: with Peter Steinberger, the creator of OpenClaw

Timestamps

00:00 Intro

07:21 Working at Google

12:41 What drew Tibo to OpenAI

15:19 The early days of Codex

18:20 Why Codex was built in Rust

21:15 Why Codex is open source

25:50 Codex plays nice with other models: why?

32:09 How the harness works

36:44 Harness and model improvements

41:19 The SDLC behind Codex

46:39 Code reviews at Codex

52:09 Maintenance and architecture

56:43 How AI tools expand what engineers can do

1:02:30 The Merge: ChatGPT + Codex

1:07:16 How Tibo uses Codex and ChatGPT

1:10:44 Advice for engineers who want to work in AI

References

Where to find Tibo Sottiaux:

• X: https://x.com/thsottiaux

• LinkedIn: https://www.linkedin.com/in/thibault-sottiaux-27195366

Mentions during the episode:

• How Codex is built: https://newsletter.pragmaticengineer.com/p/how-codex-is-built

• Slow down to speed up: so much has changed in 6 months’ time: https://newsletter.pragmaticengineer.com/p/slow-down-to-speed-up

• N-Side: https://www.n-side.com

• Google DeepMind: https://deepmind.google

• AlphaFold: https://deepmind.google/science/alphafold

• Tibo’s reply on X about Google’s canceled bot, LMChat:

• Greg Brockman on X: https://x.com/gdb

• Sam Altman on X: https://x.com/sama

• Python: https://www.python.org

• Rust: https://rust-lang.org

• The creator of Clawd: “I ship code I don’t read”: https://newsletter.pragmaticengineer.com/p/the-creator-of-clawd-i-ship-code

• Using Goals in Codex: https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex

• ChatGPT is now a partner for your most ambitious work: https://openai.com/index/chatgpt-for-your-most-ambitious-work

• ChatGPT Work: https://chatgpt.com/work

—

Production and marketing by Pen Name.

💾

  • ✇FreshRSS releases
  • FreshRSS 1.30.0
    Milestone This is a security-oriented major release with several important security patches, so users are encouraged to update without delay. From this release, we are also making it clear that our rolling-release channel (edge) is recommended for faster security patches. Breaking change 💥: Disallow access to local networks such as 127.0.0.1 by default, for security reasons Feature highlights✨: Filter global view feed list by state and search New option to hide badges showing number of unre
     

FreshRSS 1.30.0

Par : Alkarex
9 septembre 2026 à 16:43

This is a security-oriented major release with several important security patches, so users are encouraged to update without delay.

From this release, we are also making it clear that our rolling-release channel (edge) is recommended for faster security patches.

Breaking change 💥:

  • Disallow access to local networks such as 127.0.0.1 by default, for security reasons

Feature highlights✨:

  • Filter global view feed list by state and search
  • New option to hide badges showing number of unread articles (Phantom Obligation)
  • Refresh only feeds in the current view
  • Offer to add a prefix when re-sharing user labels

Bug fixes highlights 🐛:

  • Several security attack scenarios patched
  • Fix lost elements while parsing search query
  • Fix “mark as read older than…” widening the active search
  • Fix saving user queries
  • Fix SQL errors breaking some regex searches with MySQL / MariaDB

This release has been made by @Alkarex, @andris155, @ColonelMoutarde, @Frenzie, @IEEE-754, @Inverle, @math-GH, @nykula, @polybjorn, @Stunkymonkey and newcomers @0xdeadrelay, @AdamKorcz, @aligundogar, @bossaarebecca-alt, @Cactys12, @chrislongros, @Divinelink, @Elgeryy1, @featurecreep-cron, @Fripix, @fzlzjerry, @georatas, @gshimo, @iatman ,@ihsanarifr, @jamalkamaladdin, @JamBalaya56562, @jbrayton, @jeremy-code, @juherr, @kobihikri, @LeeXiaolan, @masskrdjn, @mohammadlashkari, @nathanpixodeo, @Otolock, @payaci, @salvador-castro, @SamCyber001, @satyvm, @senti-man, @simitana, @ThomasVermeer, @Totara-thib, @TowyTowy, @utkutibet, @XiaoSong1223

Full changelog:

  • Security
    • 💥 Disallow access to local networks such as 127.0.0.1 by default, for security reasons (breaking change) #8400,
      #9195
      • Selected local networks can be allowed under System configuration or using the INTERNAL_HOST_ALLOWLIST environment variable
      • Passing * allows all networks like before (unsafe)
    • Improve SSRF mitigations by restricting CURLOPT_PROXY #8950
    • Fix auth CSRFs (login and register actions) #9171
    • Log invalid challenge and ignore JSON error during login #9278
    • Disallow fetching of non remote URI #9215
    • Only allow HTTP/HTTPS schemes for enclosure and thumbnail URLs #9272
    • Fix access control in rss and opml actions #8912
    • Refactor to use CSRF field directly instead of borrowing it from a form #9169, #9205
    • Cleaner limit anonymous mode to default user #9235
    • Fix HTML ingestions in templates #9146, #9170
    • Fix bad header filtering bypass #8964
    • Sanitize all fields during JSON import #9168
    • Gate greader (JSON) user query share format behind Share by OPML #9248
    • Public OPML should not contain cURL parameters #9070
    • Ignore security-relevant OPML attributes for dynamic OPML sources #9276
    • Strip feed URL credentials from anonymous user query output #9246
    • Set limits for regex during search #8913
    • Fix path disclosure in cache error message #9206
    • Limit the length and parentheses nesting depth of a search query #9277
    • Use timing-safe comparison for tokens #8945
    • Use hash_equals() for GReader API token comparison #9183
    • Mailer: allow disabling SMTPAutoTLS via config #9026
    • Warn during install if document root does not point to ./p/ #9010
    • Stop the unread-count poller after the session ends #9065
    • Add remote IP address to warning on form login #8942
    • Pin the GitHub actions using SHA #9200
    • Harden cache and SimplePie cache deserialization #9273
  • SimplePie
    • Security: Disallow javascript: URI scheme (protocol) #8263
    • Fix wrong player parent logic leading to invalid type #8893, simplepie#978
    • Consistently enable XML_OPTION_PARSE_HUGE #8894, simplepie#977
    • Fix null warning in IRI for PHP 8.5+ #8918, simplepie#979
    • Fix sanitizer whitelist stripping order #9066
    • Show only one representation per media:group #9009
    • Bump upstream SimplePie #8947
  • Features
    • Filter global view feed list by state and search #9132
      • Use global view when searching from subscription page #9144
    • New option to hide badges showing number of unread articles (Phantom Obligation) #8844
    • Refresh only feeds in the current view #9060
    • Offer to add a prefix when resharing user labels #9236
    • Add log search to the logs page #9059
    • Add configurable log_level system setting #9185
    • New option to keep or not the custom sort order when navigating between categories and feeds #8969
    • New per-feed option to show or hide enclosures (attachments) #9015
    • Detect JSON feeds from URLs containing json #9058
      • Also when subscribing via the API #9167
    • Order categories during OPML import/export according to position #9203
    • OPML: include each feed’s refresh interval (TTL) in export/import #8982
    • Log failed CSS content retrieval (Web scraping) #9077
    • Allow providing a category when adding a feed by bookmarklet #9047
    • Add LinkAce sharing service #9024
    • Add Nextcloud Bookmarks sharing service #9032
  • Bug fixing
    • Fix lost elements while parsing search query #8884
    • Fix “mark as read older than…” widening the active search #9173
    • Fix saving user queries #9190
    • Fix SQL errors breaking some regex searches with MySQL / MariaDB #9036
    • Fix marking filtered label articles as read in SQLite and PostgreSQL #9264
    • Fix tagging an already-tagged entry on PostgreSQL raising a SQL error instead of being a no-op #9136
    • PostgreSQL: make committing new entries resilient to duplicate keys #9231
    • Preserve negative timezone offsets in date intervals #9071
    • Fix feed dropdown bugs due to hash desync #8949
    • Fix slider not reinitializing after form submit #8973
    • Minz: Skip loading duplicated JS/CSS assets #9000
    • Respect simplepie_syslog_enabled for the uses cache logs #8986
    • Fix statistics repartition averages #8996
    • Fix article hover date visibility #8997
    • Keep search and state filters when marking articles as read #9007
    • Fix --db-prefix silently drops following CLI flags #9042
    • Remove stale dynamic favicon links #9127
    • Fix desync between favicon and title unread counters #9262
    • Fix outdated username length hint on registration and install forms #9013
    • Redirect away from wrong URL paths #9075
    • Fix auto-share shortcut on first use #9072
    • Exclude hidden feeds from global view counts #9152
    • Fix only the last <media:credit> being written to the RSS output #9174
  • CLI
    • New cli/reconfigure-user.php to read/write per-user config attributes #8873
    • Report new articles count per feed in app/actualize_script.php output #8948
    • Output a diagnostic when the cli/health.php check fails #8980
  • API
    • Add a warning message to the API password section and a log warning when a client uses GET instead of recommended POST #8845
    • Fever API: log the client IP address on authentication failure #8981
    • WebSub: ignore HTTP/HTTPS scheme difference in Self URL comparison #9005
  • Deployment
    • Docker alternative image updated to Alpine 3.24 with PHP 8.5.7 and Apache 2.4.67 #8916
    • Start supporting PHP 8.6+
      • Docker dev :newest with PHP 8.6 #9155
    • Docker: attach provenance and SBOM attestations to the published image #9150
    • Apache use only CONN_REMOTE_ADDR in logs when mod_remoteip is available, for compatibility with LiteSpeed Web Server #8890
    • Fix .dockerignore being ignored during build in CI #9001
    • New ENABLE_ACCESS_LOG environment variable to disable access logs #9191
    • Check GMP during 32-bit installation #9046
    • Improve actualize mutex to allow multiple instances #9045
    • OIDC: redirect to a default URL on expired auth state instead of 400 #9143
  • UI
    • Always jump article to top when header is offscreen, also when Stick the article to the top when opened is disabled #8870
    • Move article header/footer options (feed title, authors and date, icons position, tags) from Reading to Display configuration #9139
    • Move disable button before remove button in user management #8944
    • Keep scroll position of slider after form submit #8974
    • Group export feeds by category #9079, #9154
    • Sort feed names with locale-aware collation #8985
    • Sort labels with locale-aware collation #9023
    • Format unread counter in title on page load #9263
    • Display slider after submit for all buttons in feed update UI #8999
    • Improve aside keyboard navigation #9202
    • Allows usage of Ctrl/Shift keys with the open website shortcut #9186
    • Fix padding for .nav_menu in Alternative-Dark, Flat, and Nord themes #8901
    • Fix typo in alert error border color variable #9266
    • Use JavaScript Event() constructor instead of deprecated initEvent() #9035
    • Use :user-invalid instead of :invalid for CSS form field styling #9025
    • Remove unused simple layout #8998
    • Various UI and style improvements: #8823, #8824,
      #9140, #9145
  • Extensions
    • Minor Minz_Extension typing #8952
    • Improve extension list fetch diagnostics #9055
    • Fix a PHP warning in Serve action #9267
    • Fix extension settings cancel action #9053
    • Fix sharing menu conflicts with extensions #9074
    • Add read status hook for entries #8995
    • Dispatch a new JavaScript event freshrss:entryStateChange when an entry finishes being marked read/unread #9031
    • Redirect after saving user CSS/JS so changes apply immediately #9006
  • I18n
  • Misc.

❌