{
    "version": "https://jsonfeed.org/version/1.1",
    "title": "Command-Tab",
    "home_page_url": "https://command-tab.com/",
    "feed_url": "https://command-tab.com/feed.json",
    "authors": [
        {
            "name": "Collin Allen"
        }
    ],
    "items": [
        {
            "id": "tag:command-tab.com,2026-06-12:importing-certificates-into-xcode-27-device-hub",
            "url": "https://command-tab.com/2026/06/12/importing-certificates-into-xcode-27-device-hub/",
            "title": "Importing Certificates into Xcode 27\u0027s Device Hub",
            "date_published": "2026-06-12T21:14:00Z",
            "content_html": "\u003cp\u003eXcode 27 introduced, among other new features, a new Device Hub app for developers that takes the place of the Simulator app. Where Simulator relied on separate windows for each device, Device Hub brings them all together into a single window where each simulated device is the detail view from a source list of devices on the left. It\u0026rsquo;s a more organized approach, made necessary by the wide variety of platforms Apple and Apple platform app developers have to build and test against.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Xcode 27\u0027s Device Hub\" src=\"https://r2.command-tab.com/xcode27-device-hub.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eFor enterprise users or developers building apps that communicate with web services over HTTPS, those services need to be using a certificate pair signed by a globally-trusted authority like DigiCert or Let\u0026rsquo;s Encrypt for them to work \u0026ldquo;out of the box\u0026rdquo; in the simulated OS. If they are using a certificate pair signed by a self-signed or in-house/enterprise CA (Certificate Authority), the OS will refuse to connect, displaying a \u0026ldquo;This connection is not private\u0026rdquo; interstitial in Safari or failing with a TLS trust error like \u003ccode\u003eNSURLErrorServerCertificateUntrusted\u003c/code\u003e. Even if the host Mac has the CA root certificate installed and trusted, the simulated devices rely on their own per-virtual-device trust store.\u003csup id=\"fnref:1\"\u003e\u003ca class=\"footnote-ref\" href=\"#fn:1\"\u003e1\u003c/a\u003e\u003c/sup\u003e\u003c/p\u003e\n\u003cp\u003eIn releases \u003cem\u003eprior\u003c/em\u003e to Xcode 27, you could resolve this by importing the root public certificate into the simulated OS. On iOS, this could be done by dragging and dropping the \u003ccode\u003e.cer\u003c/code\u003e file onto the Simulator device window. Nothing would appear to happen, but you could then navigate to Settings, General, About, Certificate Trust Settings and mark the certificate as trusted. On tvOS, the process was even more complex, requiring you to open Settings, General, Privacy \u0026amp; Security, hold down the virtual remote\u0026rsquo;s Play button on the Share AppleTV Analytics option to bring up a hidden dialog, then enter an HTTP URL to a \u003ccode\u003e.cer\u003c/code\u003e file. Similar to iOS, you\u0026rsquo;d have to mark it as trusted by navigating tvOS to Settings, General, About, Certificate Trust Settings and enabling the switch for that certificate. This process was slow and, especially on tvOS, quite obscure.\u003c/p\u003e\n\u003cp\u003eIn Xcode 27 with Device Hub, this process is much more uniform.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Signed mobileconfig profile in Apple Configurator\" src=\"https://r2.command-tab.com/xcode27-signed-mobileconfig.jpg\" /\u003e\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eOpen \u003ca href=\"https://apps.apple.com/us/app/apple-configurator/id1037126344?mt=12\"\u003eApple Configurator\u003c/a\u003e and create a new profile.\u003c/li\u003e\n\u003cli\u003eUnder General, give the profile a name, a unique identifier, and perhaps an organization name.\u003c/li\u003e\n\u003cli\u003eUnder Certificates on the left, click the Configure button and choose the \u003ccode\u003e.cer\u003c/code\u003e file you wish to install into the simulated OS.\u003c/li\u003e\n\u003cli\u003eFrom the File menu, choose \u0026ldquo;Sign Profile\u0026hellip;\u0026rdquo; and select a developer identity to sign with. Alternatively, you can sign profiles from the command line with \u003ccode\u003esecurity cms -S -N \"My Signing Identity\" -i unsigned.mobileconfig -o signed.mobileconfig\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eIn Device Hub, select the target device, then open the Profiles tab in the right-side device inspector.\u003c/li\u003e\n\u003cli\u003eClick the plus button below the list and choose the \u003ccode\u003e.mobileconfig\u003c/code\u003e file you just signed.\u003c/li\u003e\n\u003cli\u003eThe profile and its contained certificate should be immediately installed into the simulated OS. In iOS, you can verify by navigating to Settings, General, VPN \u0026amp; Device Management, and on tvOS the list of installed profiles is at Settings, General, Profile.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eWhile this new process does require you to wrap certificates in an Apple Configurator profile, this is much more consistent with how Apple\u0026rsquo;s device management system works, as it relies on signed profiles with policies, not loose \u003ccode\u003e.cer\u003c/code\u003e files. And now, just by adding the \u003ccode\u003e.mobileconfig\u003c/code\u003e to the Profiles section of the device inspector, the embedded certificate is automatically marked as trusted, greatly speeding up installation on new virtual devices.\u003c/p\u003e\n\u003cdiv class=\"footnote\"\u003e\n\u003chr /\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eMuch like Simulator devices, Xcode\u0026rsquo;s SwiftUI Previews rely on their own dedicated trust store, but there\u0026rsquo;s seemingly no way to configure this for SwiftUI Previews. Apple folks, please see \u003ca href=\"rdar://FB10667327\"\u003e\u003ccode\u003eFB10667327\u003c/code\u003e\u003c/a\u003e.\u0026#160;\u003ca class=\"footnote-backref\" href=\"#fnref:1\" title=\"Jump back to footnote 1 in the text\"\u003e\u0026#8617;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e"
        },
        {
            "id": "tag:command-tab.com,2026-06-02:macrochips",
            "url": "https://command-tab.com/2026/06/02/macrochips/",
            "title": "Macrochips",
            "date_published": "2026-06-02T07:00:00Z",
            "content_html": "\u003cp\u003eI was so inspired by \u003ca href=\"https://www.evilgeniuslabs.org/macrochips\"\u003eJason Coon\u0026rsquo;s macrochips project\u003c/a\u003e \u0026ndash; 4\u0026rdquo; slate drink coasters laser-engraved to look like notable chips from computing history \u0026ndash; that I had to design and make some of my own. I don\u0026rsquo;t own a laser cutter, but the local hardware store had one available, and I was able to convince them to let me engrave similar \u003ca href=\"https://www.amazon.com/dp/B01G6MHU9Y\"\u003eslate coasters\u003c/a\u003e despite them not being among their pre-defined set of available engraving targets (keychains, mugs, and the like). But what to pick? I decided to go with some chips that were meaningful to me:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eApple A17 CPU\u003c/li\u003e\n\u003cli\u003eNintendo 64 CPU\u003c/li\u003e\n\u003cli\u003eSony PlayStation CPU\u003c/li\u003e\n\u003cli\u003eBroadcom Raspberry Pi 5 CPU\u003c/li\u003e\n\u003cli\u003eNVIDIA Media and Communications Processor (from the original Xbox)\u003c/li\u003e\n\u003cli\u003eIBM PowerPC 603 CPU (from early PowerPC Macs)\u003c/li\u003e\n\u003cli\u003eMotorola PowerPC G4 CPU (from later PowerPC Macs)\u003c/li\u003e\n\u003cli\u003eAMD K6 CPU\u003c/li\u003e\n\u003cli\u003eIntel i386 EX CPU\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThe hardest part of designing these was tracking down vector versions of some of these companies\u0026rsquo; now-obsolete logos, extracting them from PDF files and datasheets, but I think the designs turned out pretty good:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"My macrochip designs\" src=\"https://r2.command-tab.com/macrochips.png\" /\u003e\u003c/p\u003e\n\u003cp\u003eOnce designed, it was time to hand them off to the laser cutter:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Laser cutter mid process\" src=\"https://r2.command-tab.com/macrochip-engraving.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eIt was fun to watch the designs get laid down by the laser cutter:\u003c/p\u003e\n\u003cvideo src=\"https://r2.command-tab.com/macrochip-engraving.mp4\" controls loop\u003e\u003c/video\u003e\n\n\u003cp\u003eThe results turned out alright:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"My macrochip designs as slate coasters\" src=\"https://r2.command-tab.com/macrochip-coasters.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eThough, there were a number of text layers I forgot to convert to outlines, so the engraving prep software replaced them with Myriad instead of the specific fonts I had chosen. As well, a few early attempts were also a little mis-aligned. I could certainly do better if I had time to sit and make adjustments with my \u003cem\u003eown\u003c/em\u003e laser cutter\u0026hellip;\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2026-05-30:indiana-jones-and-the-great-circle",
            "url": "https://command-tab.com/2026/05/30/indiana-jones-and-the-great-circle/",
            "title": "Indiana Jones and the Great Circle",
            "date_published": "2026-05-30T07:00:00Z",
            "content_html": "\u003cp\u003e\u003cimg alt=\"Indiana Jones and the Great Circle title screen\" src=\"https://r2.command-tab.com/indy-title.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eI finally caught up to 2024 and finished playing \u003cem\u003eIndiana Jones and the Great Circle\u003c/em\u003e to 100%. I had been putting off starting the game for some time because I\u0026rsquo;m really not much of a gamer, and I find it oddly difficult to internalize new game control schemes and menu systems. But once I finally picked up the controller, it didn\u0026rsquo;t take long to get acquainted with the intuitive grip and whip system, and I\u0026rsquo;m so glad I did, because this game is really something special.\u003c/p\u003e\n\u003ch2 id=\"look-and-feel\"\u003eLook and Feel\u003c/h2\u003e\n\u003cp\u003eMachineGames did a fantastic job at matching the feel of the source material. The levels are dense with detail, the typography looks just right, and there are both first person in-game and third person cutscene references to the films\u0026rsquo; cinematic choices at every turn. Most notably, the use of hard contrasting light and shadow appears fairly often while exploring. Following along with the game\u0026rsquo;s story feels like enjoying a lost installment from the original trilogy, which is a bar I didn\u0026rsquo;t expect it to clear going in.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"A spotlight casts Indy\u0027s shadow on the wall\" src=\"https://r2.command-tab.com/indy-shadow.jpg\" /\u003e\n\u003cem\u003eCarefully placed spotlights and torches regularly cast Indy\u0026rsquo;s recognizable shadow.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Light shines across Indy\u0027s eyes as he thinks\" src=\"https://r2.command-tab.com/indy-eye-light.jpg\" /\u003e\n\u003cem\u003eLight reveals Indy\u0026rsquo;s eyes when he\u0026rsquo;s making a connection or solving a puzzle.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Welcome to Sukhothai screen\" src=\"https://r2.command-tab.com/indy-sukhothai.jpg\" /\u003e\n\u003cem\u003e\u003ca href=\"https://www.teff-type.com/product/open-kapitalen/\"\u003eOpen Kapitalen\u003c/a\u003e and \u003ca href=\"https://www.r41.it/en/eurostile\"\u003eEurostile Extended\u003c/a\u003e welcome you to new regions and lend film authenticity.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eChoosing a mostly first-person adventure also seemed like a big development risk. For an iconic character like Indiana Jones, it\u0026rsquo;s definitely a choice to \u003cem\u003enot\u003c/em\u003e show him for large swaths of the game. To make it convincing, they had to lean hard into what it would be like to \u003cem\u003ebe\u003c/em\u003e Indiana Jones. So much would revolve around what you can do with your hands and whip and items. Therefore, that in-game system had to feel very comfortable to use and be pretty extensive. I had played a few previous Indiana Jones (and of course, \u003cem\u003eTomb Raider\u003c/em\u003e) games which were all third person, so going in, I thought first person would be weird or off-putting, but this game does it so well that I now prefer it over third person or over-the-shoulder views.\u003c/p\u003e\n\u003cp\u003eThe developers clearly spent a lot of time studying the films. They picked up so many of Indy\u0026rsquo;s smirks, quirks, and mannerisms, and when combined with Troy Baker\u0026rsquo;s shockingly accurate voiceover work, you\u0026rsquo;d be surprised to learn it wasn\u0026rsquo;t voiced by and motion captured from Harrison Ford himself. The humor from the films is also ever present and used to great effect. Even beyond the dialogue, the yells, grunts, and exclamations all sound so perfect, capturing Indy\u0026rsquo;s intonation well.\u003c/p\u003e\n\u003cp\u003eWhat really put it over the top for me, though, is the music and sound. The game features a lovely and familiar score, threading John Williams\u0026rsquo; original themes through new material in a way that sounds completely organic and unforced, rather than just quoting the Raiders March and calling it a day. Sound effects are also very much on point, with whip, punch, and gunfire having the signature cracks, thuds, and pops that seem right out of the films.\u003c/p\u003e\n\u003cp\u003eThere are a few \u003ca href=\"https://www.youtube.com/watch?v=FsxTQvo5QhM\"\u003ebehind-the-scenes videos\u003c/a\u003e that \u003ca href=\"https://youtube.com/watch?v=7VRZJPWAW_g\"\u003ego deep into\u003c/a\u003e all of this, and I watched them with a big stupid grin on my face. Hearing the development team talk about watching the films together, cataloging the core details that had to be right, and obsessing over everything clearly paid off.\u003c/p\u003e\n\u003cp\u003eIt\u0026rsquo;s also just a gorgeous game. The \u003ca href=\"https://en.wikipedia.org/wiki/Id_Tech_7\"\u003eid Tech 7\u003c/a\u003e engine looks incredible on modern devices, rendering lighting and geometry in more detail than I\u0026rsquo;m used to in games (again, I don\u0026rsquo;t play a ton of games). The amount of just \u003cem\u003estuff\u003c/em\u003e to see in the levels is impressive. I can\u0026rsquo;t even imagine how long it took to set-dress all these areas. Notably, many of these items can be used as weapons or distractions, including wrenches, frying pans, mops, and bottles.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Indiana Jones turns to think, revealing his adventure companion Gina behind him\" src=\"https://r2.command-tab.com/indy-turn.jpg\" /\u003e\n\u003cem\u003eJust marvel at the level of detail achieved here: The fine individual hair, the wear on the seams of the leather jacket, the distressed fur felt on the fedora, and the specular highlights on the sclera of the eyes.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Looking through a town and down the main river in Sukhothai\" src=\"https://r2.command-tab.com/indy-sukhothai-detail.jpg\" /\u003e\n\u003cem\u003eEvery region has loads to explore, little sub-plots to follow, and NPCs going about their business. Some casually relay details or hints towards as-yet-unsolved puzzles.\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"gameplay\"\u003eGameplay\u003c/h2\u003e\n\u003cp\u003eThe game heavily encourages you to lean on Indy\u0026rsquo;s punch and whip maneuvers rather than using his revolver. Ammo isn\u0026rsquo;t something to be spent carelessly. Rather, you save it for the moments when you get into a jam that\u0026rsquo;s larger than you can otherwise take on. But the cost of using a loud weapon is that nearby enemies will overhear it, blow the whistle on you, and rally reinforcements, so you need to pick and choose your battles carefully rather than playing it like a run-and-gun first person shooter. While not a stealth game, climbing, disguise, distraction, and a healthy dose of hand-to-hand combat will get you further than running headlong into battle. Certain classes of enemies will also see through your various disguises and similarly call attention to you, so you need to be aware of who\u0026rsquo;s nearby.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Looking down from atop a scaffold, reloading\" src=\"https://r2.command-tab.com/indy-reload.jpg\" /\u003e\n\u003cem\u003eAttention to detail is everywhere in this game. Here, the number of remaining shots in the heads-up display corresponds to the number of visibly unfired rounds in the revolver. The reload animation has Indy individually pluck out spent rounds and replace them, rotating the cylinder for each.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003eThe game balances exploration, discovery, collection, puzzle solving, and storytelling well. I rarely found myself spending too much time doing any one of those activities. The puzzles aren\u0026rsquo;t particularly difficult, with key items often just in adjacent crawlspaces, but they\u0026rsquo;re also not \u003cem\u003etoo\u003c/em\u003e simple. They feel calibrated to make you think, but aren\u0026rsquo;t so onerous that they impede advancing the story.\u003c/p\u003e\n\u003cp\u003eAlong the way, you pick up money, bandages, food, local maps, and Adventure Books that expand your capabilities. The books are the game\u0026rsquo;s skill system, where you can improve your abilities like reducing reloading time, increasing damage dealt against enemies, or boosting climb and run stamina, and finding them is a nice reward for exploration. Once learned, they make future encounters progressively more achievable and boost your confidence to take swings at more aggressive confrontations. Indy is a scholar and a problem-solver first, so getting better at the job through research feels like the right approach.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"A view of the menu system listing Adventure Books that boost combat skills\" src=\"https://r2.command-tab.com/indy-books.jpg\" /\u003e\n\u003cem\u003eAcquiring and reading Adventure Books boosts combat, survival, brawling, etc.\u003c/em\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Indiana Jones\u0027 Pause menu\" src=\"https://r2.command-tab.com/indy-pause-menu.jpg\" /\u003e\n\u003cem\u003eEven the Pause menu looks like it belongs. Also, hey, it\u0026rsquo;s me: I\u0026rsquo;m \u003ccode\u003emac_minded\u003c/code\u003e on PlayStation and \u003ccode\u003eMac Minded\u003c/code\u003e on Xbox.\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"that-belongs-in-a-museum\"\u003eThat Belongs in a Museum\u003c/h2\u003e\n\u003cp\u003e\u003cem\u003eThe Order of Giants\u003c/em\u003e DLC is a worthwhile addition, though it left me wanting even more time in this world. What MachineGames accomplished here is astounding. Licensed games based on beloved properties like Indiana Jones have a history of often getting surface details right but missing what actually made the source material work. This one didn\u0026rsquo;t miss. It understood what \u003cem\u003eIndiana Jones\u003c/em\u003e is about well enough to make a game that genuinely belongs on the same shelf as the films. I don\u0026rsquo;t know if it will happen, but I would very much love a sequel.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2026-04-25:using-uv-with-red-hat-python-images",
            "url": "https://command-tab.com/2026/04/25/using-uv-with-red-hat-python-images/",
            "title": "Using uv with RedHat Python Images",
            "date_published": "2026-04-25T07:00:00Z",
            "content_html": "\u003cp\u003eWhen deploying web apps, I use containers almost exclusively. Containerization lets you package up everything your app needs and ship all of it to a container runtime in a single archive. While it has some drawbacks, it\u0026rsquo;s still a significant net improvement over web app deployment methods that pre-date it.\u003c/p\u003e\n\u003cp\u003eI use \u003ca href=\"https://astral.sh/uv\"\u003euv\u003c/a\u003e to install dependencies into a container image, but I typically \u003cem\u003edon\u0026rsquo;t\u003c/em\u003e want to create a Python virtualenv within the container because then there are two levels of isolation to contend with. Just the container alone is sufficient. However, I still want all the benefits of using uv, particularly the specific tree of dependency versions and their hashes listed in the \u003ccode\u003euv.lock\u003c/code\u003e file. For this reason, I configure uv to install the listed dependencies into the container\u0026rsquo;s \u0026ldquo;system\u0026rdquo; Python at install time, rather than a virtualenv \u003ccode\u003e.venv/\u003c/code\u003e directory:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-dockerfile\"\u003eFROM registry.redhat.io/rhel9/python-312:latest\n\nWORKDIR /opt/app-root/src\n\n# Use the \u0026quot;system\u0026quot; Python for uv (the container\u0027s)\nENV UV_SYSTEM_PYTHON=1\nENV UV_PROJECT_ENVIRONMENT=/opt/app-root\n\n# Install uv\nRUN pip install --upgrade pip==26.0.1 \u0026amp;\u0026amp; pip install --upgrade uv==0.11.4\n\n# Copy only dependency files first to cache the dependency installation as its own container image layer.\n# --active: prefer the environment specified by VIRTUAL_ENV (in the upstream RedHat Python base image)\n# --frozen: treat the versions in uv.lock as the source of truth and skips updating the lockfile\n# --no-dev: skip dev dependencies, since this is a non-development environment\n# --compile-bytecode: compile Python files to .pyc files to trade CI build time for faster container start time\n# --no-python-downloads disables automatic downloads of Python so we use the container\u0027s\nCOPY pyproject.toml uv.lock .\nRUN uv sync --active --frozen --no-dev --compile-bytecode --no-python-downloads\n\n# Copy the rest of the codebase in a separate layer\nCOPY . .\n\nCMD [\u0026quot;granian\u0026quot;, \u0026quot;app:app\u0026quot;]\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eThose options will use uv to install dependencies into the container-provided Python environment at \u003ccode\u003e/opt/app-root/\u003c/code\u003e in the Python image rather than creating a new virtualenv at \u003ccode\u003e/opt/app-root/src/.venv/\u003c/code\u003e. With this, you can omit \u003ccode\u003euv run ...\u003c/code\u003e from container commands, cron jobs, etc. Opening a shell into this container will drop you into a place where the dependencies are installed and readily available without having to activate a virtualenv, prefix tool invocations with \u003ccode\u003euv run\u003c/code\u003e, or specify a container \u003ccode\u003eENTRYPOINT\u003c/code\u003e).\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2026-04-20:push-notifications-with-brrr",
            "url": "https://command-tab.com/2026/04/20/push-notifications-with-brrr/",
            "title": "Push Notifications with Brrr",
            "date_published": "2026-04-20T07:00:00Z",
            "content_html": "\u003cp\u003eiOS developer Simon St\u00f8vring recently launched \u003ca href=\"https://brrr.now\"\u003eBrrr\u003c/a\u003e, a convenient and low-friction web service and corresponding iOS app deliver push notifications to your iOS devices using only an HTTP request. In this way, it can integrate with almost any service or device that is internet-connected. Options allow you to customize the notification content, alert sound, destination URL, image, and more.\u003c/p\u003e\n\u003cp\u003eBrrr fills the particular niche of when you want a quick notification from a script, a cron job, or home automation trigger without building your own push notification infrastructure. It\u0026rsquo;s not the first app of its kind to do this, but it does so very simply. And at $9.99/year, it\u0026rsquo;s very reasonably priced for what it does.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2026-04-19:a-decade-and-counting",
            "url": "https://command-tab.com/2026/04/19/a-decade-and-counting/",
            "title": "A Decade and Counting",
            "date_published": "2026-04-19T07:00:00Z",
            "content_html": "\u003cp\u003eIn 2023, I shared this anecdote at the Pixar Anniversary Awards celebration for people who reached 10 years of employment:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eI was late on my first day at Pixar. I\u0026rsquo;m not one of those perpetually-late-to-everything people. I pride myself on being on time or earlier for events. But on my first day at Pixar in the summer of 2013, I wildly underestimated how long it would take to get from the North Bay to Emeryville during morning rush hour traffic.\u003c/p\u003e\n\u003cp\u003eAs the minutes ticked over my scheduled orientation start time, my palms were starting to sweat against the steering wheel. Cars were barely inching along, and the time kept getting later and later. Soon, the recruiter I had been working with started calling and urgently asking, \u0026ldquo;Are you still coming?\u0026rdquo;, and I swore that I was indeed still on my way and it would just be a little longer. Taking a risk, I swerved into the carpool lane for the last mile or so and I arrived \u0026ldquo;only\u0026rdquo; 40 minutes late and bolted into the Steve Jobs Building. Graciously, they rushed me over to the theater to catch up with everyone else to watch a screening of \u003ca href=\"https://en.wikipedia.org/wiki/Party_Central\"\u003e\u003cem\u003eParty Central\u003c/em\u003e\u003c/a\u003e at what seemed like maximum volume, which was a hell of a way to kick start a morning.\u003c/p\u003e\n\u003cp\u003eSo, I want to thank my recruiter for not turning me away when I finally arrived, and want to thank everyone at Pixar for being such a truly wonderful group of people. I love working with all of you and look forward to the next decade. I promise I\u0026rsquo;ll be on time.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eIt\u0026rsquo;s been a few years since that ceremony, and Pixar continues to be a place where I want to do my best work. The care and enthusiasm everyone pours into their particular craft is, I hope, evident in our body of work.\u003c/p\u003e\n\u003cp\u003eWhat inspires me to do my best work? A few things I\u0026rsquo;ve identified over the years.\u003c/p\u003e\n\u003cp\u003eThe first and most important, I think, is being given the authority and autonomy to gather requirements for, design, engineer, and ship tools that help people get their job done. These tools provide users with more time to focus on doing creative work rather than wrangling minutiae, and it\u0026rsquo;s rewarding to be able to turn an idea into a released product without a bunch of red tape.\u003c/p\u003e\n\u003cp\u003eWorking alongside people who genuinely give a damn about their work also matters too, particularly people will give honest critical feedback when my own work isn\u0026rsquo;t up to par. We hold each other\u0026rsquo;s standards high, and do so with respect, where the goal is to lift up the work and not drag the other person down. And very often the best technical solutions win because the right answer, once someone speaks it into the room, is clear to all involved and we move forward in agreement.\u003c/p\u003e\n\u003cp\u003eThere\u0026rsquo;s also the proximity to the actual creative work. The end users of the tools I create are animators, producers, production staff, and so on. When my tools work well, it ripples into a film, even though I\u0026rsquo;m not among those who touch the film\u0026rsquo;s pixels directly.\u003c/p\u003e\n\u003cp\u003eFinally, there\u0026rsquo;s the constraint of a specific, known audience.\u003csup id=\"fnref:1\"\u003e\u003ca class=\"footnote-ref\" href=\"#fn:1\"\u003e1\u003c/a\u003e\u003c/sup\u003e Building for co-workers is different from building for \u0026ldquo;users.\u0026rdquo; I know many of them by name. That specificity tends to produce more considered work than if I\u0026rsquo;m building for an abstraction. And the feedback I get about the work is everywhere, from conversations in Slack to spontaneous \u0026ldquo;Hey, wouldn\u0026rsquo;t it be cool if\u0026hellip;?\u0026rdquo; spitballing in the lunch line.\u003c/p\u003e\n\u003cp\u003eNone of this is a recipe, and I\u0026rsquo;m not sure it\u0026rsquo;s replicable. These are conditions I largely stumbled into, often by luck and the kindness of others, and only later learned to recognize as what was making the work feel meaningful. After more than a decade in, I\u0026rsquo;m still here, which probably says something about how rare that is to find.\u003c/p\u003e\n\u003cdiv class=\"footnote\"\u003e\n\u003chr /\u003e\n\u003col\u003e\n\u003cli id=\"fn:1\"\u003e\n\u003cp\u003eBuilding for a specific audience is also convenient and beneficial from a technical standpoint because the target devices are a much more limited and homogenous set, for example, modern \u0026ldquo;evergreen\u0026rdquo; browsers and Apple platforms. I can therefore take advantage of new features and APIs quite readily, and more quickly deprecate and remove cruft.\u0026#160;\u003ca class=\"footnote-backref\" href=\"#fnref:1\" title=\"Jump back to footnote 1 in the text\"\u003e\u0026#8617;\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/div\u003e"
        },
        {
            "id": "tag:command-tab.com,2026-04-15:going-electric",
            "url": "https://command-tab.com/2026/04/15/going-electric/",
            "title": "Going Electric",
            "date_published": "2026-04-15T07:00:00Z",
            "content_html": "\u003cp\u003eI am done with gasoline and I\u0026rsquo;m never going back. Early last year, I sold my gasoline-powered car and went all in on an electric vehicle. I skipped right over hybrids, which I viewed as being burdened with the additional complexity of having to haul around two sources of locomotion. I figured that if I was going to try something new, I should just make the switch and not try to hedge against the new thing at the cost of added complexity and maintenance. Electric vehicles are well enough established (particularly in California) that there was little reason to avoid making the jump, and I\u0026rsquo;m so glad I made the switch.\u003c/p\u003e\n\u003cp\u003eAfter checking out everything from the large F-150 Lightning down to a petite little Chevy Bolt, I settled on a used 2022 Volkswagen ID.4 which had just come off lease. With only about 20,000 miles on the odometer, it was still very much like new. But the fact that it was previously a lease meant it was likely handled carefully, and the fact that it was now used meant it was extremely affordable for an EV at a time when EVs are often more expensive than gas vehicles. I ended up paying about $25,000 for it, and that felt like a steal for what I got.\u003c/p\u003e\n\u003cp\u003eThis being my first EV, I was initially a little bit wary about going electric, but now that I have a year\u0026rsquo;s worth of daily-driver experience with the technology, it\u0026rsquo;s so crystal clear to me that this is the future of vehicles and that the internal combustion engine\u0026rsquo;s best days are behind it. It feels like a seismic shift both in the way I drive and use energy.\u003c/p\u003e\n\u003cp\u003eLike most EVs, the ID.4 has some really great features. The very first difference you notice is the instant acceleration. You start moving the moment you press the pedal. The best way to describe it is like the difference between pre-iPhone touchscreens which often struggled to keep up with the movement of your finger, whereas the iPhone made the screen contents feel like they moved directly with your finger. EV acceleration feels tactile and direct, rather than propagated through a buffer delay. Because it\u0026rsquo;s electric, the ID.4 moves so smoothly and quietly that it really feels like a much more expensive luxury car. It also has a tight turning radius and can thus easily achieve a 180 degree turn-around inside the width of a narrow street without having to perform a multi-point turn.\u003c/p\u003e\n\u003cp\u003eI was coming from a 2009 Toyota Corolla base trim, so many of the features of the ID.4 are just the current state of vehicles made within the last decade and not EV exclusives, but are nonetheless delightful to have, including:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIlluminated exterior and (RGB) interior handles\u003c/li\u003e\n\u003cli\u003eComfortable heated seats\u003c/li\u003e\n\u003cli\u003eHeated steering wheel\u003c/li\u003e\n\u003cli\u003eRemote climate control\u003c/li\u003e\n\u003cli\u003eBack up camera\u003c/li\u003e\n\u003cli\u003eSide mirror lane occupancy indicators\u003c/li\u003e\n\u003cli\u003eBuilt-in USB-C ports\u003c/li\u003e\n\u003cli\u003eApple CarPlay\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eCarPlay, in particular, was a must-have. The Chevy dealer tried to convince me that GM\u0026rsquo;s Bluetooth solution was still very good, but I wasn\u0026rsquo;t having that at all. The ID.4 also has walk-up unlock, walk-away lock, and auto-enters Park, so I never really think about what mode the car is in: I walk up (it unlocks), I get in, buckle, drive somewhere, stop, unbuckle (it enters Park), then I just get out and walk away (it locks). I never have to think about turning it on or off myself, making for a frictionless experience.\u003c/p\u003e\n\u003cp\u003eThe ID.4 has two drive modes, \u0026ldquo;D\u0026rdquo; and \u0026ldquo;B\u0026rdquo;. D mode (the default Drive mode) makes the car drive much more like gas car, with the ability to coast for longer distances and do little regenerative braking. But toggle into B mode and the car behaves more like its true EV self, doing more aggressive regenerative braking when you ease off the accelerator pedal, allowing you to recover some electricity while cornering or going downhill. It took a short few days before B mode was far and away my preferred mode, making the D mode (and thus the behavior of gas cars) feel almost slippery by comparison.\u003c/p\u003e\n\u003cp\u003eThe major consideration when choosing an EV is how and when you\u0026rsquo;ll charge the battery. Chargers are popping up in more and more places, but you very likely spend a lot of time not driving with the car parked somewhere for hours at a time. That\u0026rsquo;s probably the best time and place to charge. A couple years ago, we installed a modest home solar and battery storage system, and adding a home EV charger (Level 2 @ 220V 40A) charger later was a straightforward addition. While I could have achieved sufficient charging without any special charger using a regular household plug (Level 1 @ 110V 15-20A), the Level 2 home charger makes filling up my car only take a few hours and is easily done while I\u0026rsquo;m sleeping or working from home while the sun is shining on the solar panels. Powering my car is now effectively free using energy from the sun instead of \u003ca href=\"https://www.youtube.com/watch?v=KtQ9nt2ZeGM\"\u003edisposable energy from oil\u003c/a\u003e. I can plug in at convenient times and almost always have a \u0026ldquo;full tank\u0026rdquo; ready to go without having to consider the gas station on the way home since my home \u003cem\u003eis\u003c/em\u003e the station. And so is my work. And the grocery store. Almost every destination has something available or nearby, but having a sufficient charger at home is what really puts \u0026ldquo;range anxiety\u0026rdquo; fears to rest.\u003c/p\u003e\n\u003cp\u003eOn the interior, one of the compelling reasons for choosing the ID.4 was its minimalist, unadorned heads-up display. The dashboard user interface is big, bright, and clear, with simple numerals for the speed, flanked by cruise control and next-turn instructions (which can use the built-in navigation or CarPlay). This approach was not true for the Kia Niro, which had a fake analog speedometer needle and gradients and shadows abound.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"ID.4 Dashboard\" src=\"https://r2.command-tab.com/id4-dash.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eThere are a few things that could be better, though:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eThe steering wheel and center console use touch controls, and while they\u0026rsquo;re not easy to press accidentally, they do require you to \u003ca href=\"https://www.wired.com/story/why-car-brands-are-finally-switching-back-to-buttons/\"\u003elook away from the road to adjust\u003c/a\u003e. In my Corolla, I could adjust the heat mode, fan speed, and temperature by feel alone, and that felt safer. VW is, thankfully, \u003ca href=\"https://www.autocar.co.uk/car-news/new-cars/volkswagen-reintroducing-physical-controls-vital-functions\"\u003emoving away from touch controls\u003c/a\u003e in \u003ca href=\"https://www.caranddriver.com/news/a69916699/volkswagen-interior-physical-buttons-return/\"\u003efuture models\u003c/a\u003e.\u003c/li\u003e\n\u003cli\u003eRemote climate control sometimes takes a minute or more to respond. I never had this feature at all before, though, so any availability was still a welcome feature.\u003c/li\u003e\n\u003cli\u003eWireless CarPlay is convenient, but a little laggy and skips occasionally. This might just be wireless CarPlay\u0026rsquo;s fault and not VW\u0026rsquo;s. Wired CarPlay via USB-C works reliably, is very responsive, and charges my phone faster than the available Qi charger (and with less heat).\u003c/li\u003e\n\u003cli\u003eI wish the VW app had a web app counterpart. How hard could this be, given they already have an app?\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eMinor gripes aside, none of these are dealbreakers. Overall, the ID.4 is a competitively priced EV that was, for me, a great entry into the world of electric vehicles. My experience so far has been extremely positive, and if it were totaled, I would buy one again in a heartbeat. I\u0026rsquo;m never buying a gasoline-powered \u003cem\u003eanything\u003c/em\u003e again.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2022-04-24:running-nuxt-3-behind-an-nginx-reverse-proxy",
            "url": "https://command-tab.com/2022/04/24/running-nuxt-3-behind-an-nginx-reverse-proxy/",
            "title": "Running Nuxt 3 Behind an nginx Reverse Proxy",
            "date_published": "2022-04-24T07:00:00Z",
            "content_html": "\u003cp\u003eI was attempting to run \u003ca href=\"https://github.com/nuxt/framework\"\u003eNuxt 3\u003c/a\u003e RC1 in development mode behind a local nginx reverse proxy, but ran into several issues. There are a number of reasons to run a development application server behind a \u003ca href=\"https://en.wikipedia.org/wiki/TLS_termination_proxy\"\u003eTLS-terminating reverse proxy\u003c/a\u003e, including more closely mirroring a production setup, ensuring an application performs correctly when proxied, and gaining HTTPS support to enable use of  newer \u003ca href=\"https://www.digicert.com/blog/https-only-features-in-browsers\"\u003eHTTPS-only user-agent APIs\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003eHowever, when nginx reverse proxies to the Nuxt server using a configuration like the following, the application will load correctly in the browser but \u003ca href=\"https://vitejs.dev\"\u003eVite\u003c/a\u003e (bundled with Nuxt) will no longer be able connect to its backend websocket server to provide hot module replacement (HMR).\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-nginx\"\u003elocation / {\n  proxy_pass http://127.0.0.1:3000;\n  proxy_set_header X-Real-IP $remote_addr;\n  proxy_set_header Host $host;\n  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTo fix this, Vite needs to be made aware it\u0026rsquo;s being reverse proxied, and nginx needs to pass through Vite\u0026rsquo;s websocket connection.\u003c/p\u003e\n\u003cp\u003eIn the Nuxt config (\u003ccode\u003enuxt.config.ts\u003c/code\u003e), add the following Vite config:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-javascript\"\u003evite: {\n  server: {\n    hmr: {\n      protocol: \u0027wss\u0027,\n      clientPort: 443,\n      path: \u0027hmr/\u0027\n    }\n  }\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eVite will now use the secure websocket protocol over the same HTTPS port as the application, but it will request it at a new, distinct path.\u003c/p\u003e\n\u003cp\u003eIn the nginx config, add a new \u003ccode\u003elocation\u003c/code\u003e directive to match the configured Vite path (\u003ccode\u003e/_nuxt\u003c/code\u003e is always prepended), have it perform an HTTP Upgrade, and then reverse proxy to Vite\u0026rsquo;s websocket server, which always listens on port 24678:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-nginx\"\u003elocation /_nuxt/hmr/ {\n  proxy_http_version 1.1;\n  proxy_set_header Upgrade $http_upgrade;\n  proxy_set_header Connection \u0026quot;Upgrade\u0026quot;;\n  proxy_pass http://127.0.0.1:24678;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eAfter restarting the development server and nginx, Nuxt 3 and Vite HMR work great behind nginx, which now handles TLS termination and reverse proxying of HTTP and websocket traffic.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUpdate 2023-09-28\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eAs of Nuxt 3.7.4, the \u003ccode\u003enuxt.config.ts\u003c/code\u003e configuration \u003ca href=\"https://github.com/nuxt/nuxt/issues/12003#issuecomment-1738373498\"\u003eis unnecessary\u003c/a\u003e, though having the following nginx config in place avoids a WebSocket error about the WebSocket host being undefined:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-nginx\"\u003elocation /_nuxt/ {\n    proxy_http_version 1.1;\n    proxy_set_header Upgrade $http_upgrade;\n    proxy_set_header Connection \u0026quot;upgrade\u0026quot;;\n    proxy_set_header Host $host;\n    proxy_cache_bypass $http_upgrade;\n    proxy_pass http://127.0.0.1:3000;\n}\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNote the differences from the above config \u0026ndash; the location path dropped \u003ccode\u003ehmr/\u003c/code\u003e, the Vite HMR port (\u003ccode\u003e24678\u003c/code\u003e) became the default Nuxt port (\u003ccode\u003e3000\u003c/code\u003e), and the \u003ccode\u003eHost\u003c/code\u003e header was also added (but the \u003ccode\u003eHost\u003c/code\u003e header is likely not critical for this scenario).\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUpdate 2026-03-23\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eTangentially related: In development, \u003ca href=\"https://nuxt.com/modules/icon\"\u003eNuxt Icon\u003c/a\u003e collections are loaded from the Nuxt server at \u003ccode\u003e/api/_nuxt_icon\u003c/code\u003e, but this path might introduce a conflict if you are integrating a completely separate non-Nuxt API at \u003ccode\u003e/api\u003c/code\u003e. In my case, I often have a Python API expecting requests bearing that path prefix. My local nginx setup forwards requests with \u003ccode\u003e/api\u003c/code\u003e prefixed paths to Python, resulting in a Nuxt 404 on Nuxt Icon collection manifests such as \u003ccode\u003e/api/_nuxt_icon/bi.json?icons=escape\u003c/code\u003e or \u003ccode\u003e/api/_nuxt_icon/solar.json?icons=check\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003eSetting a \u003ccode\u003elocalApiEndpoint\u003c/code\u003e overrides the default value of \u003ccode\u003e/api/_nuxt_icon\u003c/code\u003e both in how the Nuxt server route is offered and how the Nuxt client requests the collection JSON. The \u003ca href=\"https://github.com/nuxt/icon/issues/185\"\u003eissue\u003c/a\u003e and \u003ca href=\"https://github.com/nuxt/icon/pull/191\"\u003efix\u003c/a\u003e are both documented on GitHub. In \u003ccode\u003enuxt.config.ts\u003c/code\u003e, add something like the following:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-javascript\"\u003eicon: {\n  localApiEndpoint: \u0027/_nuxt_icon\u0027,\n},\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eNote that \u003ccode\u003e/api\u003c/code\u003e is absent from the value of \u003ccode\u003elocalApiEndpoint\u003c/code\u003e, durecting Nuxt Icon to use a path \u003cem\u003eother than\u003c/em\u003e \u003ccode\u003e/api/_nuxt_icon\u003c/code\u003e. Anything that will not be picked up by an external API is valid here, and will make the Nuxt Icon module work again.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2020-01-11:building-cen64-on-macos",
            "url": "https://command-tab.com/2020/01/11/building-cen64-on-macos/",
            "title": "Building cen64 on macOS",
            "date_published": "2020-01-11T08:00:00Z",
            "content_html": "\u003cp\u003eFor testing Nintendo 64 homebrew ROMs, \u003ca href=\"https://github.com/n64dev/cen64\"\u003ecen64\u003c/a\u003e is the most accurate emulator (though it doesn\u0026rsquo;t run at full speed yet). Here\u0026rsquo;s how to build it from source on macOS:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eInstall XQuartz from the official \u003ca href=\"https://www.xquartz.org/\"\u003edistributed disk image\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ebrew install cmake glew\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003egit clone https://github.com/n64dev/cen64.git\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecd cen64\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emkdir build\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecd build\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ecmake ..\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003emake\u003c/code\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eIf you\u0026rsquo;d like to enable cen64\u0026rsquo;s debug logging, create a debug build when running \u003ccode\u003ecmake\u003c/code\u003e:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-shell\"\u003ecmake -DCMAKE_BUILD_TYPE=Debug ..\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eWhen running cen64 outside of an XQuartz X11 terminal, it may report:\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eUsing NTSC-U PIFROM\ncreate_device: Failed to initialize the VI.\nFailed to create a device.\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003eTo fix this, you can run it within an XQuartz X11 terminal, or set the \u003ccode\u003eDISPLAY\u003c/code\u003e environment variable to something like \u003ccode\u003e:0\u003c/code\u003e either in your \u003ccode\u003e.bashrc\u003c/code\u003e file or inline during invocation:\u003c/p\u003e\n\u003cpre\u003e\u003ccode class=\"language-shell\"\u003eDISPLAY=:0 ./cen64 /path/to/pifdata.bin /path/to/rom.z64\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e\u003ccode\u003eDISPLAY\u003c/code\u003e needs to be set because cen64 calls \u003ca href=\"https://tronche.com/gui/x/xlib/display/opening.html\"\u003eXOpenDisplay\u003c/a\u003e with a NULL display name (presumably to default to your \u003ccode\u003eDISPLAY\u003c/code\u003e environment variable), but if it\u0026rsquo;s not set, XOpenDisplay returns NULL and cen64 has no display within which to create a window for rendering Nintendo 64 content.\u003c/p\u003e\n\u003cp\u003eFor extremely verbose register-level output, edit \u003ccode\u003eCMakeLists.txt\u003c/code\u003e and set \u003ccode\u003eDEBUG_MMIO_REGISTER_ACCESS\u003c/code\u003e to \u003ccode\u003eON\u003c/code\u003e. Make sure to remove any cached data in \u003ccode\u003ebuild/\u003c/code\u003e to ensure your changes are reflected, then recompile and re-run.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUpdate 2024-03-02\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eDevelopment on cen64 has not progressed in many months and is now considered unmaintained. \u003ca href=\"https://ares-emu.net\"\u003eares\u003c/a\u003e, a cross-platform, open source, multi-system emulator is now regarded as the best emulator for Nintendo 64 development.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2017-09-16:brewbot-sending-coffee-notifications-to-slack",
            "url": "https://command-tab.com/2017/09/16/brewbot-sending-coffee-notifications-to-slack/",
            "title": "BrewBot - Sending Coffee Notifications to Slack",
            "date_published": "2017-09-16T07:00:00Z",
            "content_html": "\u003cp\u003eAt work, we have a coffee machine that serves dozens of people in the building, and it\u0026rsquo;s difficult to know when to come get fresh coffee. You might arrive when it\u0026rsquo;s empty and be tasked with making more, but the ideal situation is to arrive just as a fresh pot is being brewed.\u003c/p\u003e\n\u003cp\u003eWe also use Slack for team chat and various notifications, so integrating the coffee machine status was a no-brainer. Using a non-invasive/inductive current sensor and Raspberry Pi, the following setup monitors coffee machine energy consumption and waits for a significant rise in current draw, followed by several minutes of sustained usage. Once a time threshold has passed, it does an HTTP POST to a Slack webhook, sleeps for about 15 minutes, then starts monitoring again. This \u0026ldquo;brewbot\u0026rdquo; code is \u003ca href=\"https://github.com/command-tab/brewbot\"\u003eavailable on GitHub\u003c/a\u003e, and a parts list can be found below.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Completed kit\" src=\"https://r2.command-tab.com/brewbot_full_kit.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Packaged in box\" src=\"https://r2.command-tab.com/brewbot_box.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"ADC board\" src=\"https://r2.command-tab.com/brewbot_adc_board.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eFull parts list:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"http://www.adafruit.com/products/856\"\u003eMCP3008 8-Channel 10-Bit Analog to Digital Converter\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.adafruit.com/products/998\"\u003eRaspberry Pi model B\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.adafruit.com/products/2203\"\u003e16-pin IC socket\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.adafruit.com/products/344\"\u003eAssortment of heat shrink tubing\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.adafruit.com/products/937\"\u003ePanel mount to Micro USB adapter\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.sparkfun.com/products/11508\"\u003e10K\u03a9 1/4W LED resistor\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.adafruit.com/products/1148\"\u003eHalf-size Perma-Proto Raspberry Pi Breadboard PCB Kit\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.sparkfun.com/products/9594\"\u003e5mm Yellow LED\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e1/8\u0026rdquo; panel mount audio jack\u003c/li\u003e\n\u003cli\u003e10uF electrolytic decoupling capacitor\u003c/li\u003e\n\u003cli\u003e33\u03a9 1/2W burden resistor\u003c/li\u003e\n\u003cli\u003e2x 470K\u03a9 1/2W voltage divider resistors\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.sparkfun.com/products/11005\"\u003e30A non-invasive current sensor\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.sparkfun.com/products/11367\"\u003e22 AWG Solid Core Hook Up Wire\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e5x7 photo box, from The Container Store\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.amazon.com/gp/product/B00B588HY2\"\u003e8 GB Class 10 SDHC card\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.amazon.com/dp/B005CLMJLU\"\u003eEdimax EW-7811Un Wireless Nano USB Adapter\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e6x Nylon screws washers and nuts\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.monoprice.com/Product?p_id=8617\"\u003e8\u0026rdquo; AC Cord Clips\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.monoprice.com/Product?c_id=102\u0026amp;cp_id=10242\u0026amp;cs_id=1024201\u0026amp;p_id=3645\u0026amp;seq=1\u0026amp;format=2\"\u003eHDMI to Mini HDMI adapter\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.monoprice.com/Product?c_id=104\u0026amp;cp_id=10419\u0026amp;cs_id=1041909\u0026amp;p_id=3654\u0026amp;seq=1\u0026amp;format=2\"\u003e6\u0026rsquo; Mini HDMI to HDMI Cable\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"http://www.acehardware.com/product/index.jsp?productId=29313236\"\u003e10\u0026rsquo; USB A Male to B Male Cable\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eRelated reading: \u003ca href=\"https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol\"\u003eHyper Text Coffee Pot Control Protocol\u003c/a\u003e\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2013-07-23:gottago",
            "url": "https://command-tab.com/2013/07/23/gottago/",
            "title": "GottaGo",
            "date_published": "2013-07-23T07:00:00Z",
            "content_html": "\u003cp\u003eWorking at \u003ca href=\"http://www.blackboard.com/mobile-learning/index.aspx\"\u003eBlackboard Mobile\u003c/a\u003e making unique mobile apps is fun, but occasionally it\u0026rsquo;s interesting to do something completely different at work, just to see what you can come up with. To that end, we recently hosted our first Hackathon, where small teams of co-workers had 24 straight hours to create a project of any theme using resources available inside our outside of the office, and the results would be judged by our peers. One of the other benefits of working in a growing industry is that we\u0026rsquo;re expanding our staff almost weekly. Unfortunately, though, that means that the building we\u0026rsquo;re in is less and less able to handle the increasing capacity. Specifically, the bathrooms are occupied more frequently, resulting in either a return trip to your desk only to try again later, or an awkward wait of unknown duration.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"header\" src=\"https://r2.command-tab.com/gottago_header.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eWorking with \u003ca href=\"https://twitter.com/JMT3\"\u003eJoe Taylor\u003c/a\u003e and \u003ca href=\"https://twitter.com/eclittlejohn\"\u003eEric Littlejohn\u003c/a\u003e, our Hackathon project set out to make the office bathroom availability more visible and accessible through a combination of hardware and software. The piece of the project that lets this all work is a microswitch installed inside each door jamb, such that when the locking bolt is engaged, the switch is tripped. That way, we can do anything with resulting data, knowing that when the door is locked, the room is in use. Running wire down through the hollow metal trim was tedious and time consuming, and involved a lot of false starts and fishing around with a straightened coat hanger, but we finally got a run of wire inside each frame.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"door switch\" src=\"https://r2.command-tab.com/gottago_switch.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eOn each office floor there are two bathrooms side by side, and the pair of switches inside the door jambs are wired to a single \u003ca href=\"http://arduino.cc/\"\u003eArduino\u003c/a\u003e fitted with an \u003ca href=\"http://arduino.cc/en/Main/ArduinoEthernetShield\"\u003eEthernet Shield\u003c/a\u003e for network connectivity. The Arduino samples the switches many times per second, providing near-instant feedback.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"arduinno board\" src=\"https://r2.command-tab.com/gottago_arduino.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eAfter \u003ca href=\"http://www.labbookpages.co.uk/electronics/debounce.html\"\u003edebouncing\u003c/a\u003e the switch input signal over about 50 milliseconds, the Arduino waits for a definitive change in state \u0026ndash; from locked to unlocked, or unlocked to locked \u0026ndash; before illuminating LED lights on the wall.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"wall lights\" src=\"https://r2.command-tab.com/gottago_lights.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eAfter the light corresponding to the now-occupied bathroom is lit, the Arduino also performs an HTTP POST, sending the event details (floor level, which room, and current occupancy state) to an in-house webserver running Node.js and MongoDB. The webserver records the data and makes it visible on a web page for viewers to check the availability digitally, for those who can\u0026rsquo;t see the wall mounted lights from their seating position.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"event sequence animation\" src=\"https://r2.command-tab.com/gottago.gif\" /\u003e\u003c/p\u003e\n\u003cp\u003eIf you\u0026rsquo;d like to employ a project like this, the code we hacked together is \u003ca href=\"https://github.com/BbMobile/GottaGo\"\u003eavailable on GitHub\u003c/a\u003e, and the wiring is rather straightforward:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAll components share a common ground\u003c/li\u003e\n\u003cli\u003eLED anodes are wired to \u003ccode\u003eroom_a_led_pin\u003c/code\u003e and \u003ccode\u003eroom_b_led_pin\u003c/code\u003e and brought high when doors are locked, and low when unlocked\u003c/li\u003e\n\u003cli\u003eSwitches bring \u003ccode\u003eroom_a_switch_pin\u003c/code\u003e and \u003ccode\u003eroom_b_switch_pin\u003c/code\u003e low when triggered, and the Arduino uses the \u003ccode\u003eINPUT_PULLUP\u003c/code\u003e pinMode for the unlocked state\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eOur Hackathon project came in at second place, losing to an as-yet-unannounced software project, but we had a lot of fun staying up and hacking all night!\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2013-06-06:adventures-with-nest",
            "url": "https://command-tab.com/2013/06/06/adventures-with-nest/",
            "title": "Adventures with Nest",
            "date_published": "2013-06-06T07:00:00Z",
            "content_html": "\u003cp\u003eI recently purchased a pair of \u003ca href=\"https://nest.com\"\u003eNest Learning Thermostats\u003c/a\u003e for my new home. Compared to the white brick style Honeywell thermostats that came with the place, the Nest is so much more advanced. It does temperature learning, auto-away, and remote control over Wi-Fi from the web and iOS devices. It also has a color LCD and just generally looks beautiful on the wall with its brushed stainless steel housing.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"nest thermostat\" src=\"https://r2.command-tab.com/nest.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eInstalling the Nest is pretty straightforward with a modern forced air heating and cooling system:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eRemove the old thermostat and mounting plate from the wall\u003c/li\u003e\n\u003cli\u003eDisconnect the wires\u003c/li\u003e\n\u003cli\u003ePatch and paint any holes\u003c/li\u003e\n\u003cli\u003eInstall the Nest mounting base and connect the wires\u003c/li\u003e\n\u003cli\u003ePop the Nest onto the base and configure the software\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eMy initial install went well physically, but not long after, I discovered that the Nest would regularly run out of battery power. I quickly learned that due to how the HVAC circuits are arranged, the Nest can only draw power while the system is running. When the system is not busy heating, cooling, or running the fan, the Nest is left to run under its own battery power. And in sunny California during the springtime, the system doesn\u0026rsquo;t run often enough to let the Nest keep a charge. Several times per day, I would have to unplug the Nest from its base and charge it over micro USB. Not a great solution.\u003c/p\u003e\n\u003cp\u003eReading more about the Nest and HVAC circuitry, I found that there is a solution for situations like this. A \u0026ldquo;common wire\u0026rdquo; that provides a path back to the HVAC controller would allow the Nest to draw the power it needs while not running any systems. As luck would have it, my system provided this common wire, but connecting it to the Nest had no effect on the battery. More telling was the fact that the Nest did not detect that the wire was connected.\u003c/p\u003e\n\u003cp\u003eSo, I decided to find out what was at the other end of that common wire. I put up a ladder and ventured into the attic of my home and scouted around the furnace. On top of it, inside an easily-opened metal enclosure, was the thermostat controller, a ZTech ZTE2S. Double checking the \u003ca href=\"https://r2.command-tab.com/zte2s_wiring.pdf\"\u003ewiring diagram\u003c/a\u003e and comparing it with the wires on the left (coming from the Nests), it\u0026rsquo;s clear that the blue common wire is simply not connected to the controller. In the photo below, you can see that it\u0026rsquo;s clipped short, close to the brown jacket covering the bundle of five wires.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"wiring before with blue wire disconnected\" src=\"https://r2.command-tab.com/nest_before.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eReconnecting the wire was a matter of disconnecting the wires that were already connected, snipping them all to the same length, and stripping a little plastic off the end so that all five can be connected to the HVAC controller.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"wiring after with blue wire connected\" src=\"https://r2.command-tab.com/nest_after.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eA few hours after leaving the Nest installed with the common wire attached and the HVAC controller all closed up, its battery has fully charged and the features work great.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2011-05-12:simulating-slow-internet-for-ios-testing",
            "url": "https://command-tab.com/2011/05/12/simulating-slow-internet-for-ios-testing/",
            "title": "Simulating Slow Internet for iOS Testing",
            "date_published": "2011-05-12T07:00:00Z",
            "content_html": "\u003cp\u003eApple\u0026rsquo;s iOS Simulator is an acceptable environment for testing development code, but when users purchase your finished app from the App Store, they\u0026rsquo;ll be running it on real hardware, particularly on networks that are likely much less reliable than your home or office internet.\u003c/p\u003e\n\u003cp\u003eTo ensure your app performs well under real-world conditions, you can load up the code on a device and go outside, but then you can\u0026rsquo;t debug as easily. And even if you bring your MacBook Air with you, what if your Verizon iPhone is everything you hoped, and it performs admirably on the worst of days? To get around all of this, you can approximate an unreliable network with \u003ca href=\"http://mschrag.github.com\"\u003eSpeedLimit\u003c/a\u003e. SpeedLimit is a System Preferences pane for intentionally and selectively slowing down specific ports and domains.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"speedlimit window\" src=\"https://r2.command-tab.com/speedlimit.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eDownload and install SpeedLimit, add one or more hosts (separated by commas, as seen above), select a target speed, and click Slow Down. Subsequent network requests matching the criteria you set will be throttled, giving you time to go all out testing your app\u0026rsquo;s performance and error handling. Does it crash when users hit the Back button while a UITableView is loading? Does it lock the UI while downloading avatars or thumbnails? SpeedLimit lets you find out, and be confident in your networking code.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2009-09-14:how-to-find-the-right-windows-driver",
            "url": "https://command-tab.com/2009/09/14/how-to-find-the-right-windows-driver/",
            "title": "How to Find the Right Windows Driver",
            "date_published": "2009-09-14T07:00:00Z",
            "content_html": "\u003cp\u003eWhen setting up a new Windows machine, whether it\u0026rsquo;s Windows 2000 all the way up through Windows 7, you\u0026rsquo;ll occasionally run into an issue where you need drivers for a system or PCI device that you just can\u0026rsquo;t seem to find. To make matters worse, you don\u0026rsquo;t know which company made the device, so you don\u0026rsquo;t even know where to start looking for drivers. Should you go to Dell\u0026rsquo;s site? The motherboard manufacturer? Persistent \u0026ldquo;Unknown device\u0026rdquo; entries in the Windows Device Manager are a plague upon even the most seasoned techs. Here\u0026rsquo;s a tip to get your driver hunt moving in the right direction.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eFind Out Who Made the Device\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eFiguring out which company made the device(s) in question is the first step towards getting it working. Start by opening the Windows Device Manager. My preferred quick way of doing this is clicking Start, Run, type \u003ccode\u003edevmgmt.msc\u003c/code\u003e, and pressing Enter. Once there, choose the device in question and right click it, and select Properties. Select the Details tab to see something like the view below:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"windows device manager\" src=\"https://r2.command-tab.com/windows_device_manager.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eNote the PCI \u003ccode\u003eVEN\u003c/code\u003e and \u003ccode\u003eDEV\u003c/code\u003e 4-character identifiers. PCI, USB, and many other system devices have Vendor and Device IDs. The Vendor ID is specific to the manufacturer, like Broadcom or nVIDIA. The Device ID is specific to the particular make or model of device you have. These are expressed in hexadecimal (0 through 9 plus A through F), so don\u0026rsquo;t be surprised to see letters there, as well. Some common Vendor IDs are \u003ccode\u003e8080\u003c/code\u003e and \u003ccode\u003e8086\u003c/code\u003e for Intel, \u003ccode\u003e0A5C\u003c/code\u003e for Broadcom, \u003ccode\u003e10DE\u003c/code\u003e for nVIDIA, \u003ccode\u003e1002\u003c/code\u003e for ATI, and \u003ca href=\"http://www.pcidatabase.com/reports.php?type=tab-delimeted\"\u003emany more\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eLook Up Vendor and Device IDs\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eA common way to express both the Vendor and Device IDs in a single string is 1022:2000, Vendor ID first. Combine your Vendor and Device IDs in this manner, and wrap it with quotes: \u0026ldquo;1022:2000\u0026rdquo;. Google that, and you should quickly figure out who made your \u0026ldquo;Unknown device\u0026rdquo; and what model it is. With this knowledge, you can either find the appropriate driver on your computer manufacturer\u0026rsquo;s website (Dell makes a good note of which manufacturer\u0026rsquo;s devices they use for a particular system), or you can visit the device manufacturer\u0026rsquo;s website directly.\u003c/p\u003e\n\u003cp\u003eI hope this information can help those looking to simply get their hardware working under Windows, whether it\u0026rsquo;s running on a Mac or PC.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2009-07-05:macally-icekey-usb-2-0",
            "url": "https://command-tab.com/2009/07/05/macally-icekey-usb-2-0/",
            "title": "MacAlly IceKey USB 2.0",
            "date_published": "2009-07-05T07:00:00Z",
            "content_html": "\u003cp\u003eMacAlly has been producing the same IceKey keyboard since 2003, and while it\u0026rsquo;s a solid performer featuring comfortable low profile scissor keys and extra USB ports, it still ships with a maddeningly slow internal USB 1.1 hub. While this early USB specification is plenty fast for a keyboard alone, it throttles back speeds of all attached devices like flash drives, iPods, and digital cameras. Copying an music album or two can take several minutes over USB 1.1, whereas today\u0026rsquo;s USB 2.0 takes only seconds. With USB 2.0 as today\u0026rsquo;s ubiquitous standard and USB 3.0 just around the corner, it\u0026rsquo;s disappointing that MacAlly has yet to update the IceKey to include a faster hub. Luckily, you can take matters into your own hands. Here\u0026rsquo;s how to install a high speed hub inside the keyboard while maintaining MacAlly\u0026rsquo;s elegant factory appearance.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"macally icekey keyboard\" src=\"https://r2.command-tab.com/macally_icekey_start.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eWhat You\u0026rsquo;ll Need\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ea MacAlly IceKey\u003c/li\u003e\n\u003cli\u003ea small, narrow USB hub (a cheap Targus hub worked fine for me)\u003c/li\u003e\n\u003cli\u003ea screwdriver set\u003c/li\u003e\n\u003cli\u003ea soldering iron, solder, and spare wire\u003c/li\u003e\n\u003cli\u003ea pocket knife (I\u0026rsquo;m not sure any project I\u0026rsquo;ve done \u003cem\u003edidn\u0026rsquo;t\u003c/em\u003e require this\u0026hellip;)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eOpen the Hub\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eUSB hubs generally aren\u0026rsquo;t too complicated to open, and this Targus on is no exception. A single screw on the underside holds together the hub\u0026rsquo;s two plastic halves, which snap apart with little effort. Write a note or take a picture to document the wire colors and order relevant to the orientation of the board inside \u0026ndash; it will come in handy later.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"usb hub board\" src=\"https://r2.command-tab.com/macally_usb_hub_board.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOpen the Keyboard\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThe MacAlly IceKey is slightly trickier to get apart, but not much. Remove all the obvious screws on the bottom of the keyboard, including the one under the \u0026ldquo;Do Not Remove\u0026rdquo;/Quality Control/Warranty sticker. Then, flip open the pivoting feet to expose two more screws covered by a protective piece of rubber. The final two screws are under the front rubber feet.\u003c/p\u003e\n\u003cp\u003eStarting with the keyboard upright and facing you, begin unsnapping the plastic hooks around the perimeter starting at the front middle. A plastic pry tool might come in handy, but isn\u0026rsquo;t required. Once the top is removed, you can clearly see all the important electronics, including a very common Cypress USB controller chip.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"keyboard controller\" src=\"https://r2.command-tab.com/macally_keyboard_controller.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"left port\" src=\"https://r2.command-tab.com/macally_keyboard_leftport.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eTest Fit Everything\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eJust to make sure the rest of this modification is physically possible, fit the USB hub board in the open space at the top of the keyboard and set the keyboard bezel on top. Luckily, the IceKey has plenty of room to spare. I was planning to have to remove the USB ports from the hub board to make everything fit, but there was so much extra space that I didn\u0026rsquo;t even have to go to that length.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUnhook the Keyboard\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCarefully pull the keyboard ribbon cables straight away from their matching plugs on the controller board. Gently flip the keyboard pad over, and unscrew the two short ground wires to completely free the keyboard keys from the plastic housing. Set it aside for later; it does not need to be modified \u0026ndash; all the action happens on the two remaining circuit boards. Unscrew both boards to get at the backs of each.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"ribbon cables\" src=\"https://r2.command-tab.com/macally_keyboard_ribbon_cables.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eCut Wires\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCut the gray ribbon that leads from the controller board to the left port. Since that wire only provides USB 1.1 speed, we won\u0026rsquo;t be using it. You\u0026rsquo;ll note that it has two extra wires that run to an unpopulated LED on the left board, so we can skip those when doing the re-wiring. (I wonder what MacAlly had in store for that, or if this keyboard is a \u0026ldquo;port\u0026rdquo; from another language or something?)\u003c/p\u003e\n\u003cp\u003eUnplug the USB cord from the controller board and cut off the connector. This cord needs to run to the input on the new USB hub, and not to the input on the keyboard controller board where it currently connects.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eCut Traces\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eSince the right port also needs USB 2.0 speeds, it too will need to be disconnected from its USB 1.1 source. However, it is soldered directly onto the controller board and is effectively hard-wired into the slowness. This is perhaps the trickiest part of the whole project: desolder the USB connector and use a knife to scrape away the traces that run to the port. Some are on top of the board, and some are on the bottom. (You might be able to get away with cutting the traces without removing the port, as a little bit of the traces are exposed on the top before routing into electronic components, but you\u0026rsquo;ll want to test with a multimeter and make sure you\u0026rsquo;ve done this successfully.) Once all four traces to the port are cut, re-solder the USB port in place (if you removed it).\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"cut traces\" src=\"https://r2.command-tab.com/macally_usb_traces_cut.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eRe-wire the Keyboard Controller and Ports\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eHere\u0026rsquo;s a simple before and after block diagram to help your wiring layout:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"wiring diagram\" src=\"https://r2.command-tab.com/macally_icekey2_diagram.gif\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSolder Keyboard Cord to Hub Input\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eStrip about an inch of plastic from the cut end of the keyboard cord to expose its individual wires, and strip just a millimeter or two from each of those. Using your note from earlier, solder the keyboard wires to the matching USB hub input connections. On this Targus hub, the wires were in the same order as the standard \u003ca href=\"https://images.google.com/images?q=USB%20pinout\"\u003eUSB pinout\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSolder Keyboard Controller to a Hub Port\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eSolder four wires from the keyboard input port (where the cord originally connected to) to one of the USB hub ports, effectively making the keyboard controller into one of four devices on the hub. Previously, the keyboard supplied its own hub, but we\u0026rsquo;re bypassing it altogether. Luckily, most everything is either color coded or silkscreen labeled on the circuit boards (\u003ccode\u003eV/5V\u003c/code\u003e is red, \u003ccode\u003eD-\u003c/code\u003e is green, \u003ccode\u003eD+\u003c/code\u003e is white, and \u003ccode\u003eG/GND\u003c/code\u003e is black).\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSolder Keyboard USB Ports to Hub Ports\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eSolder wire from the left USB port board to another free USB hub port, making sure to get the order correct. With the traces cut on the right port, run wire from the connections under the board to yet another free hub port. You should end up with a hub layout like this:\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"hub wires\" src=\"https://r2.command-tab.com/macally_keyboard_hub_wires.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eTest and Close It Up\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eWith each new component wired up, double-check your connections and plug it in. Initially, my first test failed and Windows complained about a malfunctioning USB device (I tested it on an old PC, just in case I shorted out the computer\u0026rsquo;s USB controller. I\u0026rsquo;d rather fry an old computer than my new iMac!) The key to making everything work properly was to reconnect those two shared ground wires from early on \u0026ndash; the keyboard must have a common ground with the controller and hub!\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"completed wiring\" src=\"https://r2.command-tab.com/macally_keyboard_test.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eOnce it works, secure all the wires and boards. I used a few short pieces of electrical tape to stop everything from bouncing around, too. Snap the plastic top back on, replace all the screws, and enjoy your USB 2.0 MacAlly IceKey!\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2009-06-14:boot-camp-drivers-for-imac-early-2009",
            "url": "https://command-tab.com/2009/06/14/boot-camp-drivers-for-imac-early-2009/",
            "title": "Boot Camp Drivers for iMac (Early 2009)",
            "date_published": "2009-06-14T07:00:00Z",
            "content_html": "\u003cp\u003eApple\u0026rsquo;s newest iMacs are a fast set of machines and run Windows faster than any PC I\u0026rsquo;ve ever used, but unfortunately, Apple has yet to update Boot Camp with the required drivers to support the latest and greatest components. Mac OS X ships with the necessary software and works as expected, but Windows XP is met with some trouble. Right away, you\u0026rsquo;ll notice that your graphics resolution is set to a paltry 800x600, and you have no sound output as well. Here\u0026rsquo;s how to get those systems working until Apple can provide an \u0026ldquo;official\u0026rdquo; fix:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eGraphics Drivers\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eVisit \u003ca href=\"http://www.nvidia.com\"\u003enVidia\u003c/a\u003e and download the \u0026ldquo;GeForce 9M Series (Notebooks)\u0026rdquo; driver package, as this is graphics chipset in the Early 2009 iMacs. Run the downloaded setup utility, next-next-nexting your way through the steps, and reboot at the end when prompted. Upon restart, you\u0026rsquo;ll be able to properly max out your display to the iMac\u0026rsquo;s native resolution.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAudio Drivers\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eBoot Camp 2.1 actually ships with RealTek HD audio drivers, as evidenced by the lack of a yellow exclamation mark for this system in Windows\u0026rsquo; Device Manager, but they don\u0026rsquo;t seem to work properly, since there\u0026rsquo;s no sound output. Visit \u003ca href=\"http://www.realtek.com.tw/downloads\"\u003eRealTek\u003c/a\u003e and download the \u0026ldquo;High Definition Audio Codecs\u0026rdquo; driver package for your OS. In this instance, I downloaded \u0026ldquo;Windows 2000, Windows XP/2003(32/64 bits) Driver only (Executable file)\u0026rdquo;, since I\u0026rsquo;m running Windows XP Pro SP2. Run this setup utility as well, rebooting again when done. After restarting, you should be greeted with Windows\u0026rsquo; standard login sound, confirming the install worked.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUpdate:\u003c/strong\u003e The Mac OS X 10.6 Snow Leopard disc includes Boot Camp drivers for these iMacs. The Snow Leopard disc is a hybrid image: it provides the Mac OS X installer when viewed under a Mac OS X system, but shows Windows drivers when viewed in Windows. Just run the setup in Windows right off the disc, and you should be set.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2009-03-22:dig-into-iphone-apps",
            "url": "https://command-tab.com/2009/03/22/dig-into-iphone-apps/",
            "title": "Dig into iPhone Apps",
            "date_published": "2009-03-22T07:00:00Z",
            "content_html": "\u003cp\u003eSo you\u0026rsquo;re curious about the contents of iPhone and iPod Touch apps, including artwork, sounds, and more? Here\u0026rsquo;s how to dig into an application and see what goodies are hidden inside. Standard copyrights still apply.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSync Your Apps with iTunes\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eAssuming you already have the target application on your iPhone or iPod Touch (just \u0026ldquo;iPhone\u0026rdquo; from this point forward for brevity\u0026rsquo;s sake), simply sync your iPhone with your Mac or PC. Doing so will backup your device and transfer any purchased applications in both directions. With the target application now on your computer, navigate to your iTunes \u0026ldquo;Mobile Applications\u0026rdquo; folder, where iTunes typically does its own file housekeeping. Under Mac OS X, the default location is \u003ccode\u003e/Users/yourname/Music/iTunes/Mobile Applications/\u003c/code\u003e.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUnzip an App\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eCopy your target \u003ccode\u003e.ipa\u003c/code\u003e-suffixed application to a different location, ensuring that the original stays in the Mobile Applications folder to keep iTunes happy. To get inside the application, rename its extension to \u003ccode\u003e.zip\u003c/code\u003e. Open the zip file, and you will have access to the guts of the app (except the source code, of course).\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eHigh-res App Artwork\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eDirectly inside the unzipped application folder, you\u0026rsquo;ll find a file named \u003ccode\u003eiTunesArtwork\u003c/code\u003e, with no extension. A hex editor revealed that the file is typically a jpeg image, so rename it to include \u003ccode\u003e.jpg\u003c/code\u003e at the end, and you\u0026rsquo;ll end up with the same 512x512 pixel artwork displayed by iTunes when browsing downloaded Applications. To get at other resources, open up the adjacent \u0026ldquo;Payload\u0026rdquo; folder, and you\u0026rsquo;ll find a \u003ccode\u003e.app\u003c/code\u003e file \u0026ndash; the application bundle that runs on the iPhone. Right- or Control-click on the \u003ccode\u003e.app\u003c/code\u003e, and choose \u0026ldquo;Show Package Contents\u0026rdquo; to open up the bundle.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eSounds\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eSounds are typically found among the many resources directly inside the application as files with extensions like \u003ccode\u003e.caf\u003c/code\u003e, \u003ccode\u003e.mp3\u003c/code\u003e, \u003ccode\u003e.aif\u003c/code\u003e, and \u003ccode\u003e.m4a\u003c/code\u003e. At this point, the organizational structure is up to the application\u0026rsquo;s developer, so you may need to look around a little. Leopard\u0026rsquo;s QuickLook feature is a boon in times like this, helping assess a file\u0026rsquo;s purpose without opening half a dozen applications.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eOther Graphics\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eAlso nestled inside iPhone applications are many of the graphics used throughout the app. It\u0026rsquo;s possible that some may be drawn by code, but complex graphics are generally stored as images. However, viewing the images isn\u0026rsquo;t as easy as renaming the files as before. This will be a bit trickier, as the iPhone works some magic on the images before finishing the app build process, leaving images in an iPhone-optimized state. Fortunately, the process can be reversed with a little bit of Terminal trickery:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eCopy all \u003ccode\u003e.png\u003c/code\u003e images to a new folder elsewhere. Images of other formats (\u003ccode\u003e.jpg\u003c/code\u003e, \u003ccode\u003e.gif\u003c/code\u003e, etc.) should be readily viewable.\u003c/li\u003e\n\u003cli\u003eDownload David Watanabe\u0026rsquo;s \u003ca href=\"http://www.newsfirex.com/blog/?p=176\"\u003emodified iPhonePNG\u003c/a\u003e command-line application, unzip the archive, and open up Terminal from your /Applications/Utilities folder.\u003c/li\u003e\n\u003cli\u003eType \u003ccode\u003ecd\u003c/code\u003e, then drop the iPhonePNG folder into the Terminal, and tap Return to switch to that folder.\u003c/li\u003e\n\u003cli\u003eType \u003ccode\u003e./iPhonePNG\u003c/code\u003e, drop the folder of encoded images into the Terminal, and tap Return to decode the whole folder full of images.\u003c/li\u003e\n\u003cli\u003eThe output folder sites beside iPhonePNG, so type \u003ccode\u003eopen .\u003c/code\u003e and tap Return (open space dot) to open the current folder (a dot, in Unix terms) in the Finder. Open the decoded images folder and have a look around!\u003c/li\u003e\n\u003c/ol\u003e"
        },
        {
            "id": "tag:command-tab.com,2009-01-06:ipod-screen-scratch-removal-revisited",
            "url": "https://command-tab.com/2009/01/06/ipod-screen-scratch-removal-revisited/",
            "title": "iPod Screen Scratch Removal Revisited",
            "date_published": "2009-01-06T08:00:00Z",
            "content_html": "\u003cp\u003eSeveral years ago, I recommended RadTech\u0026rsquo;s \u003ca href=\"http://www.radtech.us/Products/IceCreme.aspx\"\u003eIceCreme\u003c/a\u003e as a great solution for cleaning up your iPod\u0026rsquo;s scratched-up screen. While I still stand by my results and recommendation, IceCreme isn\u0026rsquo;t the sort of thing you can find at a nearby store, and is also a little pricey. Removing scratches from iPods and other pocket-bound electronics remains a common problem, so I thought it would be worthwhile to test some of the other available options. Additionally, since nicks and scratches occur on more than just the screen, we\u0026rsquo;ll also test the solutions elsewhere on an iPod. For this little experiment, I chose three solutions offering varying levels of abrasiveness: Colgate toothpaste, Brasso metal polish, and Easy-Off oven cleaner. All three promise to leave their intended surfaces shiny and clean, and in the case of the latter two, free of scratches. We\u0026rsquo;ll see how each fares when put to use on both the front plastic and back metal of an iPod.\u003c/p\u003e\n\u003cp\u003eTo keep things clear, each polish will be used in a masked-off area, hopefully leaving a clear division among the results. The target iPod is an already well-used 4G 20GB iPod, with most of its still working inner parts removed and replaced with padding just to help sustain its form while being polished. Donated to the cause, this iPod will be beat up even further, with even layers of light scratches, heavy scratches, and deep cuts, simluating everything from normal wear to keychain induced destruction. It has surely seen better days, and is now destined for that great Apple Store in the sky, all in the name of science. I started with Brasso first, since it has been recommended many times since my last scratch removal post, both by commenters and firsthand accounts. If you\u0026rsquo;re attempting this yourself, be sure to work in a well ventilated area, as Brasso smells very strongly of ammonia, and might start to irritate your eyes after a short while!\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"scratched ipod with brasso\" src=\"https://r2.command-tab.com/scratch_ipod_brasso.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eAfter only five minutes of polishing, the results were quite good, with nearly all of the light and medium scratches completely removed from the screen area. Deeper cuts remained, though their rough edges were significantly smoother.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"polished ipod with brasso\" src=\"https://r2.command-tab.com/scratch_ipod_brasso_done.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eToothpaste was next on the list, and while it left the iPod minty fresh with a sparkling shine, its scratch-reducing effects were barely noticeable. Due to its sticky consistency, it was also more difficult to polish with than the more liquid Brasso, yielding poorer results for double the effort \u0026ndash; a total flop. Oven cleaner was last, and I really had no idea what to expect with it. Claiming to leave glassy surfaces shiny and free of scratches, it sounded like a possible winner. As it turns out, it\u0026rsquo;s not much more than a repackaged kitchen cleaner, resulting in a streak-free but still heavily scratched iPod. I\u0026rsquo;ll end up cleaning my glass top oven with this one, and nothing else. With the front of the iPod clearly showing Brasso as the top choice, it was time to see what worked best on the scratched metal backing of the iPod.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"ipod with scratched back\" src=\"https://r2.command-tab.com/scratch_ipod_scratched_back.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eAgain, after just a few minutes with each polish, Brasso came out on top, while the other two trailed woefully behind. The Brasso-polished back still had quite a few scratches, though far less pronounced than when I started. All of them, including the deep cuts, had a very slick feel, whereas the others still left the surface pretty rough.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"scratch comparison\" src=\"https://r2.command-tab.com/scratch_back_comparison.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eConvinced that Brasso was the right choice, I went back and finished off the front, cleaning up all but the most severe marks on the screen.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"ipod front\" src=\"https://r2.command-tab.com/scratch_ipod_front.jpg\" /\u003e\u003c/p\u003e\n\u003cp\u003eGiven the results of my tests, I can easily recommend Brasso as a great iPod polishing solution that can be had for under $3 at your local stores.\u003c/p\u003e"
        },
        {
            "id": "tag:command-tab.com,2008-12-21:learning-cocoa-for-the-iphone",
            "url": "https://command-tab.com/2008/12/21/learning-cocoa-for-the-iphone/",
            "title": "Learning Cocoa for the iPhone",
            "date_published": "2008-12-21T08:00:00Z",
            "content_html": "\u003cp\u003eThese last few weeks, I\u0026rsquo;ve been teaching myself Cocoa to learn what makes Mac OS X and iPhone OS apps tick. While Objective-C is quite a departure from my usual web development world, it has quickly become one of my favorite languages, as it takes care of much of the drudgery of pure C and has plenty of useful frameworks to get your application up and running quickly. Here are some of the best resources I\u0026rsquo;ve found so far:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"http://cocoadevcentral.com/\"\u003eCocoa Dev Central\u003c/a\u003e and \u003ca href=\"http://www.cocoalab.com/?q=becomeanxcoder\"\u003eBecome an Xcoder\u003c/a\u003e are both excellent tutorials for beginners, written in a clear, straightforward manner. They also explain the ins and outs of memory management, which is critical on platforms like the iPhone and iPod touch.\u003c/li\u003e\n\u003cli\u003eStanford\u0026rsquo;s \u003ca href=\"https://cs193p.sites.stanford.edu/\"\u003eCS193P lecture notes\u003c/a\u003e and examples have proven to be one of the best resources for learning Cocoa, particularly for the iPhone. These notes and tests offer Cocoa Touch in bite-size chunks, with a little bit of \u0026ldquo;on your own\u0026rdquo; work to ensure you know your stuff before moving on.\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://developers.google.com/code-search\"\u003eGoogle Code Search\u003c/a\u003e is a good last resort for examples of how others are using a small bit of code or a particular class. For more accurate results, append \u0026ldquo;lang:objectivec\u0026rdquo; to your search string to narrow results to only Objective-C code.\u003c/li\u003e\n\u003c/ul\u003e"
        },
        {
            "id": "tag:command-tab.com,2008-12-16:consolas-cursor-fix",
            "url": "https://command-tab.com/2008/12/16/consolas-cursor-fix/",
            "title": "Consolas Cursor Fix",
            "date_published": "2008-12-16T08:00:00Z",
            "content_html": "\u003cp\u003eIf you\u0026rsquo;ve attempted to use Consolas as your choice programming font on the Mac, you may have noticed (\u003ca href=\"/2008/02/19/finding-the-perfect-programming-font/\"\u003eas I did\u003c/a\u003e) an odd issue with the font, where your blinking cursor hangs much lower than the current line. Oddly enough, this little issue only seems to affect Mac OS X. Even the Consolas set that ships with Microsoft Office 2008 has the same problem! Yet, when the same exact font file is used under Windows, the cursor position is correct.\u003c/p\u003e\n\u003cp\u003eJohn Gruber \u003ca href=\"http://daringfireball.net/linked/2008/12/15/bbedit-91\" title=\"Daring Fireball: BBEdit 9.1\"\u003ementioned\u003c/a\u003e that \u003ca href=\"http://www.barebones.com/products/bbedit/demo.html\"\u003eBBEdit 9.1\u003c/a\u003e now ships with Consolas as its default font, so I decided to see if it had the same cursor problem I had experienced in the past. As it turns out, BBEdit\u0026rsquo;s version of Consolas works just fine, as seen in the image above. However, it doesn\u0026rsquo;t include the other styles like Consolas Bold, Italic, and Bold Italic.\u003c/p\u003e\n\u003cp\u003eThrough one way or another, the copy of Consolas that ships with BBEdit 9.1 is different than the one that ships with Microsoft Office 2008. To make system-wide use of the working version, \u003ca href=\"http://www.barebones.com/products/bbedit/demo.html\"\u003edownload BBEdit 9.1\u003c/a\u003e, mount the disk image, and navigate to:\u003c/p\u003e\n\u003cp\u003e(Control-click BBEdit, and choose \u0026ldquo;Show Package Contents\u0026rdquo; to get inside the application bundle): \u003ccode\u003eBBEdit.app/Contents/Resources/Fonts/consola.ttf\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eCopy consola.ttf from BBEdit\u0026rsquo;s \u0026ldquo;Fonts\u0026rdquo; folder to your own Fonts folder at \u003ccode\u003e~/Library/Fonts\u003c/code\u003e, or \u003ccode\u003e/Library/Fonts\u003c/code\u003e if you want to make it available to everyone who has an account on your computer. Then, fire up your favorite editor, set Consolas as your preferred fixed-width font, and get coding!\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eUpdate:\u003c/strong\u003e Bare Bones has apparently changed the version of Consolas that ships with BBEdit versions later than 9.1, and they now have the cursor problem as well\u0026hellip;\u003c/p\u003e"
        }
    ]
}