Merit, But Make It Legible

Featured

Merit, But Make It Legible

One of the more irritating features of modern life is that people love to say they reward merit when what they often reward is legibility.

Not raw capability.
Not force of will.
Not how much resistance someone had to push through to become good at something.

Legibility.

Did the achievement arrive in packaging the system already knows how to admire? Did it come with a famous school, recognizable institutions, polished references, family support, clean internships, the right tone, the right posture, the right little trail of approved breadcrumbs? If so, people relax. They call it excellence.

Meanwhile, if someone arrives at similar visible competence through a messier path — sparse resources, little formal support, public materials, self-direction, no safety net, and almost no room for error — the response is often weirdly diminished.

That person becomes scrappy.
Surprisingly strong.
Promising.
Impressive, considering.

Considering what, exactly?

What is being “considered” is usually the absence of prestige decoration. The person may have built nearly the same capability, or in some cases more durable capability, but because they did not emerge from a trusted institutional pipeline, people treat the result as somehow less real. Or more provisional. Or faintly suspicious. They get credit, but in the off-brand, slightly patronizing way society reserves for people who succeeded without first being pre-approved.

This is backwards in an important sense.

The person who had elite schooling, money, family support, institutional legitimacy, and low-friction access to opportunity may in fact be highly capable. None of this automatically disqualifies them. Plenty of advantaged people are genuinely excellent.

But there is still a difference between demonstrating excellence under supportive conditions and constructing yourself under weak ones.

The bootstrap path often demands a set of traits that institutions claim to admire but are not especially good at recognizing in the wild:

  • initiative
  • independence
  • persistence
  • improvisation
  • the ability to learn without structure
  • the ability to continue without validation
  • the ability to recover from mistakes that were actually costly

Those are not decorative virtues. Those are core builder traits.

And yet, because they do not come pre-certified by prestige systems, they are routinely under-read. Not merely under-resourced at the start — under-credited even after the fact.

That distinction matters.

Being under-resourced means you lacked inputs.
Being under-credited means the world misreads what you produced.

Those are different problems.

The first makes the climb harder.
The second makes the summit look smaller than it is.

A lot of evaluators will insist this is not bias, just pragmatism. They will say elite labels are useful proxies. And to be fair, they are. Institutions act as compression algorithms. They save busy people the trouble of asking inconvenient questions like:

  • How hard was this path, actually?
  • How much support was quietly embedded in the background?
  • How much independent force did this person have to generate on their own?
  • How many hidden cushions were mistaken for personal greatness?

These are not questions most systems are built to ask, because they are expensive to answer and mildly destabilizing to the mythology. It is much easier to see Harvard, billionaire parents, polished confidence, and familiar signals, then conclude: obviously exceptional.

Clean. Efficient. Safe.

It is much less comfortable to look at someone who assembled themselves from public materials, intermittent guidance, and sheer stubbornness, then admit that what you are seeing may represent a more violent act of self-construction.

The elite profile is often treated as natural greatness.
The bootstrap profile is often treated as an anomaly.

But anomalies are sometimes just reality showing through the branding.

This does not mean the bootstrap person is always better. That would just be reverse snobbery with better PR. The point is narrower and more important: achievement is frequently judged by how frictionless it looks, not by how much force was required to make it happen.

And force matters.

Especially in domains where the environment is unstable, where there is no syllabus, where support is partial, where nobody is coming to organize your progress for you. In those situations, the ability to move without structure, learn without permission, and continue without applause is not some charming side trait. It is often the thing itself.

That person may not sound as polished.
They may not tell the story as elegantly.
They may not have the right names on the résumé.
They may not know how to perform legitimacy in the dialect gatekeepers prefer.

But sometimes they built more real capability with less help and less slack.

And the world, being the world, often reads that as scrappy instead of formidable.

Which is convenient, because formidable would force people to rethink what they are actually rewarding.

Building VoiceAnki, Part II

Featured

Real Decks, Bad Formatting, and the Small Matter of Talking to Your Phone

Last time I wrote about VoiceAnki as the project that started as “what if Anki had a mouth and some manners” and then kept escalating.

This post is the sequel where the app met real decks, real speech errors, and the ancient software engineering tradition of discovering that your clean architecture was, in fact, a suggestion.

The short version:

  • the speech loop got less gullible
  • the grader got more structural
  • the logs stopped being decorative
  • I built a local robot to do smoke tests because my own voice was starting to file HR complaints
  • and we are now close enough to the edge of deterministic grading that the next layer is visible, but still carefully fenced off

This is not an “AI solves education” post.

It is a post about building a voice-first Android study app that has to survive:

  • imported decks with formatting from the cursed earth
  • speech recognition that is usually helpful and occasionally drunk
  • grading policy that has to be fast, fair, and local
  • users who absolutely do not care that the regex looked elegant in your notebook

Demo Decks Lie

There is a phase every voice app gets to enjoy where the demo looks great.

You ask a clean question. You answer with a clean sentence. The recognizer hands you a clean transcript. The evaluator gives you a clean pass. Everyone nods like this was a serious plan all along.

Then you point the app at real material.

That is when you meet answers like:

  • 1. foo2. bar
  • Successful: ... Unsuccessful: ...
  • Pros: ... Cons: ...
  • 1877-78
  • Gen. Milyutin
  • one huge paragraph that starts with the useful bit and then wanders into side quests

Imported decks are not malicious. They are just old, messy, human, and full of local conventions. In other words: exactly the kind of input software tends to hate.

The first big lesson of this branch was that the grader needed to stop pretending every card was basically the same problem. A short person-name fact is not the same thing as a date range. A date range is not the same thing as a compact list. A compact list is not the same thing as a long explanatory answer that a human will naturally summarize instead of reciting bullet-by-bullet like a haunted audiobook.

That sounds obvious now. It was less obvious when the system was still getting away with a lot of fuzzy matching and a relatively small pile of hand-reviewed examples.

Card Shape Beats Raw String Length

The biggest architectural shift in this branch is simple to say and annoyingly non-trivial to implement:

grade by answer shape, not just by answer text

That means the evaluator now spends more effort upfront figuring out what sort of thing it is looking at:

  • short factual answer
  • person name
  • short numeric answer
  • definition
  • compact list
  • explanatory multi-point answer
  • command-like or control-like utterance

Once you have that, the rest of the pipeline gets saner. You stop asking one grading rule to play twelve different sports at once.

We are still keeping the main grading path deterministic and fast. That is not nostalgia; it is product design. If a spoken flashcard app feels like it pauses to hold a committee meeting before deciding whether 1877 to 1878 means 1877-78, the illusion is gone.

The user experience needs to feel immediate.

That means the hot path still has to be cheap:

  • classify once
  • prepare candidate structure once
  • compare against compact evidence
  • decide

If later we add something smarter for borderline cases, it has to sit behind that path, not inside it.

Structure Beats Vibes

One of the most useful additions here is a new structured-answer parser. I am not going to dump the entire evaluator recipe into a public post, because some of that is still moving and some of it is the kind of thing you learn by burning hours in log review. But the broad move is worth talking about.

Instead of treating every stored answer as one opaque blob, VoiceAnki now tries to recognize when the answer is actually a structure:

  • a compact list
  • a numbered list
  • a labeled list
  • a longer explanatory list

That sounds modest. It is not modest. It changes the whole feel of grading.

Here is a trimmed version of the parser entry point:

fun parse(answerText: String): StructuredAnswerParse {
    val decoded = decodeAnswerText(answerText)
    val numberedItems = extractNumberedItems(decoded)
    if (numberedItems.size >= 2) {
        val items = numberedItems.map(::buildItem)
        return StructuredAnswerParse(
            kind = classifyKind(items),
            items = items,
        )
    }

    val labeledItems = extractLabeledItems(decoded)
    if (labeledItems.size >= 2) {
        val items = labeledItems.map(::buildItem)
        return StructuredAnswerParse(
            kind = classifyKind(items),
            items = items,
        )
    }

    return StructuredAnswerParse()
}

That is not magic. It is just the system finally admitting that:

  • formatting matters
  • import damage matters
  • labels matter
  • and if the stored answer is really a list, we should stop grading it like a paragraph that fell down the stairs

Another small but satisfying detail is handling glued list markers. This is the kind of bug that sounds fake until you meet it in the wild:

val source = answerText
    .replace('\n', ' ')
    .replace(Regex("(?<=[a-zA-Z])(?=[1-9][.)-])"), " ")
    .replace("\\s+".toRegex(), " ")
    .trim()

That one line exists because decks really do contain things like foo2. bar, and if you do not split that boundary correctly, you end up evaluating nonsense against nonsense and calling it rigor.

The public version of the lesson is:

real grading quality is often won or lost before you ever compare a transcript to anything

If candidate preparation is bad, downstream scoring does not matter much. You are just being wrong with more confidence.

Speech Software Is Mostly About Timing

There is another lie voice products tell when they are young: that speech recognition quality is the main problem.

It is a problem. It is not the only problem. A lot of the actual work is timing, turn-taking, partials, retries, and deciding when not to believe the recognizer’s last word on what just happened.

This branch did a bunch of work in the speech loop itself:

  • carrying multiple alternatives deeper into grading
  • preserving useful partials
  • separating answer listening from control language
  • treating very short answers differently from long ones
  • quietly retrying some short numeric misses instead of immediately punting to the UI

One of the safer excerpts here is the fallback path for partials:

private fun partialFallbackResult(
    error: Int,
    speechStarted: Boolean,
    strongPartialPhrases: List,
    partialPhrases: List,
): RecognitionResult.Transcript? {
    if (!speechStarted) {
        return null
    }

    val fallbackPhrases = mergePhrases(
        primary = strongPartialPhrases,
        secondary = partialPhrases,
    )

    if (fallbackPhrases.isEmpty()) {
        return null
    }

    return when (error) {
        SpeechRecognizer.ERROR_NO_MATCH -> RecognitionResult.Transcript(fallbackPhrases)
        else -> null
    }
}

This is one of those changes that sounds small until you look at user experience.

If the user said something real, the recognizer heard enough to produce useful partials, and the final result still collapsed into ERROR_NO_MATCH, the product should not act like the person never spoke. That is the kind of behavior that makes users think the app is being smug on purpose.

Arithmetic cards were especially good at exposing this. If the app cannot survive one-word answers like five, it does not matter how clever your long-answer scoring is. Nobody is impressed. They are just annoyed.

So a lot of recent work has been about making the short-answer path feel less brittle without turning the whole system into a thicket of deck-specific hacks.

Fast Matters More Than Fancy

One thing I want to be explicit about: there is a lot of temptation in this space to keep throwing more intelligence at grading until it feels “smart.”

That is not automatically a win.

For VoiceAnki, grading speed is part of the product. The user just spoke. The app needs to respond like it was listening, not like it has submitted a ticket.

That constraint shapes the whole design:

  • keep the deterministic path local
  • keep candidate preparation reusable
  • keep transcript-time scoring bounded
  • do not add a visible “thinking…” pause to the normal loop

There is secret sauce in the exact rubric and decision policy, and I am not going to dump that out here line-by-line. But the public-facing principle is straightforward:

the fast path has to stay boring

If the user notices grading latency, they stop trusting the rhythm of the interaction.

And voice UX is rhythm.

Logs Graduated From Debug Tool to Product Infrastructure

I used to think of logs as something you improve once the interesting engineering is done.

That was cute.

On a speech app, logs are part of the interesting engineering.

A bad miss can come from:

  • speech recognition
  • transcript selection
  • answer-shape classification
  • lexical comparison
  • summary-vs-list policy
  • command/control routing
  • deck formatting

That means “it got this wrong” is not one bug category. It is a small crime scene.

So this branch put a lot more effort into making the logs answer questions like:

  • what transcript did we actually choose?
  • what kind of answer did we think this card wanted?
  • what decision path fired?
  • what evidence made the evaluator accept or reject?

That turns review from:

  • “huh, weird”

into:

  • “the answer was parsed as a structured list, but the wrong branch still ran”
  • “the recognizer had a good partial and then dropped the final”
  • “the card was really a summary-shaped answer, but the evaluator treated it like a raw string match”

That is a much more productive kind of pain.

We Built a Tiny Robot Because Manual Smoke Testing Is a Scam

One of my favorite additions around this branch is a local Pipecat smoke-test agent.

This is not some grand autonomous tutoring system. It is a very specific little goblin.

Its job is:

  1. listen to VoiceAnki through the laptop mic
  2. wait for the phone to stop talking
  3. answer through the laptop speakers
  4. keep doing that long enough to flush out session-loop bugs

That sounds silly. It is also incredibly useful.

The helper has a VoiceAnki-specific prompt, local audio transport, transcript logging, and a blunt little repeat-limit rule so it does not get stuck asking for the question forever:

repeat_limit_rule = f"""
Temporary smoke-test rule:

- Track how many times you have said exactly "can you repeat the question" for the current card.
- If you have already asked {max_repeat_requests} times for the same card, do not ask again.
- Instead, say exactly: I don't know
- Use that forced failure to let VoiceAnki mark the card wrong and move to the next question.
""".strip()

That rule exists because, left to their own devices, voice systems will absolutely form little conversational sinkholes and sit there repeating themselves like two Roombas politely arguing in a closet.

I also finally wrote proper smoke-run capture scripts so the whole thing can run unattended and leave behind artifacts we can review later:

ANDROID_CAPTURE_PID="$(spawn_detached "$ROOT_DIR" "$ANDROID_LOG" \
  "$ADB_BIN" -s "$ADB_SERIAL" logcat -v time \
  VoiceAnkiSpeech:D VoiceAnkiEval:D VoiceAnkiSemantic:D AndroidRuntime:E '*:S')"

PIPECAT_CAPTURE_PID="$(spawn_detached "$PIPECAT_DIR" "$PIPECAT_LOG" \
  "$PIPECAT_PYTHON" agent.py --input-device "$PIPECAT_INPUT_DEVICE" \
  --output-device "$PIPECAT_OUTPUT_DEVICE")"

That gives each run:

  • filtered Android logs
  • Pipecat logs
  • run metadata
  • timestamped folders for later review

It turns out this matters a lot, because manual voice testing is expensive in a very dumb way. You can lose an hour just being the person who says Roosevelt into a phone over and over while watching adb logcat scroll by like the Matrix, except less profitable.

Once a little robot can do even part of that for you, bugs start showing up in clusters instead of as rumors.

The Branch Is About More Than Just One Deck

A lot of the pressure for these changes came from history decks, because history decks are very good at producing:

  • long answers
  • compressed spoken summaries
  • date ranges
  • names with ASR drift
  • multi-point answer blobs

But the goal is not “optimize for history.”

That would be a trap.

The real target is broader:

  • explanatory cards where users summarize instead of reciting
  • imported decks with broken structure
  • voice-native equivalence for dates and names
  • command/control phrases coexisting with answer content
  • better handling for cards where exact string equality is just the wrong abstraction

If the implementation only works because the source material happens to be one subject area, that is not a system. That is a souvenir.

What Landed, and What Is Still Moving

A fair amount of the branch is already real:

  • more answer-shape-aware evaluation
  • stronger short-answer handling
  • better transcript preservation
  • richer evaluator logs
  • local Pipecat smoke testing
  • unattended log capture for long runs

There is also important work underway, some of it not committed yet:

  • broader under-acceptance reduction for explanatory multi-point cards
  • cleaner parsing of ugly imported answer text
  • more voice-native normalization for dates and names
  • more explicit decision-source logging
  • more regression tests built from real reviewed misses, not just happy-path examples

That uncommitted work matters because this branch has been one of those very honest engineering branches where the review notes, the smoke-test notes, and the code all inform each other in tight loops.

Or, put less politely: the app keeps finding new ways to be wrong, and I keep taking notes.

That is good. It means the system is meeting reality.

Deterministic Grading Is Better Now, but It Is Not the Final Boss

This is the part where I want to be careful not to oversell the current system.

The deterministic grader is better than it was:

  • more structural
  • less naive
  • more debuggable
  • less likely to reject obviously good answers for ridiculous reasons

That is real progress.

But there is also a limit to how far you want to push deterministic grading before the whole thing turns into an overfitted museum of exceptions and folklore.

That does not mean the deterministic work was wasted.

It means it was the right layer to improve first:

  • command routing
  • control handling
  • structured parsing
  • short-answer resilience
  • person-name behavior
  • list-vs-summary handling
  • observability

Those are foundational. A later model-backed layer should inherit them, not bulldoze them.

That is why the on-device inference work I have been sketching is intentionally narrow and conservative. The likely next step is not “let a model grade everything.” It is closer to:

  • keep the cheap path cheap
  • keep the main loop immediate
  • use on-device adjudication only for a narrow band of borderline long-answer cases
  • keep abstention first-class
  • make it optional and Android-native

In other words: add one careful new tool, not a second religion.

The Main Lesson So Far

The main lesson from this phase of VoiceAnki is that speech products punish fake abstraction almost immediately.

If your system is too generic, it feels unfair. If it is too clever, it becomes slow. If it is too rigid, users hate it. If it is too permissive, grading stops meaning anything.

The job is to keep finding the narrow path where the app feels:

  • fast
  • fair
  • understandable
  • and boring in the best possible way

Not “maximally AI.” Not “academically pure.” Not “one more heroic regex.”

Just a study loop that feels natural enough that the user forgets how much machinery is underneath it.

And if, along the way, we end up with a better parser, a less gullible speech loop, a tiny local smoke-test goblin, and a cautious roadmap for on-device adjudication, that seems like a pretty decent trade.

ROS2 OSX brew formula

Featured

Getting ROS 2 Working on macOS, Then Packaging It for Homebrew

ROS 2 on macOS is one of those things that technically works, but often feels harder than it should. The official source-build path is real, but in practice it can turn into a long chain of dependency issues, middleware decisions, Python problems, Qt mismatches, and package combinations that work on one machine but not another.

I wanted a better answer than “it builds on my laptop.” The goal was to get ROS 2 running reliably on macOS, verify the tools people actually use in the beginner tutorials and early development workflows, and package the result so other developers could install it with Homebrew instead of rebuilding the whole stack from scratch.

That work is now complete. The result is a Homebrew-installable formula called ros2-kilted-core: a tested, curated ROS 2 Kilted environment for macOS.

The problem

ROS 2 is well supported on Linux. On macOS, the story is less polished.

The source-build path exists, but it is easy to end up in a state where the build partially succeeds, some tools launch, others fail, and the final setup is too fragile to recommend to anyone else. A successful compile is not the same thing as a usable development environment.

That was the real problem to solve: not just making ROS 2 build once, but making it practical.

That meant getting the core runtime working, verifying the tools used in the beginner tutorials, making sure the GUI tools actually launched, and confirming that the result could support real development instead of merely surviving a single build command.

What I built

This project started with a source checkout of ROS 2 Kilted on macOS and a curated build of the packages needed for a realistic developer workflow.

That included:

  • building the core ROS 2 runtime on macOS
  • standardizing on Fast DDS as the default supported middleware path
  • verifying demo talker/listener nodes
  • getting turtlesim working
  • validating the beginner CLI tools, including:
    • ros2 node
    • ros2 topic
    • ros2 service
    • ros2 action
    • ros2 param
    • ros2 interface
    • ros2 launch
    • ros2 doctor
    • ros2 bag
  • getting rqt_graph, rqt_console, and rqt_service_caller working on macOS
  • creating a separate tutorial workspace for beginner client-library examples
  • packaging the result into a Homebrew formula

The result is not a theoretical “this should probably work” setup. It is a tested ROS 2 environment for macOS, built from source and packaged for reuse.

The macOS-specific work

A large part of the effort was in solving the smaller platform-specific issues that tend to make ROS 2 on macOS feel unreliable.

That included:

  • choosing a package set broad enough to be useful but small enough to maintain realistically on macOS
  • narrowing the middleware path so runtime behavior stayed predictable
  • handling Python and Qt GUI dependencies cleanly
  • fixing a Qt5/Qt6 header clash affecting turtlesim
  • patching the rqt path so it used a working PyQt setup on macOS
  • dealing with vendor packages that would otherwise try to download sources during the build
  • bundling Python build and runtime tooling in a reproducible way
  • validating the final result outside the original development workspace

In other words, this was less about running one successful build command and more about taking a fragile source build and turning it into a repeatable installation.

What the Homebrew formula installs

The Homebrew formula is called ros2-kilted-core.

It installs a curated ROS 2 macOS build that includes:

  • the core ROS 2 runtime
  • Fast DDS as the supported default RMW path
  • the main ROS 2 CLI tools
  • turtlesim
  • rqt_graph
  • rqt_console
  • rqt_service_caller
  • ros2 bag
  • the rest of the validated beginner and developer toolchain

It is intentionally not a full “everything in ROS 2” desktop distribution. It is a curated macOS-focused build designed to be practical for tutorials and development.

The main benefit is that users do not need to manually clone the source workspace, run vcs import, assemble the Python build environment, or rediscover the same macOS-specific fixes. Homebrew downloads the packaged source bundle and builds from that.

Why I packaged this as a custom Homebrew tap

I packaged this as a custom Homebrew tap rather than submitting it to homebrew/core.

That was the right fit for a few reasons:

  • it is a curated ROS 2 distribution, not a tiny standalone utility
  • it is specifically tuned for macOS
  • it includes a practical set of development and tutorial tools
  • it is easier to maintain and iterate in a dedicated tap than in the main Homebrew formula collection

That means the package is installable through Homebrew, but maintained in its own GitHub repository.

Installation

The Homebrew tap is here:

nigeldaniels/homebrew-ros2-kilted

Install it with:

brew install nigeldaniels/ros2-kilted/ros2-kilted-core

The package uses ros2-kilted-prefixed commands instead of replacing the global ros2 command, which makes it safer to install alongside other ROS environments.

Why this matters

A lot of developers want to experiment with ROS 2 on macOS, work through the tutorials, or do real development without switching to Linux immediately. The source-build path exists, but it is still rough enough that many people give up before they get to the interesting part.

This project makes that path much more approachable.

Instead of “it should work if everything goes right,” the result is now:

  • a working ROS 2 source build on macOS
  • a verified set of beginner and development tools
  • a reusable Homebrew installation path for other developers

That makes ROS 2 on macOS far more practical than it was before.

Final thoughts

ROS 2 on macOS is still not the smoothest platform story in robotics, but it becomes much more usable once the setup is curated, tested, and packaged properly.

That was the point of this work: get ROS 2 working on macOS, make sure the important tooling actually runs, and package it so other developers can install it without repeating the same setup process by hand.

If this saves someone else from spending a weekend chasing build failures, Python issues, middleware confusion, and Qt breakage, then it was worth doing.

Friends.

Featured

warning: This story is a bit of an omage to hunter S Thompson and gonzo Journalism the story is 96% true but ~ 4% is completely made up.

As I get older I make an effort to spend more time with friends. For the most part this has been a positive experience. Friends unlike family are people you choose and who also choose…. I hope to spend there time with you. I find that for the most part this makes for more enjoyable interactions than you have with close family members and probably most importantly when your tired of your friends you can choose to no longer associate with them. Which I guess is true of family too but I think for most people that decision should not be taken as lightly.

So a few days ago I got a call at 5:00 am from a good friend saying he was in trouble and needed to be picked up from the airport right away. As a good friend might I didnt ask any questions and I dutifully went to pick him up from southwest at the oakland airport. He seemed fine but as we existed the airport he explained to me that he had spent the weekend in las vegas and gotten himself into a fairly impressive spot bit debt and needed to barrow some money in order to pay his mortgage. Mother Fucking friends!. Anyways I explained that I wasn’t comfortable lending him the money and after a few deep breaths he proposed an alternative solution. Because he needed the money NOW ( apparently casino markers are not low interest!) with tears in his eyes he suggested that he would sell me his prized 2013 Porsche 911 for 50% off if I could get him the cash that morning. After pretending to think about this offer for 2 or 3 stop lights and reminding my friend that everything would be ok I took him up on the offer.

After waiting for the bank to open. I was now the proud owner of 911s convertible! and hopefully my friend was a bit closer to being out of the hell he had just created for himself.

this is going to be fun !

Now anyone who knows me knows. That I have been a Porsche fanatic for life. When I was born my dad was the proud owner of a poorly cared for yellow 1974 911 sc that spent at least 60% of its life dumping large amounts of oil onto the ground. I have memories as far back as I can remember of him picking me up from school or taking me to school. I loved sitting in those largely useless back seats and just listening to the engine or sitting in the front seat silently rooting for my dad as he passed various Honda’s and Toyota on the way home I loved that car and when my dad sold it preceding his retirement I cried. To this day I have a poster of a red ( I would never own a red car) 911 on my wall. So making this decision was really a no brainier. The big question was well WHAT NOW?

Out of sheer luck I had arranged to meet an old freind of mine for wine tasting; I want to be clear THIS WAS NOT MY IDEA! I like to drink as much as the next guy but sipping on tiney amounts of over priced grape juice while pontificating over hints of eucalyptus is not normally my idea of a great time. But the chance to drive to Napa in a Porsche was basically irresistible.

So Saturday morning, After losing my weekley basketball game to my most reliable friend. I set off on my trip to Napa. The car is just great and I wish I was a practiced automotive reviewer so I could really describe what its like, but I am not, and at least for this portion of the trip I would be lying if I said it was brilliant because it wasn’t. What would have normally been a 42 minute cruise to ” the wine country” was basically an hour and a half of stop and go traffic. I did take the top down and breath in some of the crisp swamp air that you can find in the low lying valleys of northern California but this was hardly the breath taking mind bending back roads experience that I had dreamed of.

After arriving in Napa while sitting in traffic I decided to try out the cars hands free system and gave my friend Josh a call. He said to meet him at the Winery at the ” barn in the back”.

Now I have to apologize here I didn’t take any pictures of the first winery I always find taking pictures a bit awkward and I will be honest you didn’t miss much. A bunch of old people were gathered in a tent regularly lining up to receive tiny pours of “free” wine. I wondered about this a little bit. Do winerys just regularly give out free samples?… Well no! It turns out that if you agree to buy 4 bottles a month from the winery in question you become a member and you can invite your friends to come and drink for “free” ! Josh, Thanks for being a friend!

I have known Josh sense middle school. We don’t get to see each other much these days. But through copious amounts of facebook stalking I have managed to stay in touch and we have met up in Chicago a few times for dinner and now for wine in Napa!

When we were kids I had a decent businesses burning CDs full of pirated music and selling them at school.

Out of friendship I shared one of my more formative discovery’s with Josh. It was this really interesting little program called Napster. I quickly learned why good businesses have secrets! After teaching josh to How to convert mp3s to Wavs he quickly started his own competing business selling CDs. And because he lived in a nicer neighborhood with broadband my own businesses fell apart as I couldn’t keep up with the number of songs he could download with my shity 56k modem. These days Josh has an engineering degree and a masters in business and he works as a management consultant and has developed the very Type A personality to match.

After about an hour of trying to drink as much free wine as possible, bullshitting, pontificating and humble bragging. I learned that Josh worked at Porsche of all places ( god damn it I still cant win!). I naturally brought up the Napster story, we had a good laugh about it. Then with the grace and confidence of a master orator I gestured as I spoke and knocked over my first glass of red wine which splashed like the brush to the canvas of a great work of art onto josh’s button down shirt. ( insert dramatic pause.)

In my defense I thought the wine went well with the shirt. He took it like champ and we had another good laugh…. Josh I’m sorry, at least consciously it was an accident. I can’t be held responsible for the actions of my subconscious. Like I said Josh works for Porsche and I fallowed him to the next winery.

Thats Josh’s company Tycan up ahead…. 911 > Tycan just saying.

Outside deck of winery.

in a moment of weakness they managed to sell me a bottle of wine for some other friends.

Ok, So I have to admit that tooling around “the wine country” in a couple of Porsche’s was basically a dream come true. Not to mention I got to spill some wine on a good friend and former rival. Thanks Josh, but mostly his wonderful wife Carla for inviting me.

I was going to split this into 2 posts but as usual laziness has won the day. The fallowing weekend. I decided to take car up to Scotts valley to take a peak inside Bruce Canepas shop. He is the largest importer of porsche 959s in the US. I was hoping the car might help me to look like a potential customer instead of the lookeyloo hooligan that I am. It didn’t work. but I got a few pictures inside of Bruce’s massive shop. ( Story continues after the photos)

Before I left home some facebook stalking led me to send a message to my friend Hustle. His real name is Rustle but I call him Hustle.

Rustle Joined my High school during sophomore year. The story goes; After his first year at the local public high school Russell received a D in AP English and his parents assumed he was on drugs. After attempting to show up for his first day of school he was informed that he was no longer enrolled and that he would be attending my private school instead. Hustle did eventually manage to get himself back to public school after only a year but we developed a decent friendship and I made efforts to stay in touch over the years.

Knowing that Rustle lived in Santa Cruz I was hoping he might call me back during my trip to scotts valley and as luck would have it I received the fallowing text ” I’m in Watsonville having beers at the ‘beer mule’ at the moment, but i’ll be back to the ranch mid-afternoon I reckon… ya coming to town?”.

Now the last time I checked with Rustle he had just graduated from UCSD. And he was spending his time surfing and fishing so I was a bit perplexed by the “ranch” but I was looking for any excuse for more driving so I agreed to meet up with him that afternoon. In the mean time I made a quick 60 mile run to what I thought was carmel on highway 1 To pick up a pair of sun glasses. You shouldn’t really drive a 911 without sunglasses but you absolutely cannot show up at the ranch house of some one you haven’t seen for 10+ years without a pair !

30 minutes Later… I walked into the local sun glass hut, grabbed a pair off the rack and spent 10 minutes arguing with the clerk about my need for 2 receipts…I just wanted to make sure I could return these “expertly crafted, polarized, shatterproof, 200 dollar, 7 ounce” pieces of Chinese plastic in the event I lost the primary receipt. As the clerk relented and printed my 2nd receipt I received this text from Russell. “ Would love to have you over for dinner, have an old boat you can crash in ” … Well …. Fuck me running now I have dinner and a place to stay! now this is what friends are for. I flogged the 911 back up the 1 to some where in the santacruze mountains. These are the kinds of back roads that motoring dream are made of. After about 25 minutes and 3-4 near death experiences. I Entered what appeared to be a residential neighborhood.

The very first house to my left was a large white sort of Spanish style mansion. Now I am thinking to myself ” this is not really very ranch like but hell I’m game!” This wasn’t the house so I kept driving. The next house was another large Spanish style house but this time Cannery yellow with colored tile. This was also not the house. But this was the end of the road. So I was a bit confused and out of cell phone range. As I went back down the hill. I noticed a boat and a large ford f250 parked in front of a wooden fence about 6ft high. Close enough to a ranch for me and I parked outside.

I hadn’t seen Hustle in years and between seeing him and his compound for the first time I was a bit overwhelmed. At an undisclosed location in the crustacean mountains my high school friend ordered a shipping container from the port of oakland had it transported ~ 70 miles. He then modified the container. Gave it running water, a full complement of appliances and a bathroom complete with a Tub, shower and urinal. I wish I had taken more pictures of the interior But I am always hesitant to take pictures inside peoples homes.

In addition to his container based home. He raises sheep, chickens and naturally grows a small amount of marijuana … this is northern California after all! At this point I was tired. excited to finally see my old friend and a bit beat from all the driving. Russell offered me a variety of his locally grown products and we relaxed and reminisced about times gone by. As the night went on his wife returned home and they began to prepare dinner. Now, at my house. Things get microwaved and or boiled. I pride my self in both my nuking and water heating abilities. This was not the case at the house of Hustle. For dinner Mrs Hustle made from scratch Duck pot stickers which were amazing accompanied by my choice or chardene or Coors light. After Verifying that she was in fact Mrs Hustle and not a kidnapping victim. I ate a brilliant dinner by there indoor and outdoor fireplaces places. Fallowed by the hand rolled bounties of there harvest. At this point I took a quick nap on there couch. A while later I was informed that Russel had created a bed for me in the boat ( pictured above) as promised. He used an electric blanket to make sure things were warm enough and I was surprised to find out it was actually quite comfortable. At about 1am I woke up coughing. I have terrible allergies and the combination of wood fire and sleeping in a boat did not agree with me. I got up, peed over the side of the boat , puked a little bit ( caused by the coughing) and went back to sleep. I guess some where around 3am I woke up again peed and puked over the side and decided that this was probably not going to work. I went and grabbed my covers from the cabin climbed into the 911 and found restful sleep after I turned on the seat heaters.

I never imagined I would sleep in a 911 but that night I did!

Surprisingly I slept well. Some where around 6:30am Mrs Hustle headed off for work. I tried to say good morning but I don’t think she noticed me in the car.

I went back sleep and some where Around 9 am Russel woke me up and informed me that he needed to go do some work on his other boat down at the santacruze harbor. After we gathered a sander, beer and some horticulture I fallowed the f250 to the local hardware store and then to the harbor. Now obviously hustle has some home court advantage and I was still a bit groggy but I just barely managed to keep up with his f250 in the 911 through the back roads of Santa Cruze.

The SC harbor is gorgeous and this day was no exception.

SC harbor.

When we arrived we went down to the boat and Hustle threw on some Bob Marley played back through the hidden sound system on his boat. He proceeded to start sanding and painting and I mostly just chilled had another Coors light and shot the shit about former teachers and friends from High School. 3 are dead the rest are happily married and enjoying there lives.

Some time around 11:30 I started to get hungry and I offered to take Russel out to eat for lunch. He informed me that he couldn’t because he had prepared a lunch for Mrs hustle who was going to meet us at noon during her lunch break….. no word on my lunch..

I checked with Mrs hustle again and she assured me that she was not infact suffering from Stockholm syndrome. The rest of my time in Hustle land is not particularly entertaining but I want to take a moment to thank the Hustles for the hospitality and quickly acknowledge that my friend Rustle is winning at life!

Time to go home. So I fire up the 911 and get back on the 1 headed toward the san mateo bridge. If you have not had a chance to go for a drive on highway 1 I highly recommend it it is a long coastal highway with incredible views, very few police officers and more than enough curves to put the life of any Porsche driving douche bag at risk.

After reaching the 92 I was tired and ready to go home when I got an idea. I called my friend T ( mostly just to test the hands free feature of the car ) And asked if I could come by to drop off the bottle of wine I had picked up during the prior week. T lives in walnut creek with her husband and 2 children we have been friends for a long time and she seemed happy that I wanted to visit. I hung up the phone and and proceeded to sit in bumper to bumper traffic for 2hrs.

Arriving in Ts quiet and fancy neighborhood I promptly reved the the engine to 7300 rpm and was soundly ignored by ~ every thing. Entering el casa de T&A ( yes those are there initials) is always a great time they like to make stuff so often you get to see some new cool furniture they have made or some remodeling project in progress. But tonight I walked into a large number of children’s toys and the sounds of people trying to convince a 2 year old to eat broccoli. I walked in, Told T happy birthday and handed her a bottle of wine. I attempted to help feed a 2 year old for roughly 3 seconds at which point her husband solved the problem by adding a genrous amount of ranch dressing to the broccoli. After the 2 year old seemed satified I watched him laugh and run around in ciricles while screaming for 30 minutes straight at which point T said ” its bed time” At this point I was happy to open the bottle of wine and sit on the couch and wait for parents to do what ever they do during bed time. But I was infromed that I was going to help put people to sleep.

I Mostly laid on the floor and watched T read a book to her son.

I realize this story got a little boring but I value my friends and all the exsperiances we have had over the years and hopefully the ones we will have in the future.

As for the 911 I had to get rid of it for financial reasons and I miss it every day.

A new adventure

Featured

My friend L

So after a long illness. that can only be described as a break from reality and a ” feeling that everything was dead” My good friend and former roommate L helped me to land a new job. Subsequently Saving my life and preventing me from becoming homeless.

Lets talk about L; I met L some time around 2017 while working for stereotypical San Francisco startup. You know the kind, a few smart engineers/phds and myself. working on a machine learning based signals intelligence cloud based platform utilizing deep neural networks to change the world by helping sales people sell things.

L was a perfect match fresh out of one of the standard silicon valley feeder schools. young Caucasian male, slightly emaciated. round glasses, tight jeans and appropriately naive and an occupant of what I have previously referred to as programmer pods.

est. 2010 a programmer pod is a questionable interpretation of mid century modern architecture, intended largely for the purpose of separating tech company employees from there wallets and the masses.

Getting to know L over the next 3 years I found that he was a little bit different. He didn’t really like to do much work ( I want to be clear he is an incredibly talented programmer) he enjoyed spending the vast majority of his time making coffee, reading Tolstoy and self diagnosing himself with an abundance of questionable medical conditions. As you might expect L was eventually let go for not doing much work. The company was sold to a larger more well funded cloud based communications platform built on deep neural networks to ….. help sales people sell things…

And I lost my mind.

Anyways skipping ahead to today. L called and asked if I wanted to go out for a drive. In standard L fashion he showed up roughly 3 hrs late after I had already eaten and asked if I wanted to grab dinner. I didn’t . So on a whim we got on the high way and started driving.we stayed on the highway while chatting about largely nothing and as we ran into the Richmond San Rafel bridge L instructed me to get off the highway so we could avoid paying the toll and ending up at San Quinton.

point molate is dark, very dark and a largely abandoned former winery, military base and abandoned industrial area. It has no street lights and very few people at night time . We drove around. looking for a place to stop to sit around maybe look look at the bay and the , kvetch and head off to find something to eat.

Instead I found myself just driving further and further from the highway on deteriorating roads. After a few miles of driving through an abandoned former military housing some interesting old warehouses and a lot of barbed wire fences. We ran into a sign resembling the one bellow. at the base of a steep hill.

I wish I would have taken more pictures.

At the urging of L we continued to drive over the hill onto the other side of point molate. The drive was interesting. But unfortunately as we continued to drive we started to see strange black stars nailed to the trees. maybe one suspiciously occult black star every 3000 feet.

it was dark and I will admit to being a little worried. L insisted we keep driving. As we started to reach the peak of the the hill, I began to realize we had been driving for maybe 40 minutes on a twisty dilapidated road decorated with pentagrams in the middle of the night. and I got a little worried. As we began our decent. L ( not a bay area native) started to bring up the fact that there are known to be a few cults in the bay area,…and wondered allowed if the black stars were in any way related. Naturally around the next several corners we could see that we were headed towards a small minimally lit marina with what appeared to be small shacks and house boats… the perfect place for a black star idolizing and hopefully friendly Satan worshiping cult. Just as we arrived at the bottom of the hill we saw a sign labeled with the words ” black star” and a small goat with only a passing similarity to this guy.

about 1000 feet later we ran into a pen of live goats and at this point. I could only hope that the occupants of the animal sacrificing satan worshiping cult we had discovered at the end of a private road on an abandoned military base were friendly. As we passed the live goats. We found ourselves in a dimly lit parking lot with some rusty light heavy industrial equipment, and two empty mid 90s economy cars. The parking lot was separated from the marina and a another urt/shack by small embankment topped by a set of abandoned railroad tracks. At this point I parked the car so we could get out and stretch our legs smoke a ciggerte and decide what to do next.

Out of an abundance of caution and fear of whoever was living in the marina. I decided we should walk down the rail road tracks in the opposite direction of the potentially inhabited part of the marina. In the dark with really no good idea of where we were headed. On this side of point late you can see out into the bay but there is no lighting and I was sort of disappointed that there was nothing interesting to see. And then… we ran into this.

Is this just not a digital signal?

Featured

I set out wanting to capture the signal transmitted from my gate opener (pictured at  the very bottom) but the results are confusing so I am attempting to document what I did.

The first thing I I did was build a basic receiver in gnu radio to do the capturing shown here.

testfile

osmocom source: This an interface to our software defined radio (hardware)

  • sample rate: 16M  ( our hardware can effectively sample between 8 million IQ samples per second and 20M because of my initially confusing results I upped it to 16M hoping it was a resolution problem.
  • Ch0 : frequency: ( center frequency ):  300M  300mhz
  • Ch0: RF gain: 0 this this controls a rx amp built into our hardware)

QT GUI sink:  ( just a way to out put our signal in the frequency domain )frequency_domain

the brown line is peak hold using this I estimated the transmit frequency to be ~ 300.2 mhz the blue spike at 300 is a gnu radio side effect which occurs at the center frequency.

The next step I assumed would be to attempt to “tune” and demodulate the signal so I built a another flowgraph for that:reciver

 

  • File source: ( just our IQ samples stored in a file)
  • Throttle: This prevents gnu radio from sending data faster than 16Mps
  • QT GUI sink : outputs the previous graph
  • Frequency Xlating FIR FILTER ( was supposed to accomplish the fallowing) 
    • tune to our signal by downshifting captured spectrum by the difference between the center frequency and the tuning frequency
    • low pass filter the shifted signal with a cutoff of 50kHz and a transition width of 1Khz
    • decimate the outgoing data stream down to our working_samp_rate of 400kHz
    • XFF details ( how we do the above with this block)
      • Decimation:  int(samp_rate/working_samp_rate)
      • Taps: firdes.low_pass(1, samp_rate, filter_cutoff , filter_transition)
      • Center Frequency : freq-center_freq

Demodulation:( maybe this is where I went wrong?) : I am only really familiar with on off keying so  I use the so called “complex to magic” block to provide a high constant value when the carrier is present and a low ~constant value when the carrier is absent. 

The fallowing shows but the input provided to complex to mag and the output afterwards: 

final

So Looking at things in the time dimension demodulated or not I don’t see anything I would recognize as digital maybe a nice square wav? So I suspect that at least 1 of the fallowing things are true.

  1. My gate opener is broken
  2. my gate opener is not digital
  3. my gate opener does not use on off keying?
  4. Something else?

IMG_20180323_080512

REWORK the review

Featured

rework

A good friend recommended this book he’s sort of new to the working world so I guess he is reading a lot of stuff of this nature. The book is by the guys at 37signals; they are a web design firm who is well known for creating Basecamp, Backpack and campfire and most famously ruby on rails.  I wasn’t actually expecting a lot from this book, I am not into “design” and I have a deep deep hatred for ruby but I have been known to read a business or 2.

REWORK is marketed  as a sort of ‘everything you know is wrong’ Business book with the back cover reading “Most business books give you the same old advice: Write a business plan, study the competition, seek investors, yadda yadda. If you’re looking for a book like that, put this one back on the shelf.” and  “What you really need to do is stop talking and start working. This book shows you the way. You’ll learn how to be more productive, how to get exposure without breaking the bank, and tons more counter intuitive ideas that will inspire and provoke you.”

The book starts off with a narrative about starting your own business and introducing the authors own experiences. Their point of view is clear; anyone can start a business , it doesn’t take a lot of time or money thanks to modern technology. The authors go on to use their own experience to support their claims in a compelling manner , if you’re not familiar with signals they are a small company with under 20 employees who mostly work from home but do a lot of great work. The company has made millions of dollars  the authors use example from this experience to make the argument that you don’t have to have a giant company with lots of funding, or a huge number of employees or fancy offices to have a business,  you just need to get started and make things people want to use. For the most part this argument is well supported and I think it provides useful perspective in a time where many people are trying to raise money for their next startup and go public.

The book also covers topics that are useful even if you don’t wish to start a business and  think this is where the book really shines.Topics include workaholisum , meetings, marketing and staying late. REWORK makes an effort to deconstruct the uselessness of all of them in a both informative and entertaining fashion.

There are a few examples that stand out. The first that comes to mind is the topic of staying late anyone who has worked at a startup knows about the “virtues of working late”, the idea being the more hours you spend working and the less you sleep the more you you are obviously getting done and as such The standard working Hours for a startup are from 9am – 7 pm or later. Now I know in the US we all love work . But the book points out that most of the long hrs we do are spent  not working at all , just hanging out in the office, talking to coworkers and if you work in silicon valley playing a couple of games of table tennis. The reality is a lot of work can be done in 8 hrs if you use your time wisely and REWORK does a great job illustrating this. Another topic The book dives into is “marketing” now I expected the authors to throw out the concept of marketing entirely, but surprisingly the authors go on to explain that marketing is not about add buys or “ campaigns” but rather everything a company does from the quality of its products to its most basic interactions with is customers is a form of marketing and should be treated that way. They also offer other lower budget marketing ideas like blogs and providing tutorials for customers that might help to provider a deeper connection with customers that I certainly had not considered before.

I could go on and on about the various topics but honestly REWORK is not that long and I think almost everyone should read it. I recommend this book to anyone who is interested in doing great things and sharing them with the world. I think the marketing pitch is wrong, REWORK should really be marketed as more of a personal development or career development book,  It’s a short and easy read so  you shouldn’t have many excuses not to read it.

House of cards returns for season 2

Featured

Image

So as of midnight this morning ( thats always a funny phrase) house of cards is back ( and the torrent is available). I had mixed reactions to the first season I have always sort of felt that kevin spacey played a better supporting actor than a lead but I enjoyed it and I especially enjoyed not having to wait for 1 episode per week, so season 2 can be found at

http://torcache.net/torrent/C5E7E5D8EE41633BC86C67C85F6850658982C843.torrent?title=%5Bkickass.to%5Dhouse.of.cards.2014.s02.season.2.complete.720p.x264.aac

More Adventures in San Leandro

Featured

Image

One of the east bay’s best kept secrets

Previously I wrote a bit about why I think San Leandro is an awesome, but under appreciated city to live in. So today while I was out on my morning walk I decided to take some pictures

The things I like about san leandro are as fallows:

  • Its small quiet and safe – the population is still under 100k people
  • has a nice marina
  • BART – if you live in the bay area more than 10 minutes from bart you live in the wrong place !
  • Flat – This is big for me I like to go on long walks but walking up and down hills can really suck the fun out of it , Its nice to be able to walk to the  store.
  • its within 30 minutes of SF by bart or car

So here are the pics:

Image

Image

Image

Image

Image

ImageImage

Super Freakonomics, the review

Featured

Image

This is my first attempt at a book review, I have a feeling that as far as book reviews go this won’t be very good, but because  I have a narcissistic need to show off that I do in fact read books, I am writing it anyways. Please be warned my last attempt at a book review was during my junior  year of high school where  I shamelessly plagiarized the the character summaries  from the cliff notes ( it may have been spark notes, I can’t remember) of Moby Dick to prove the thesis that characters of Moby Dick were what made the story.

Super Freakonomics is the squeal to the Best selling Freakonomics by the economist Steven Levitt and that other guy who I can only assume is responsible for creating lighthearted narrative that made the first Freakonomicsthe easy to consume best seller that it was and is.

The Duo return to action in this version with a clear goal of being much more controversial. While the first outing of Freakonomics addresses issues including why drug dealers often live with there mothers , “which is more dangerous  a gun of a swimming pool” and ” what schoolteachers and sumo wrestlers have in common”  and provides ” surprising answers to these question. The second book takes on the likes of  Global warming, prostitution and the spared of AIDS. Another major difference from the first book is that this version states from the beginning that its goals are to ” begin a dialog” which is certainly an interesting take from a couple of guys who claim to use the rigorous  analysis of “data” ( they really like that word ) to find truth. “Truth” rarely requires a dialog… just saying.

So how is the book?  well the narrative is still very enjoyable and lighthearted and I think any one over  12 or 13 years old will find this an easy read. The Analysis is interesting and as you would expect from a book called freakanomics the conclusions reached by the authors are certainly surprising or at least they will be to most people . The downside to this version of freakanomics lies in the authors far more liberal use of data and sources. In the first book Levitt relies heavily on statistics and well accepted studies to support his ideas and reach logical conclusions. In this version the authors rely  much more on individuals and single sources to make arguments as apposed to reaching logical conclusions which is a bit of a shame as this sort of hurts the original premise that a ruthlessly analytical approach  to the world can be used to find truth.

I would certainly recommend this book for it’s entertainment value  its well written and filled with great humor. Unfortunately unlike the original this book seems to use the sort of shock value tactics that fill the pages and channels of much of modern media which is sad because the book would have sold fine on the back of the original and it does some of the content a disservice as some of the arguments come off as political nonsense. when in fact many of them are sound.

I won’t ever recommend that any one buy anything but I enjoyed this book and its  a shame that it didn’t re-inforce the use of ruthless analysis and and anti politisisum that the world so very deeply needs

The Company I always wanted

I think people misunderstand what I mean when I say I want to build a startup.

They hear startup and think billion dollar empire, venture capital, hustle culture, some guy on LinkedIn saying “we’re changing the world” because he made a dashboard for invoices or whatever.

And sure, getting rich would be nice. I am not going to pretend money is bad. Money solves real problems. Money buys freedom. Money keeps the lights on.

But that was never really the dream.

The dream was way simpler than that.

I wanted enough money to pay the bills, rent an office, buy some food, keep the computers on, and hack with my friends.

That’s it.

A room. Some desks. Some snacks. Good internet. Maybe a whiteboard. Maybe too many monitors. People arguing about systems and programming languages and product ideas. Somebody building something weird in the corner. Somebody else reading tech news for fun. Somebody pushing a deploy. Somebody saying “wait, what if we just…” and then everyone loses two hours chasing the idea because it might actually work.

That’s the part I always wanted.

Not the empire. Not the press release. Not the fake founder mythology. Not the “we are disrupting X” nonsense.

I wanted the workshop.

The funny thing is my friends already do this. They already build things for fun. They already read about technology for fun. They already have opinions about databases and operating systems and AI and networks and whatever else. They already spend their free time doing the thing most companies have to pay people to pretend to care about.

So part of me is like: why couldn’t we build a company out of that?

Not a company where the joy gets crushed under meetings and process and status games. Not a company where snacks replace compensation or where “we’re a family” means “please work nights for free.”

I mean a real company.

One that makes enough money that people can show up and be paid like adults.

One that has customers, and bills, and boring operational stuff handled, but where the center of gravity is still making things.

A company where the work still feels alive.

I think when we were younger this was easier to understand. If somebody made something on a computer, that was cool. A website, a script, a game, a server doing something weird, whatever. The first reaction was not a policy analysis. It was “whoa, you made that?”

Now everything gets filtered through takes.

Is it good for society? Is it cringe? Is it a startup grift? Is it AI slop? Is it capitalism? Is it replacing someone? Is it going to become a monopoly someday?

Some of those are fair questions. But man, if that is always the first reaction, it kills something.

There used to be a basic joy in making the computer do a thing. I still have that. I do not think I ever lost it.

And I guess I am realizing that the company I always wanted was not really about winning capitalism. It was about making a place where that joy could survive adulthood.

Because adulthood changes things. People have partners, kids, mortgages, health problems, parents getting older, responsibilities. Sitting in a room with friends, free food, and computers does not sound as magical to everyone as it once did. To some people it sounds like one more obligation.

I get that.

So maybe the dream has to grow up too.

Not a hacker house. Not a grind cave. Not “sleep under your desk until we exit.”

More like a sane little lab.

A software shop with a soul.

A place where people can come in, do good work, make real things, get paid, eat lunch, laugh, argue about dumb technical details, and then go home without feeling like the company owns them.

That sounds modest compared to the billion dollar startup dream, but to me it feels bigger in the ways that matter.

Because the point was never just money.

The point was: can we make our natural behavior economically sustainable?

Can the thing we already love doing become the thing that pays for the room?

Can we build something useful enough that it buys us more time to build more things?

That is the company I always wanted.

Not a unicorn.

A workshop with revenue.

A place where the fridge is full, the servers are running, the work is interesting, and the people in the room still think making stuff on computers is cool.

All your CDN are belong to US

Underminr Detection: DNS Says One Thing, TLS Says Another

The detection story for Underminr is actually pretty simple, which is why it is so annoying.

You are not looking for some magic evil packet. You are looking for the layers of the connection telling different stories.

Normal web traffic looks something like this:

DNS: I want goodsite.com
DNS answer: goodsite.com is at 104.x.x.x
TLS: I am connecting to 104.x.x.x
SNI: goodsite.com
HTTP Host: goodsite.com

Everything lines up. Boring. Fine.

Underminr-style traffic looks more like this:

DNS: I want goodsite.com
DNS answer: goodsite.com is at 104.x.x.x
TLS: I am connecting to 104.x.x.x
SNI: sketchy-domain.ai
HTTP Host: sketchy-domain.ai

That is the trick.

The machine uses an allowed domain to get a perfectly valid CDN IP, then reuses that IP to talk to some other tenant living behind the same CDN.

DNSSEC does not really save you here, because the DNS answer can be totally legitimate. DNSSEC can prove that the DNS answer was authentic. Great. Congratulations. The lie happens later, at the TLS / HTTP / CDN routing layer.

So the detector has to correlate things across layers:

What DNS name did this endpoint ask for?
What IP did DNS return?
What IP did the endpoint connect to?
What SNI did it present?
What HTTP Host header did it use?
Did that hostname ever get resolved normally?

In other words, you are looking for this mismatch:

Resolved: harmless-site.com -> CDN edge IP
Connected to: CDN edge IP
Claimed SNI: evil-site.com

That is the “oh come on” moment.

The really cursed version is when the attacker splits it into steps. First they make a clean-looking connection to the allowed domain, then they come back to the same CDN edge IP and swap the SNI / Host header to the real target.

So detection has to remember recent DNS answers and recent CDN connections per machine. It is not enough to look at one packet in isolation.

The direct-to-IP version is even more annoying because there may be no DNS lookup for the bad domain at all. Then the question becomes:

Why is this machine connecting directly to a shared CDN IP
while presenting an SNI / Host name that it never resolved?

That is suspicious as hell.

And with ECH, because of course we needed one more layer of pain, the real SNI can be encrypted. At that point you need endpoint visibility, controlled DNS, policy around HTTPS / SVCB records, or some way to block or strip ECH in managed environments.

So the whole thing boils down to this:

DNS says one thing. TLS / HTTP says another. The CDN accepts both because shared edge infrastructure is a haunted house.

Honestly, it feels like Dan Kaminsky may have faked his own death and come back on the dark side.

Obviously joking. Mostly.

But this is exactly the kind of DNS-adjacent, “everything technically works as designed and that is the problem” nonsense that makes the internet beautiful and horrible at the same time.

The practical detection rule is basically:

For each endpoint:
remember recent DNS answers:
allowed-domain.com -> CDN_IP
watch outbound TLS / HTTP:
endpoint -> CDN_IP:443
SNI / Host = some-other-domain.com
alert if:
the CDN IP came from a recent allowed DNS answer
but the SNI / Host does not match that DNS name
and the SNI / Host name was not separately resolved
in a normal allowed way

That is Underminr detection.

Not “block the IP,” because the IP is probably Cloudflare, Akamai, Fastly, or some other giant shared CDN edge.

Not “DNSSEC fixes it,” because DNSSEC only proves the DNS answer was real.

The actual problem is that the trust decision was made on one name, and the connection was later used for another name.

It is a cross-layer trust bug.

The internet has a lot of those.

Because apparently we enjoy pain.

Thoughts on the Mistakes of the Social Web

The internet was social before the social web. That part gets forgotten. People talked on IRC, forums, mailing lists, Usenet, AIM, Discord-style rooms, and all kinds of weird little places. The difference was that those places had context. You were not just “an account.” You were a person in a room, with some history, some reputation, and some reason for being there.

If you linked to your own thing in one of those spaces, people usually did not lose their minds as long as it was relevant. The question was not, “Did you make this?” The question was, “Is this useful here?” That is a much healthier standard. Sometimes the best link in the conversation is your own link because you are the person who wrote the thing, built the thing, documented the thing, or found the thing.

The social web broke that in a strange way. It created a huge opening for credibility fraud. Suddenly everyone could perform expertise, manufacture popularity, juice engagement, buy followers, write in brand voice, growth-hack sincerity, and pretend to be a participant while actually acting like a little attention-extraction machine. The feed turned normal human sharing into a suspicious transaction.

So now we live in this dumb world where links are both the blood vessels of the web and somehow treated like contraband. A web with no links is barely the web. It is just a set of private malls with recommendation engines and security guards. “Do not link to your own stuff” sounds noble until you realize it mostly helps people who are already big enough that other people link to them automatically.

PageRank made sense in a world where someone else might find your weird little page and link to it from their weird little page. That was the old bargain: publish something good, and the graph of the web slowly discovers it. But a lot of that middle layer is gone or weakened. Personal sites, blogrolls, directories, small forums, and independent linking culture got paved over by platforms. Now the system still wants backlinks, but the places where people actually gather often punish the behavior needed to create them.

That is one of the great little ironies of the modern web. The machine wants evidence that the world cares, but the world has been trained to treat public linking as spam unless it comes from someone already blessed by the machine. Nice little closed loop there. Very elegant. Completely cursed.

There is an important exception here: I am much less hostile to things like Bluesky, Mastodon, ActivityPub, AT Protocol, and other systems that at least try to make the social layer protocol-shaped instead of purely platform-shaped. That matters. Federation is not magic fairy dust, and protocol people can still be annoying in the very special way protocol people are annoying, but the architecture is pointed in a better direction.

A federated or protocol-based social system is not the same animal as a giant closed platform casino. If identity, distribution, clients, moderation, and hosting can be separated, then users are not trapped in quite the same way. The conversation can move. The client can change. The server can change. Communities can set local norms. The graph is not just locked in some corporate basement next to the engagement-optimization goblin.

That does not make every federated system good. It does not mean Bsky or Mastodon or anything else automatically solves the human problems. People can bring status games, mobs, spam, and weird little dominance rituals anywhere. Give humans a protocol and we will eventually find a way to argue about the chairs. But protocol-based social is at least trying to preserve some of what made the internet good: links, portability, interoperability, local context, and the possibility that no single company gets to be the landlord of human conversation.

So the problem is not “people talking online.” That would be an insane take. The internet is one of the best machines humans ever made for finding each other. The problem is the platform-owned social web: permanent, indexed, engagement-maximized, reputation-scored, and monetized within an inch of its life.

I understand why everyone built social features. In the pre-AI era, if you wanted a big site, users were the cheapest way to get content. Users wrote the posts, uploaded the photos, made the comments, tagged the pages, reviewed the restaurants, liked the posts, ranked the content, argued with each other, moderated each other, and generated the graph. The whole thing rode on the backs of users because paying people to produce and organize all that stuff was expensive as hell.

But that bargain had a cost. The user did not just contribute to the product. The user became the product, the inventory, the moderation problem, the credibility signal, and eventually the unpaid little hamster powering the engagement wheel.

And then because everything was public, permanent, indexed, and monetized, normal social behavior got weird. A casual thought became content. A disagreement became a searchable artifact. A joke became evidence. A person became a profile. A community became a growth channel. Human interaction got shrink-wrapped, barcoded, and stacked on a pallet in the warehouse of the feed.

I do think the social web has value. I am not saying people should stop talking online. But social interaction is often temporary, contextual, and messy. The web is durable, searchable, and decontextualized. Those are not naturally the same thing.

That mismatch is where a lot of the damage came from. We took ephemeral human behavior and made it permanent infrastructure. We took conversations that should have lived in rooms and put them on billboards. Then we acted surprised when everyone got performative, defensive, spammy, paranoid, or insane.

Maybe the healthier split is simple: let the web be good at durable reference, and let social be good at human context. Links, pages, sources, guides, documents, indexes — those belong on the web. Jokes, arguments, half-formed thoughts, “you had to be there” moments, and random social chatter probably belong somewhere smaller, softer, more local, or at least more portable than the giant engagement platforms.

AI changes the economics here. It may now be possible to build useful information systems without forcing users to generate the entire content layer. Machines can parse public sources, organize messy information, summarize, classify, dedupe, and turn scattered material into something usable. Humans can review and steer instead of being mined for every post, like, comment, and scrap of attention.

That does not mean AI slop should replace human culture. Please, God, no. The last thing we need is the web turning into a haunted vending machine full of synthetic LinkedIn posts. But it does mean we may not need to make every useful site into a little social casino anymore.

The mistake of the social web was not that people talked to each other. Talking is good. The mistake was turning talk into permanent content, content into ranking fuel, ranking into status, status into credibility, and credibility into a fraud market.

The web should have links. People should be allowed to point at things. Making something useful and saying “here, I made this” should not automatically be treated like some moral failure. That is how the web breathes.

A link-hostile web is an anti-web. It is a graph afraid of its own edges.

But a protocol-shaped social web? A federated web? A web where people can talk without every conversation becoming feed chum for the same giant machines?

That might be worth saving.

A Love Letter to San Leandro

San Leandro is the kind of city that reveals itself slowly. https://sanleandrodaily.com

It does not usually announce itself with the same volume as some of its neighbors. It does not have to. Its character lives in smaller, steadier things: a public library that matters, neighborhoods that still feel like neighborhoods, local restaurants people genuinely return to, parks that get used, and a shoreline that can change the tone of an entire day.

That quiet substance is part of why I keep coming back to it.

San Leandro feels practical in the best sense of the word. It feels lived in. It feels useful. It is a place where civic infrastructure still matters, where community programming is not an afterthought, and where small businesses still help define the texture of daily life. There is a kind of dignity in that. A city does not need to perform for the outside world to be worth loving.

From a technical point of view, San Leandro is more interesting than people sometimes realize. It has real industrial history, a meaningful business base, and even its own unusual infrastructure story through Lit San Leandro and the city’s long-running interest in connectivity and modern economic development. That combination of public life, local identity, and technical ambition is rare. It is one of the reasons building software for this city feels so worthwhile.

That is also the spirit behind San Leandro Daily.

The goal is not to build a generic city app and stamp a local name on it. The goal is to build something that respects the actual rhythms of San Leandro: library events, public meetings, neighborhood happenings, family programs, local deals, and the many small signals that tell you a city is alive if you are paying attention. Under the hood, the work is fairly straightforward on purpose: a FastAPI backend, PostgreSQL for content, and a cross-platform mobile stack that keeps the product maintainable. The technology matters, but only because it helps the city show up more clearly.

That is the heart of it for me. San Leandro deserves clear attention. It deserves tools that make it easier to see what is already here.

Some cities demand to be noticed. San Leandro rewards noticing.

Please send good vibes positive thoughts and prayers to my friend Desta in Kenya

Desta and I have been close friends for a few years now. Unfortunately, she is currently very sick with lung cancer. The world can be a very unfair place. She graduated #1 in her nursing school class with near-perfect test scores, all while struggling through abject poverty. In the middle of her studies, her mother died, and she took care of — and continues to take care of — her two younger siblings.

I know she will not give up, but she could certainly use all the positive thoughts she can get. So I am asking all my readers around the world to take one small moment and mentally wish her well.

Thank you all.

LessVibes release

fuck the claw

lessvibes

lessvibes is an early JetBrains plugin project aimed at a pretty specific problem in the AI coding era: code can appear in your project faster than you can really read it.

The point of lessvibes is not to block AI tools or shame anyone for using them. The point is to make AI-assisted coding more visible and more hands-on. The plugin is meant to notice when a burst of code lands, track whether the affected files were actually opened, and help the developer step through a likely code path instead of just trusting the vibes and moving on.

In its current form, the project is focused on PyCharm first. The rough direction is:

  • track likely assisted or bulk-generated changes
  • show which files were touched
  • show which of those files were never opened
  • show which files were opened but never really edited
  • give the user a way to open a bounded left-to-right code-flow view

The project lives here:

https://github.com/nigeldaniels/lessvibes

Installing It In PyCharm

Right now, the simplest way to install lessvibes is from a locally built plugin zip.

  1. Clone the repo.
  2. From the project root, run:
./gradlew buildPlugin
  1. That produces a plugin archive at:
build/distributions/lessvibes-0.1.0.zip
  1. In PyCharm, open:
Settings / Preferences -> Plugins -> gear icon -> Install Plugin from Disk...
  1. Select the generated zip file.
  2. Restart the IDE if PyCharm asks.

After restart, the plugin should appear as the lessvibes tool window.

Installing It In Similar JetBrains IDEs

Because lessvibes is a JetBrains plugin, it may also load in similar IntelliJ-platform IDEs. That said, this project is being built with PyCharm in mind first, so anything outside PyCharm should be treated as experimental for now.

The install flow is basically the same:

  1. Build the plugin zip with ./gradlew buildPlugin
  2. Open the target JetBrains IDE
  3. Use Install Plugin from Disk...
  4. Pick the generated zip
  5. Restart the IDE

Important Warning

This project is still very much a work in progress.

It is mostly untested, the heuristics are still rough, and the code-flow logic is best-effort rather than guaranteed runtime truth. If you try it today, you should expect edges, gaps, and wrong guesses.

That said, the idea is real, the first plugin scaffold exists, and contributions are absolutely welcome.

If this problem sounds interesting to you, open an issue, send a PR, or just poke around the code here:

https://github.com/nigeldaniels/lessvibes

LessVibes: Because apparently I needed to vibe code a plugin to help me vibe code less

lessvibes: a plugin for making sure I do not become a fucking moron any faster than time already requires

I have been thinking a lot about AI coding tools lately.

Not in the fake moral-panic way. Not in the “real programmers type every character by hand in a dark room lit only by vim” way. I use the tools. The tools are useful. Anyone pretending otherwise is either lying or writing Java for fun.

The problem is not that AI coding tools are bad.

The problem is that they are too convenient in exactly the wrong place.

They make it dangerously easy to end up with code in your repo that you did not really read, did not really trace, and do not really understand. A giant slab of output appears, you skim it, rename two variables, maybe run the tests, and now congratulations: you are responsible for a system you technically approved but do not actually know.

This seems bad.

So I have been working on a plugin idea called lessvibes.

The basic goal is simple: I want something in the editor that pushes back, at least a little, against the smooth-brained workflow of sitting there like a fucking lemming waiting to click Accept.

Because let’s be honest, something has to.

If nothing pushes back on that loop, a lot of us are going to get dumber. Not overnight. Not in some dramatic sci-fi way. Just slowly, comfortably, one magical completion at a time, until our main skill is recognizing when the machine produced something that looks plausible.

That is not a great direction for software development, or for my own brain, it never got much exercise to begin with.

What lessvibes is supposed to do

The core idea behind lessvibes is that the IDE should notice when a coding session has turned into something passive.

Not “evil.” Not “fraudulent.” Just passive.

If a giant block of code lands in the editor faster than any human would normally type it, that should be treated as a moment worth paying attention to. Not because generated code is automatically wrong, but because that is the exact moment where understanding tends to quietly fall off a cliff.

So the plugin would try to estimate how a session is actually happening.

Not with fake certainty. Not with some creepy fantasy that it can prove who “really authored” every line. More like a transparent, best-effort read based on signals such as:

  • manual typing and editing
  • paste events and bulk insertions
  • accepted AI completions when the IDE exposes them
  • edits that arrive much faster than a human would normally type
  • file opens, tab focus, scrolling, dwell time, follow-up edits
  • whether the files that got changed were ever actually opened and manually touched afterward

The point is not to solve philosophy.

The point is to notice when the workflow has quietly become:

accept output, skim it badly, and emotionally hope for the best

That is a real workflow now. A lot of people are doing it. Some of them are doing it successfully, which honestly makes it even more dangerous.

The part I actually care about

The feature I like most is the code-flow view.

If the plugin decides a change was probably AI-generated, heavily pasted, or otherwise suspiciously vibey, it should open a bounded left-to-right execution path through the code.

Up to five panes.

The leftmost pane starts at the main entry point. Then each pane to the right shows the next relevant file in the flow. Not the whole dependency graph. Not one of those giant architecture diagrams that looks like a serial killer’s wall. Just the important path, bounded on purpose, so a normal human can actually follow it.

That boundedness matters.

A lot of developer tools confuse “more complete” with “more useful.” I do not want a giant spiderweb of boxes and arrows that makes me want to close my laptop and go lie on the floor. I want something that says:

hey idiot, it starts here, then goes here, then here, then here. maybe read these before you pretend you understand the feature

That is the product.

And if the project uses containers, the leftmost pane should be split horizontally. Top half: the main code entry point. Bottom half: the Dockerfile or Compose file. Because a surprising amount of confusion in modern software is not just “what does this code do?” It is “what the hell is the runtime context?” The app starts in one place, the environment is defined somewhere else, and both are easy to ignore when the code arrived in your editor in a burst of machine confidence 30 seconds ago.

So the plugin is not just about surfacing generated code. It is about surfacing execution and context together, in a way that is fast enough that I might actually use it instead of admiring it once and forgetting it exists.

The real workflow I want

What I want the plugin to encourage is an older and healthier loop:

open -> read -> edit

Not:

accept -> vibe -> move on

So lessvibes should care about things like:

  • which generated files were never opened
  • which generated files were opened but never manually edited
  • which inserted blocks later got revised by hand
  • whether the important files in a generated path ever saw real follow-up edits
  • whether I spent time reading and navigating, or just waved the code through customs

To me, those are more meaningful metrics than some bullshit chart about lines added.

I do not care how many lines “I wrote” if a glorified autocomplete snowblower dumped them into my repo and I never looked back. The meaningful question is whether I actually went into the code after it appeared.

That is what matters.

Not purity. Not virtue. Not pretending I am above the tools. Just evidence that my brain stayed in the loop.

What this is not

This is not an anti-AI project.

It is also not a surveillance tool, and if it turns into one the whole thing should be thrown in the trash.

It should not block AI. It should not shame people for using AI. It should not send sensitive code off-machine by default. It should not pretend it always knows exactly what happened. And it definitely should not become one of those dead-eyed enterprise dashboards where some manager decides Steve was only 63% hands-on this sprint and therefore needs a meeting.

Absolutely not.

If this idea works at all, it only works if users trust it.

So the defaults should be:

  • local-first
  • clear about what signals are being tracked
  • no hidden scoring
  • opt-in nudges
  • exportable or resettable session history

Basically: helpful, not narc shit.

Why I think this matters

AI coding tools are very good at helping code appear.

They are much worse at helping you metabolize what just happened.

That is the gap.

Right now the ecosystem is mostly optimized around speed, convenience, and the pleasant little dopamine hit of watching the diff get bigger. But “the diff got bigger” and “I understand the system better” are very much not the same thing. In fact, they may now be moving in opposite directions.

And I do not think the answer is fake purity where everyone pretends to reject the tools and return to some mythological golden age of hand-crafted software. The tools are here. They are useful. I am going to use them. Most people are.

What I want is some counter-pressure.

Something that makes it a little harder to drift into a state where I am technically present for the coding session but functionally just acting as a biological approval button.

Because that is the real failure mode here.

Not evil AI. Not the end of programming. Just a slow humiliating slide into becoming the guy who watches the machine cook and occasionally says, “yeah that looks right.”

I would rather avoid that outcome if possible.

So yeah

That is lessvibes.

A plugin for making sure I do not become a fucking moron any faster than time already requires.

If AI is going to stay in the editor, then the editor should do more than help me accept code. It should help me understand what just landed, where it flows, what I have actually looked at, and whether I touched the important parts with my own brain before I ship some haunted Kotlin side project into the world.

That seems like a worthwhile improvement.