#code

Public notes from activescott tagged with #code

All things code!

Wednesday, April 1, 2026

uhashring implements consistent hashing in pure Python.

Consistent hashing is mostly used on distributed systems/caches/databases as this avoid the total reshuffling of your key-node mappings when adding or removing a node in your ring (called continuum on libketama). More information and details about this can be found in the literature section.

This full featured implementation offers:

a lot of convenient methods to use your consistent hash ring in real world applications. simple integration with other libs such as memcache through monkey patching. a full ketama compatibility if you need to use it (see important mention below). all the missing functions in the libketama C python binding (which is not even available on pypi) for ketama users. possibility to use your own weight and hash functions if you don't care about the ketama compatibility. instance-oriented usage so you can use your consistent hash ring object directly in your code (see advanced usage). native pypy support, since this is a pure python library. tests of implementation, key distribution and ketama compatibility.

Solo founders and small teams are shipping real products faster than ever.

Launching is the easy part. Once you're live, the hard part starts -- growth, monetization, security, stability — that's where most apps stall out or die.

We've scaled products to millions of users and hundreds of millions in revenue. Now we're building the tools we wish we had when we started.

Think of us as the cofounder you wish you had.

Monday, March 30, 2026

SPACE was created explicitly to address the limitations of single-dimension productivity metrics (including DORA). Its core argument is that developer productivity is multidimensional and cannot be captured by any single metric or even a single category of metrics. You need to measure across multiple dimensions and combine perceptual (self-reported) data with behavioral (system-observed) data.

S — Satisfaction and Well-being

What it measures: How fulfilled, happy, and healthy developers feel about their work, team, tools, and culture. Why it matters: Developer satisfaction is both an outcome worth caring about and a leading indicator of future productivity. Dissatisfied developers leave, disengage, or burn out — all of which destroy team productivity over time. Satisfaction is also the dimension most likely to surface problems that system metrics miss (e.g., "our CI is technically fast but the developer experience of debugging failures is awful"). Example metrics:

Developer satisfaction surveys (NPS-style or Likert scale) Retention and turnover rates Burnout indicators (after-hours work patterns, survey responses) Tool satisfaction ratings

P — Performance

What it measures: The outcomes of the work — not how much was done, but whether what was done achieved its intended result. Why it matters: Activity without outcomes is waste. A team can be very busy (high activity) and still underperform (low performance) if they're working on the wrong things, producing low-quality output, or failing to deliver customer value. Example metrics:

Customer satisfaction / NPS Feature adoption rates Reliability (uptime, error rates) Code quality indicators (defect density, code review quality) Revenue or business KPIs tied to engineering output

A — Activity

What it measures: The count or volume of actions and outputs produced by developers and teams. Why it matters (with caveats): Activity metrics are the most straightforward to collect from systems (commits, PRs, deployments, reviews). They're useful as a component of productivity measurement but dangerous as the primary measure because they incentivize volume over value. The SPACE authors explicitly warn against using activity metrics in isolation. Example metrics:

Number of PRs opened, reviewed, merged Number of commits Number of code reviews completed Number of deployments Number of incidents responded to CI/CD pipeline runs

C — Communication and Collaboration

What it measures: How effectively people and teams share information, coordinate work, review each other's contributions, and work together. Why it matters: Software development is a team sport. Individual velocity means little if coordination overhead is high. Teams with poor communication have longer cycle times, more rework, and more integration conflicts — even if individual developers are productive in isolation. Example metrics:

Code review turnaround time (time from review request to first review) PR review depth (number of review comments, reviewers per PR) Knowledge distribution (bus factor — how many people can work on a given area?) Cross-team PR review frequency Meeting load and interruption frequency

E — Efficiency and Flow

What it measures: Whether developers can do their work with minimal interruptions, delays, and friction. This dimension captures the experience of getting work done — are there unnecessary handoffs, tool-switching, waiting periods, or manual steps? Why it matters: This is the heart of the "developer experience" concept. Two teams with identical DORA metrics can have radically different developer experiences if one team's pipeline is smooth and automated while the other requires manual interventions, workarounds, and waiting. Example metrics:

Time spent waiting (for CI, for reviews, for environments) Handoffs between teams or tools Manual steps in automated workflows Context switches per day "Flow state" time (uninterrupted coding time) Toil and workaround frequency

Thursday, March 26, 2026

Before running any cacheable task, Nx computes its computation hash. As long as the computation hash is the same, the output of running the task is the same.

By default, the computation hash for something like nx test remixapp includes:

All the source files of remixapp and its dependencies Relevant global configuration Versions of external dependencies Runtime values provisioned by the user such as the version of Node CLI Command flags

Nx is a build system for monorepos. It helps you develop faster and keep CI fast as your codebase scales.

Runs tasks fast - Caches results so you never rebuild the same code twice. Understands your codebase - Builds project and task graphs showing how everything connects. Orchestrates intelligently - Runs tasks in the right order, parallelizing when possible. Enforces boundaries - Module boundary rules prevent unwanted dependencies between projects. Handles flakiness - Automatically re-runs flaky tasks and self-heals CI failures.

Here's how I use the dangerous flag safely:

  1. Environment Isolation For greenfield projects or major changes, I work in isolated environments. You can set up a simple Docker container specifically for Claude development:

This gives Claude a safe sandbox to work in without risking your main system. Because I love using Makefiles, here is the one I use for essential tasks:

  1. Task Scoping The quality of your results depends entirely on how well you scope the initial task. Compare these approaches:

Bad: "Build me a financial analysis system"

Good: "Build me a financial data aggregator that does A, B, and C. Look in these specific files, follow this expected flow, create tests that validate each iteration you make, ensure changes are small and incremental."

  1. Sensitive Data Precautions Never use the dangerous flag in directories containing:

API keys or secrets Production configuration files Important datasets without backups System configuration files 4. Review Strategy For longer autonomous runs, I often ask Claude to create documentation or a changelog as it works. This makes the post-work review much more manageable.

Saturday, March 21, 2026

Friday, March 13, 2026

autotraining models with markdown

The idea: give an AI agent a small but real LLM training setup and let it experiment autonomously overnight. It modifies the code, trains for 5 minutes, checks if the result improved, keeps or discards, and repeats. You wake up in the morning to a log of experiments and (hopefully) a better model. The training code here is a simplified single-GPU implementation of nanochat. The core idea is that you're not touching any of the Python files like you normally would as a researcher. Instead, you are programming the program.md Markdown files that provide context to the AI agents and set up your autonomous research org. The default program.md in this repo is intentionally kept as a bare bones baseline, though it's obvious how one would iterate on it over time to find the "research org code" that achieves the fastest research progress, how you'd add more agents to the mix, etc. A bit more context on this project is here in this tweet.

Coding After Coders: Summary

The New Reality of AI-Assisted Programming

  • Elite software developers now rarely write code themselves — instead, they direct AI agents in plain English
  • Tools like Claude Code deploy multiple agents simultaneously: one writes, one tests, one supervises
  • Tasks that once took days now take under an hour

The Strange New Workflow

  • Developers spend their days describing intent to AI, reviewing the AI's "plan," then letting agents execute
  • When agents misbehave, developers have resorted to scolding, pleading, ALL-CAPS commands, and emotionally charged language ("embarrassing," "national security imperative") — and it seems to work
  • Prompt files have become records of hard-won rules to constrain unpredictable AI behavior

Economic Stakes

  • Coding was once considered near-guaranteed, high-paying employment ($200K+)
  • It may be the first expensive white-collar skill AI can fully replace — unlike AI video or legal briefs, AI-generated code that passes tests is indistinguishable in value from human-written code
  • Irony noted: Silicon Valley workers, who told others to "learn to code," got automated first

Developer Sentiment: Mostly Euphoric

  • Most developers interviewed were energized, not demoralized — reporting 10x to 100x productivity gains
  • Key insight from tech executive Anil Dash: unlike creative fields where AI removes the soulful work and leaves drudgery, in coding AI removes the drudgery and leaves the soulful parts

Historical Context: A Long Arc of Abstraction

  • Each programming era simplified the one before: Assembly → high-level languages (Python) → open-source packages → now natural language intent
  • AI represents the highest abstraction layer yet: developers no longer need to manage syntax, memory, or debugging minutiae
  • The open question, now being asked at Anthropic itself: what is coding, fundamentally, when the code-writing is gone?

Tuesday, March 10, 2026

Why not just play in English? English is already an agent framework—we're structuring it, not replacing it. Plain English doesn't distinguish sequential from parallel, doesn't specify retry counts, doesn't scope variables. OpenProse uses English exactly where ambiguity is a feature (inside ...), and structure everywhere else. The fourth wall syntax lets you lean on AI judgment precisely when you want to.

How is this a VM? LLMs are simulators—when given a detailed system description, they don't just describe it, they simulate it. The prose.md spec describes a VM with enough fidelity that reading it induces simulation. But simulation with sufficient fidelity is implementation: each session spawns a real subagent, outputs are real artifacts, state persists in conversation history or files. The simulation is the execution.

The Agent Skills format was originally developed by Anthropic, released as an open standard, and has been adopted by a growing number of agent products. The standard is open to contributions from the broader ecosystem.

The Agent Skills format was originally developed by Anthropic, released as an open standard, and has been adopted by a growing number of agent products. The standard is open to contributions from the broader ecosystem.

Monday, March 2, 2026

You can extract it as a function:

import { camel, mapKeys } from "radash"; import { z } from "zod";

export const camelCaseSchemaDef = (schema: T) => z .record(z.any()) .transform((x) => mapKeys(x, camel)) .pipe(schema) as T;

Use it like:

export const summarySchema = camelCaseSchemaDef( z.object({ isArticle: z.boolean(), summary: z.string(), introduction: z.string(), terms: z.array(z.string()), }) );

type Summary = z.infer // type Summary = { // isArticle: z.boolean(), // summary: string, //. introduction: z.string(), //. terms: z.array(z.string()), // }

summarySchema.parse({ is_article: true, summary: "abc", introduction: "abc", terms: ["abc", "bca"], })

#