VSCode has had a fancy terminal IntelliSense for some time now. For some reason, it only worked on my macOS laptop, but not on my Linux machine. So I started digging around and found an important caveat for the integrated terminal:
Note that the script injection may not work if you have custom arguments defined in the terminal profile, have enabled Editor: Accessibility Support, have a complex bash PROMPT_COMMAND, or other unsupported setup.
Turns out that my use of bash-preexec messed up the PROMPT_COMMAND enough that VSCode couldn't inject itself properly.
Now as I described in the previous post, I'm only really using bash-preexec to measure the run time of commands. So I used ChatGPT 5.2 and Claude Opus 4.5 to help me work through my .bashrc to remove that constraint.
First, we keep track of whether we're in the prompt (we don't want to time those commands) and we separately "arm" the timer after the prompt is drawn (so we can time things after the next command runs).
# at the top__cmd_start_us=0__cmd_timing_armed=0__in_prompt=0__timer_arm(){__cmd_timing_armed=1;}__timer_debug_trap(){[[$__in_prompt-eq1]]&&return0[[$__cmd_timing_armed-eq1]]||return0__cmd_timing_armed=0locals=${EPOCHREALTIME%.*}u=${EPOCHREALTIME#*.}__cmd_start_us="${s}${u:0:6}"}trap'__timer_debug_trap' DEBUG
__s=${EPOCHREALTIME%.*}__u=${EPOCHREALTIME#*.}__cmd_start_us="${__s}${__u:0:6}"unset __s __u
# ...PROMPT_COMMAND="__prompt_command; __timer_arm"
The trap bit is clever and does most of the heavy lifting.
Once I got this working with my PS1 (see below), I asked Claude for any other improvements it could think of. I did this 3 times and incorporated all of its suggestions.
The main things I changed were to lazy-load completions and other imports. This brought the shell startup time down from 600ms to 14ms which I definitely notice.
Then there were some quality-of-life improvements:
HISTCONTROL=ignoreboth:erasedups
shopt-s histappend histverify # append and expand history fileHISTTIMEFORMAT="%F %T "# timestamp entriesHISTSIZE=10000HISTFILESIZE=20000# ...shopt-s globstar # let '**' match 0 or more files and dirsshopt-s cdspell # autocorrect minor typos in cdshopt-s autocd # type directory name to cd into it
π¦ Matt Pocock on Ralph Wiggum (Matt Pocock). The technique is simple enough that matches my intuition for how work gets done in a sprint. Matt also has a nice video explainer.
π Logging Sucks - Your Logs Are Lying To You (Boris Tane). Argues for passing a context object around and logging that object (with all the details you could possibly need) when something goes wrong. Extends the concept of structured logging to "wide events".
π Whereβs My Orbital Habitat? (Harry Law / Asterisk). What happens when you're looking for your next moonshot, but the costs keep getting too high.
π Why Stripeβs API Never Breaks: The Genius of Date-Based Versioning (Harsh Shukla). I got through most of this post before it was revealed that Stripe has a version-level description of which features were added to the API and adapters that convert inputs and outputs into the appropriate version level based on date. Very cool, but how do you handle security issues in versions? You options (as far as I can tell are):
Announce you can no longer use a particular version. (Breaks "we support every version".)
Change the behavior of the specific version and re-release with the same version number. (Breaks "this version has this particular behavior".)
Some kind of automatic translation that says "this published version maps to this internal version".
In any case, it's all very nice, but unlikely to impact how most people will design versioned artifacts in the future.
π The Gene: An Intimate History by Siddhartha Mukherjee (2016; via Siraj Raval). The book makes many concepts in biology understandable. Combining the author's personal history makes it heart-warming.
π On deathbed advice/regret (hazn; via Tyler Cowen). I agree with the main point of the post which is why I've usually taken deathbed regret and converted it into specific advice. For many years, I've had the following (lightly edited) list towards the top of my todo list:
π Introducing Beads: A coding agent memory system (Steve Yegge). The whole thing was vibecoded and is kinda crazy, but I've actually been looking for a way to track issues from within git. Apparently the agents really like it.
π Six New Tips for Better Coding With Agents (Steve Yegge). Programming by hand is artisanal. Programming by copy-pasting from a chatbot is obsolete. The future appears to be conducting an orchestra of bot swarms.
π Childhood and Education #16: Letting Kids Be Kids (Zvi Mowshowitz). I grew increasingly angry while reading this. Zvi documents so many rage-inducing examples of bad rules around letting children do things on their own.
cosmofy 0.2.0 is available. So many things came together for this release:
Three open source developers I follow (William McGuan, Simon Willison, and Charlie Marsh) were all in a twitter thread where the concept of something like cosmofy was mentioned.
This release represents a very large shift from bundling individual python files to using uv to bundle entire venv directories. The behavior of the CLI is now much more similar to uv in form and function.
When I was designing the low-level zip file manipulation tools for cosmofy, I wanted an easy way to see the contents of the bundle. We're so used to using ls for looking into directories that I thought it would be cool to emulate as much of ls as I could.
But then I realized this was insane. First, many of the options are just aliases for slightly more explicit options. Charlie Marsh would never have a -t that was an alias for --sort=time. Why should I?
In the end I decided to go with the most common options (sorting, list view), a couple that were easy to implement, and a few longer-form ones that cover most of the aliases.
Imitation is the highest form of flattery which is why as part of the cosmofy 0.2.0 release, I decided to change everything about how the CLI behaved to make it work more like the way the tools from Astral work.
I have a long-term plan for Astral to take over making Cosmopolitan Python apps. It's a long shot, but if they do, it'll be a huge win for cross-platform compatible executables. I also saw this popular issue that there should be a uv bundle command that bundles everything up.
To make it easier to adopt, I decided to make the interface follow Astral's style in three important ways:
Subcommand structure: It's gotta be cosmofy bundle and cosmofy self update
Colored output: Gotta auto-detect that stuff. Luckily, I had fun with brush years ago, so I know about terminal color codes.
Global flags: Some of those flags gotta be global.
Smart ENV defaults: smart defaults + pulling from environment variables to override.
Now I didn't start out wanting to build my own argument parser (really, I promise I didn't!). I tried going the argparse route (I even tried my own attrbox / docopt solution), but I had a few constraints:
I really don't want 3rd party dependencies (even my own). cosmofy needs to stay tight and small.
I want argument parsing to go until it hits the subcommand and then delegate the rest of the args to the subcommand parser.
I want to pass global options from parent to child sub-parser as needed.
Together these pushed for a dedicated parser. This lets me write things like:
usage =f"""\
Print contents of a file within a Cosmopolitan bundle.
Usage: cosmofy fs cat <BUNDLE> <FILE>... [OPTIONS]
Arguments:
{common_args}
<FILE>... one or more file patterns to show
tip: Use `--` to separate options from filenames that start with `-`
Example: cosmofy fs cat bundle.zip -- -weird-filename.txt
Options:
-p, --prompt prompt for a decryption password
{global_options}
"""@dataclassclassArgs(CommonArgs):
__doc__ = usage
file:list[str]= arg(list, positional=True, required=True)
prompt:bool= arg(False, short="-p")...defrun(args: Args)->int:...
cmd = Command("cosmofy.fs.cat", Args, run)if __name__ =="__main__":
sys.exit(cmd.main())
For the colored output, I took inspiration from William McGuan's rich which uses tag-like indicators to style text.
π How I Found Myself Running a Microschool (Kelsey Piper / Center for Educational Progress). Over the past 10 years I have migrated to essentially this view: you need direct instruction to get the basics and a foundation; you need to see people enact the values you want to transmit; and you need a strong motivating project to get you over the humps when the going gets tough.
π Ideas Arenβt Getting Harder to Find (Karthik Tadepalli / Asterisk). Knowing what is causing productivity growth to start to slow is critical to selecting appropriate policies for how to get it going again. Karthik makes a good case for why the idea that "ideas are getting harder to find" is wrong and why it's more of a failure of the market to weed out bad ideas and promote good ones.
π Justified (Bite code!). just is a Rust-based task runner and here's a good write up about its features. If I wasn't writing ds (my own task runner), I'd probably use just. I'll probably experimentally support some subset of just's syntax in ds.
π Book Time #26: How I Read (Aaron Gordon / Book Time). My process for selecting books is very different from Aaron's, but it's nice to see someone else's process.
Mine:
I get recommendations from friends, colleagues, podcasts, and other books.
I add them to a list (currently an Amazon Wishlist). I prefer digital books over physical books because I can make them into audiobook (at 4x) and they take up very little physical space.
When I get to the end of the books I have in my queue, I sort the wishlist by price (lowest to highest) and buy everything under $5. That keeps me busy for about 3 months.
I take all the books that I've purchased and sort them by the number of pages (lowest to highest). This is my new reading queue.
There are only a couple of exceptions for me to deviate from this order:
My wife recommends I read something next, especially as it may impact our kids. This bumps the book to the top of the list (both for purchase and reading).
I'm about to meet someone who recently published a book. There have been a few times where I got through their most-recently published book the day before meeting them. HT: Ramit Sethi who teaches the importance of being overly prepared for certain kinds of meetings.
I often get asked how much I retain from the audio versions of books. My informal tests show no more or less than most people when they read books. I don't remember every detail, but neither do most people. HT: Mike Masnick who introduced me to the idea of listening to podcasts at greater than 2x.
π The Writer's Journey: Mythic Structure for Writers, 3rd Edition by Christopher Vogler (2007; via Chanan Berkovits). You may have heard of Joseph Campbell's The Hero with a Thousand Faces, but how about something with more contemporary references? Also, does the obligatory meta thing and shows how the process of writing itself follows the mythic structure.
While I was updating my standard pyproject.toml to use dependency groups, I switched to using uv as my build backend (from setuptools). Like all the other design choices, it has very sensible defaults with good overrides when you need them.
One thing that it doesn't support is dynamic versions (i.e. reading __version__ from __init__.py). Charlie Marsh explains:
Using dynamic metadata for things that are actually just static lookups feels like the wrong tradeoff.
Like version = ["dynamic"] to read the version from __init__.py.
As soon as you have dynamic metadata, you need to install dependencies and run Python just to get that info.
Static metadata rules. Just write the version out twice!
This makes sense, but I really didn't want to write out the version twice. Luckily, uv has a nice uv version command to change/bump the version number in the pyproject.toml, so I started thinking about how I'd also change the version in the __init__.py at the same time.
I asked ChatGPT what the best approach was and it suggested something quite different: don't write the value in __init__.py at all.
from importlib.metadata import version, PackageNotFoundError
try:
__version__ = version("package-name")# from pyproject.toml: project.nameexcept PackageNotFoundError:
__version__ ="0.0.0"# aka unknown version