Saturday, February 28, 2026

The '25 Chicago Bears Season

The Chicago Bears have not been a very good football team for years. The team suffered from collapses, inability to score on offense (traditionally relied on defense), poor coaching and a host of issues on the field.  Against our rivals, The Green Bay Packers we've suffered from late game collapse or just have not been competitive.  Playoff hopes often ended before the mid-point of the season.  

This all came to head in '24 season.  After starting out well at 4-2, a loss on a last second Hail Mary play to the Washington Commanders started team on an embarrassing 10-game losing streak that included seem them being dominated, playing like amateurs on the field, and multiple epic collapses.  The '24 season epitomizes the same old Bears moniker.  This was made all the more frustrating by the hope the fan base had with the number 1 overall pick of QB Caleb Williams and the #9  pick WR Rome Odunze.  

During this period:

The one saving grace was that they beat the Packers on the last game of the season with, of all things, a field goal by Carlos Santos as time expired.  That last win would carry the fan base through the entire off-season.  It was such a wonderful game for the Bears that the NFL uploaded the entire game to sustain the fans through the off season.

The 2025 Chicago Bears Season

Now comes the '25 season.  The Bears landed new head coach, Ben Johnson, which was by-far the biggest news for the Bears.   Some off-season signings addressing the O-line (a heavily criticized weakness through the previous season) gave some sparks of optimism, but lingering concerns about the Bears were still there.  Caleb Williams was called a bust, the draft choices were met with skepticism, and doubts about the front office and the organization continued the narrative of "how are the Bears going to screw it up this time?"  

Long time Bears fans, like any fan, always had a large vat of hope-ium but truly most fans are probably just praying (Da Pope, if you're listening) for a season of growth in in Ben Johnson's first year ("we'd be great if we reach 6-11 and show that we're competitive").   Here is a fan base that have seen decades of futility and have been conditioned to avoid expecting too much

With that, let's get into the season what was the '25 Chicago Bears

Week 1:  Minnesota Vikings vs Chicago Bears (0-1)

First game optimism.  Started out strong and getting fans excited to see the new Bears offense under Ben Johnson and initially it didn't disappoint with the Bears taking a 17-6 lead going into the the 4th quarter.  Fans felt positive seeing the growth they wanted to see, but in the 4th quarter JJ McCarthy lead the Vikings on multiple scoring drives to take a 27-17 at the 2:53 remaining mark.  3 consecutive TDs that made the Bears look confused on defense and the Viking QB looking like the star that the Vikings was hoping for.

Caleb Williams came on the field and drove down the field with his arm and legs to deliver a TD with 2:02 remaining despite initially having a TD overturned as short of the goal line.  On the next play, the Bears easily scores.   The Bears received one more possession with :02 seconds left but the Bears come out losing.

This script is similar to the Bear's history with the exception that after giving up 3 straight TDs that the Bears responded with a TD of their own and didn't just call it in.

Week 2:  Chicago Bears at Detroit Lions (0-2)

Ben Johnson returns to Detroit after been their OC for the past few years.  The Lions destroyed the Bears winning 52 to 21.  Oh, oh.  This is the the Bears that fans feared.  This wasn't a shoot-out loss.  The Bears got crushed and the only non-Bears thing about it is that they scored 21 points on 3 offensive TDs.

Fans are feeling like the Bears are still the Bears.  The media is seconding guessing everything the Bears do.  Is Johnson over his head?  Is Caleb a bust?  The Bears have no defense (can't stop the run, opposing QBs come out each games very clean), can't protect their own QB and no run game themselves.

Week 3: Dallas Cowboys at Chicago Bears (1-2)

Dallas comes into the game feeling good at 1-1 with their offense running as their fans hoped.  I'm sure they were looking forward to coming to a game against a team that have given buckets of points and can't pressure the QB.

Instead, the Bears came out with a convincing 31-14 win that included shutting out the Cowboys in the second half.  Bears fans were happy but also knows that the team does give them a nugget or two per season so they have

Week 4: Chicago Bears at Las Vegas Raiders (2-2)

Even by week 4, the Raider was not considered a good team but the Bears was only able to keep the game close.  Entering half time trailing 9-14 only after a third field with 53 seconds before the half, this was classic Bears.

The teams traded TDs in the third quarter which put the score at 16-21 and continued to trail 19-24 with 6:45 to go in the 4th.  The Bears took the lead with 1:34 remaining, but as familiar to most fans, their opponents marched down to field goal range.  Fans saw this happen plenty of time from both sides.  Either their opponents win the game on a field goal or the Bears will lose the game on missing or blocked field goals (per how they lost the previous year on consecutive weeks -- one being to the Packers).

But something very un-Bears-like happened this time.  The Bears blocked the field goal and preserved the 25-24 win.  Alright, alright, Bears fans can be on the positive side of this show for a week!

Bye Week

The Bears went into the bye week at 2-2 with lots of questions, but nobody thought there was anything special to this season.

Week 6: Chicago Bears at Washington Commanders (3-2)

Finally it is time to play the team that started the Bears on the 10-games downward spiral from last year.   For Bears fans this wasn't any other game.  This was necessary to start shedding the ghost of last season and beyond.  The Bears jumped to a 13-0 lead and then to 16-10, but in the 3rd quarter the Commanders took the 17-16 lead.  The Bears's offense with a good drive that resulted in a BLOCKED field goal.

The Commanders added another TD at the start of the fourth quarter for a 16-24 lead.  The Bears responded with a quick TD of their own with a big Caleb to Swift play.  The 2pt conversion failed so the Bears continued to trail 22-24 with 10:26 to go.  With 3:07 minutes to go, the Commanders fumbled a hand-off that was recovered by the Bears at the 44 yard line.  Relying mostly on the run, Caleb took the Bears down the field for a 38 yard FG attempt.  With their primary kicker out, Jake Moody, who just joined the team this week and was activated from the practice squad the same day, kicked the game winning field goal as time expired.  This is the same Jake Moody that the 49er's released because he missed big pressure kicks for them that came through in the wet and raining weather to seal the Bears' second comeback victory when trailing in the 4th quarter.

Week 7 New Orleans Saints at Chicago Bears (4-2)

The Saints visited the Bears for Week 7 resulting in a 26-14 win and a 4 game win streak.  The Saints were at the bottom of the standings at 1-6 so the Bears was expected to win this game at home.  During this win streak, the Bears have been getting turn-overs even though the overall defense still felt weak having given up plays while playing the bend-but-don't-break philosophy of defense.  The Bears run game has started establishing itself and the o-line has been protecting Caleb.  In this particular game, Caleb acknowledged he didn't play well but the overall team game was good and the Bears found themselves at 4-2 after starting 0-2.

Week 8 Chicago Bears at Baltimore Ravens (4-3)

The Baltimore Ravens came to Soldier Field on a 4-game losing streak and a backup QB.  Despite their record, the Ravens are still a respected team so fans felt it would be a good time to take a measure of where the Bears are.  The Bears lost 16-30 so yeah, same 'ol Bears...

Week 9 Chicago Bears at Cincinnati Bengals (5-3)

A much needed bounce-back game, the Bears kept it close going into half time trailing 17-20 even though the Bengals started with a kickoff return TD and gave up another big TD play from backup QB Joe Flacco.  The Bears missed a field goal near the end of the half that would've tied the game, but came out hot in the second half.  With just 4:53 left in the game, the Bears were up two TDs at 41-27, but over the course of around 4 minutes the Bengals were able to score 15 points (1 TD, 1 TD + 2pt conversion) to take the lead with 54 seconds remaining.  We're looking at a monumental collapse before our eyes and it brings back that there's no lead big enough for the Bears to lose.

Caleb took the field to lead a 4 plays 72 yard game winning drive in under a minute ending with a 58 yard TD pass to Colston Loveland.  This play and comeback was what everyone talks about and remembers but it needs to be remembered that the Bears was on the verge of a major collapse but Caleb settled the offense to go for a game winning drive which goes against the franchise history. 

The start of the Cardiac Bears.

Week 10 New York Giants at Chicago Bears (6-3)

The Giants were a team in disarray at 2-7 but was able to get big plays and led 20-10 with 10:19 left in the 4th quarter.  By this time, the Bears were developing a reputation for getting turn-overs (even as their bend-don't-break style has given up big plays), offense able to make big plays, they have a run game and they are winning games because of Caleb Williams.  That said, the Bears haven't come back from being down 10 points in the 4th since 2021.

With 3:56 left, Caleb throws a TD pass to Rome Odonze  to cut the lead to 3.  The defense played big with a sack to get the ball back to the offense.  Caleb took 1:06 to score a touchdown in 4 plays for 53 yards.  The defense sealed the victory and the Bears found themselves with another comeback win in the 4th quarter.

Week 11 Chicago Bears at Minnesota Vikings (7-3)

A rematch from week 1 had the Bears leading 16-3 going into the 4th quarter, but the Vikings scored 2 TDs in the 4th quarter to go up 16-17 with 50 seconds left.  On the ensuing kick-off, the special teams had a huge return.  Although Carlos Santos had missed a 45 yard FG earlier, he nails the 44 yard FG as time expires to give the Bears another come from behind win.

At this point, the way the Bears are winning is starting to look special.  Unlike previous teams, this team does make big plays regularly especially in the 4th quarter.  This is coming from the air and on the ground.  While the defense is still suspected to play a whole game, they are able to somehow come up with turn-overs.  There is a confidence by the players AND the fans that the Bears are never out of the game.  The Bears are winning in what some might say in miraculous ways.  In this game, the Bears got that one special team right as they needed it most and won the game in 50 seconds.

This game was Caleb Williams 5th fourth quarter comeback win of the season.

Week 12 Pittsburgh Steelers at Chicago Bears (8-3)

With growing confidence in the team, Bears fans were hoping that Aaron Rodgers will be the QB for the Steelers as they visited Soldier Fields.  Rodgers, as the QB for the Packers, had dominated the Bears and he wasn't shy about telling the city of Chicago, the fans and Bears that he "owned the Bears."  (Leave it on the field, Rodgers.  Try to stay classy if you can.)  Rodgers ended up not playing due to an injury.  The final score was Bear's 28-31 win and an 8-3 record.

Week 13 Chicago Bears at Philadelphia Eagles (9-3)

Doubters of the Bears were aplenty still despite winning 8 out of their 10 previous games.  People pointed out that the Bear's schedule was soft or that they were just "lucky" to have pulled out so many wins.  Finally, they said, the defending Superbowl Champions will show the world that the Bears are pretenders and not contenders.

Instead, the Bears ran the ball down the Eagles' throat with 2 players rushing over 100 yards and finishing with 281 total yards on the ground.  The 24-15 win over the Eagles on Thanksgiving was convincing and put the Bears at 9-3 and atop of the NFC North.

Usually by now Bears fans have been looking towards the draft and not the NFC North standings.

Week 14 Chicago Bears at Green Bay Packers (9-4)

While the world might have viewed the Eagles game as a benchmark for the Bears, Bears fans know that the true measure starts with beating the Packers.   Although the win against the Packers in the last game of the 2024 season was satisfying, this is the first time the Ben Johnson Bears are facing the Packers.

The Packers were comfortably leading 3-14 going into the half and still had a 10 point 11-21 lead with 2:10 left in the third quarter.  Unlike the Bears of old, this team fought back and tied the game up with 8:32 left in the fourth quarter.  The Packers put up another TD with 4:28 left and Bears fans felt something they haven't felt in a long time (or ever?).  They felt that Caleb was going to lead them to victory.  

Caleb made big plays, went 60 yards and with 22 seconds faced a fourth-and-1.  He took a shot at the end zone and was intercepted by the Packer's Nixon.  The Packers celebrated and took over the NFC North.  Packers fans were rejoicing and felt that all is right with the world now that they can look down on the Bears in the standings.

Week 15 Cleveland Browns at Chicago Bears (10-4)

Not letting themselves be let down, the Bears bounced back with a 31-3 win over the Browns.

Week 16 Green Bay Packers at Chicago Bears (11-4)

Wanting revenge for the loss at Green Bay just two weeks ago, the Bears came out with almost no energy.  The Bears were shutout at the half trailing 6-0 and although they managed a field goal and a fumble, the Packers added a touchdown and now trailed 13-6 going into the fourth quarter.

The Bears and Packers traded field goals and with 3:04 left the Bears were only able to manage a field goal and still trailed the Packers 16-9.  Initial criticism on the field goal wasn't taking the FG but that the time it took to set it up took them a couple of seconds past the 2-minute warning and thus losing a critical time stoppage that the Bears needed for that slim chance to get the ball back before the game ends.

So, with 1:59 left the Bears had to try an on-side kick.  If the Packers got the ball, the game was over.  There wouldn't be enough time for the Bears to get the ball back.  This is even too much to ask of the most optimistic of Bears fans, but these are the 2025 Cardiac Bears and they try every possession.  With a 8% chance of getting the onside kick, the Bears somehow was able to do it and gave Caleb 1:56 to get at least 7 points.

Caleb drives the Bears down to the red zone brimming with multiple big throws and catches, but finds himself facing 4th and 4 with 28 seconds left.  Not getting a first down meant the game was over.  The Packers broke through the line and forced Caleb to back pedal, he found a receiver in the corner of the end zone for a TD.  With the extra point, the Bears somehow manage to tie the game and send it into overtime.

Starting with the ball, the Packers made a huge play to get into Bears territory.  On a big third-1 the Bears stopped the Packers.  On the ensuing 4th-and-1, the Packers fumble and turn the ball over on downs.  A few key plays brought the Bears to the Packers 45 and then Caleb went for the win with deep ball to DJ Moore who had Keishan Nixon draped all over him.  Bears win and regain the top of the NFC North.

OT win over the Packers?!?  Who are these Bears?!?

The Iceman legend really grew with this win and it brought the kind of game reaction from Packers fan that have been the hallmark of Bears fans for years.

Week 17 Chicago Bears at San Francisco 49ers. (11-5)

In a battle for the top seed in the NFC, the Bears went toe-to-toe with the Niners (Full Game). In another spectacular ending scenario and less than 2 minutes, Caleb Williams and his receivers made big plays especially with conversions on 4th downs to stay alive.  A trick play at the goal line fell just short of the goal resulting in having to quickly rush the plan with 4 seconds on the clock for a final shot.  Caleb showed the escape artist ability that he's been earning throughout this season but his final throw at the end zone fell short.

I'm sure many people thought that the Bears were going to win this one and the 49er's must've felt a sense of relief even though they didn't want to admit it with comments like "they earned the win." 

Week 18 Detroit Lions at Chicago Bears (11-6)

After the Lions put up 52 on the Bears in week 2, this game ended with a Bears 19-16 loss to a 9-8 Lions team that was already eliminated from the playoffs.  The Bears had secured the NFC North and will be the #2 seed in the playoffs.

This was a game that saw the Lions jump to a 16-0 lead by halftime and then see the Bears fight back to tie the game at 16-16 including completing 2 2-pt conversions.  The Lion had the final possession and was able to win on a field goal with 1:41 remaining.

Playoffs Wildcard Round Green Bay Packers at Chicago Bears (Win)

The Packers secure the 7th seed so that brought them to Soldier Field.  The Packers had stated that they preferred to have fallen to the 7th seed and play the Bears.  They got their wish.


The Packers dominated the Bears through three quarters before the Bears stormed back with yet another come from behind victory led by Caleb Williams.  The famous 4th-and-8 showed Caleb facing a 4th down that would be the last play of the game unless he can convert.  This played showed everything that made Caleb special: leadership under pressure, escaping from what would've been a sack by every other QB and making the big play.  

This wasn't a typically comeback where the Bears got momentum and rode it to victory.  In the middle of their comeback, the Packers actually scored a TD.  It could've been the momentum killer that ended many comebacks, but this Bears team were not deterred.  They just kept come back until they took the lead and won.

The emotions of both fan bases captured by Tom Grossi:


Packers fans are not used to this against the Bears especially twice in the same season.




It's hard to express the euphoria of Bears fans seeing their team beating the rival AND eliminating them from the playoffs.

Playoffs Divisional Round Chicago Bears at Los Angeles Rams

For most of the season, the Bears were viewed as being lucky more than good.  They were starting to get recognized for not being bad, but the national media did not consider them to be contenders.  They beat the Eagles and took on the 49ers until the final play.  Now they are facing eventual Superbowl Champs who have been viewed as one of the top teams all season.  In this game, the Bears showed they belonged.  Watching this game in a vacuum will have any observer think that they were two comparable teams capable of winning the game.  Caleb had one of the most amazing throws in NFL playoffs history facing 4th down on the last play in regular to throw a TD to send the game to overtime.

Recap


The Chicago Bears provided NFL fans the best games of the season and one that Bears fan will remember.  The Bears won games that was statistically not suppose to be possible and this didn't include the game against the Rams.  The fans really love this team and just because they were winning.  I felt that the fans really liked the players of the teams.  



Saturday, January 3, 2026

Woodpecker Taper Sled

The Woodpecker Taper Sled (not to be confused with their taper jig) is not cheap at $220 before taxes and shipping.  The Internet is filled with guides on how to make cheap taper sleds from the most basic ones using just scraps and screws to very elaborate ones utilizing clamps, t-tracks, etc.  Most commercially available sleds seems to be about $100 (plus-or-minus $30). The Woodpecker Taper Sled is twice that price so is this another example of paying a brand name premium?


Compared to a DIY basic sled even a $100 commercial ones might be overpriced, but what about a more elaborate version that is reusable and adaptable similar to the commercial one?  

I decided to price out what it might cost me to build an similar sled to the Woodpecker sled:
  • Miter Bar ($30) - these wouldn't be as fancy as the ones Woodpecker use so it would require manual adjustments.
  • Jig Kit ($30) - I got lazy and didn't want to price out the specific knobs and bolts and would just buy a common kit with everything I'd need. 
  • T-slot Bit ($40) - Woodpecker cut t-slots directly into the plywood rather than using T-tracks so I'm estimating this is how much a t-slot bit will cost me.
  • Hold-down clamps ($16) - A pair of hold-downs are relatively cheap.
  • Fence ($20) - Woodpecker uses a steel knuckle fence that a Superstrut might be able to mostly mimic.
  • Plywood ($40) - Rough estimate based on a half sheet of 3/4" plywood considering how prices have been fluctuating so much.
  • Mount Rack - Can be made from scraps but wouldn't be as nice as the steel hangers the sled comes with.
  • Non-slip surface (???) - might skip this as I don't know what this is.
  • Tape measure ($10)
The total comes to $186 with only the T-slot bit being usable beyond the sled.  That's only a $34 savings with some of the parts being downgrades (miter bar, fence, mount rack) and there's also the time and labor to consider.  The materials of the Woodpecker sled seems to be higher quality then what other commercial sleds comes with (e.g. the fence of most commercial sleds seems to be a straight piece of plywood, mdf or plastic) for what its worth.

None of this information will give a general answer as to whether it's better to buy versus build.  If you get joy building jigs then I'd recommend building your own.  

If you rather not build then it becomes whether the Woodpecker sled is twice as good as other commercial sleds.  I ultimately decided to go with the Woodpecker sled.  I previously built a very basic sled with just scraps and screws and it was okay.  I had "build a complete taper sled" on my todo list that I just kept putting off (thus labor time obviously is a factor in my case) and I like the "extras" that Woodpecker sled has: adjustable miter bar, steel fence, and mount-it rack.  These all added to its value above other commercial sleds.  The time and effort saved from building the jig was worth it for me.

Thursday, December 25, 2025

Garage Shop Air Filter

The Corsi-Rosenthal Box is a DIY air purifier that uses HVAC filters and a simple box fan.  I originally built one during Covid and later moved it to my garage where I do my woodworking.  After having it on a cart for awhile, I decided to mount it from the ceiling where I plugged it into to a smart switch so I can turn it on/off with an app and where it doesn't take up floor space.  I also when from a 4 filter design to a 5 filter design.



It's bigger then commercial air filters which goes from $100 to $800 so it's about the price of the cheapest commercial ones.  Performance-wise, research on Corsi-Rosenthal boxes has shown that they perform very well.  Making it just requires 4 or 5 filters, a box fan and tape.

For a garage shop, I don't need anything fancy.

Monday, July 7, 2025

Drill Press Table

 After many, many years, I finally got around to building a drill press table.  The drill press was a tool that I thought that I'd use frequently when I bought it but I found myself generally avoiding it instead.  I think it is because of the setup that was needed whenever I needed to use it particularly all the clamps that ended up getting used and trying to balance the work piece on the small round cast iron table that it comes with.



The dimensions of the drill press table is 12" deep by 24" wide.  The thickness is 2 sheets of 3/4" Baltic birch plywood since that's what I had on hand laminated together so there is enough thickness to allow for putting in the T-tracks used by the fence and hold-down clamps.  The fence 2 1/2" tall and is made from the cutoffs that I had from the Baltic birch.

Two thing missing that is common on many DIY tables are tracks on the fence to allow for a stop block and having a replaceable sacrificial top area are that gets drilled in.   I didn't have any extra T-Tracks for the stop block and I usually just use a scrap piece of wood and a clamp when I need one.  I plan to add the sacrificial piece when I chew into the current top to see what areas that would normally chew up.

For now, I'll see if having the table will make me use it more often. 



Wednesday, June 18, 2025

My Contribution to LLM Knowledge?

When I first started to learn Go many years ago, I wrote a Wator simulation with Go and uploaded the code to a Github repo.  A few months ago, I wanted to learn how to write a 2D game with graphics so I decided to do a new implementation of Wator using Go and Ebitengine.

There was a bug that I got stuck on and because LLMs are all the rage, I decided to ask Google's Gemini 1.5 to assist me.  Gemini generated some code output in response to my request but as I was looking at what it produced, it seemed awfully familiar.  I went back and looked at my old Wator code and sure enough it was very similar (including a bug that was in the original code).  When I asked Gemini for some of its sources for coming up with the answer it listed my repo as one of them.   

Basically,  I asked an LLM a question and it responded with my own answer.  There weren't many examples of Wator in Go so it wasn't because I had written something great, but I still found it neat and funny this happened.

Wednesday, April 23, 2025

Why Big Companies Move Slow

Big companies have resources, talent, and market reach, but compared to small start-ups with less resources, talent and reach they often seem to be slow and lumbering.   Is this the inevitable result of becoming a large company?  Many companies are slow but in a different sense from the big-versus-small comparison.  Large company velocity takes into consideration "scale" and can still move nimbly and quickly within that context, but the complexity of scale often overwhelms the organization resulting in them becoming a slow and lumbering company.

Scale

To be fair to large companies, comparing launching something between a start-up and a large company isn't an apples-to-apples comparison because there's often a lot additional requirements placed on a companies that has reach a certain scale.  Some of these requirements come externally (e.g. government regulations) and some internally (existing user base, supporting existing infrastructure and use cases). 

It isn't lost on the employees how cumbersome internal requirements can be:



Having had to work on these systems, there are often valid reasons behind the requirements, but it can still be hair-pulling frustrating sometimes to have to consider all the additional requirements for what seems like a simple singular task.  Objectively, though, the team within the large company might have a higher velocity then a team in a small company because for a given feature A, one had 10 requirements to meet while the other only had 3.

This doesn't mean that big companies are not slower than start-ups because many big companies looses their nimbleness due to self-inflicted wounds because of the complexity of increased scale:
  • Complacency
  • Hesitancy
  • Bureaucracy: Navigating the corporate maze can feel like a full-time job (though, let's be real, some structure is necessary).

Complacency

The mantra of "If it ain't broke, don't fix it." can take hold at large companies especially those that have had success.  This often comes from the top where the leadership is more comfortable keeping the status quo because things are going well and don't want to risk destabilizing the business.  This isn't limited to just mature companies but can happen with growth companies.

No matter if the decision to just stay the course is correct or not, if the sense of complacency from the top seeps into rank-and-file then the culture of complacency will take hold.  

Hesitancy

Fear stiles innovation and at large companies there can be a perception that more is at stake at both the company and individual levels.  This hesitancy occurs at all levels of the organization.   The CEOs might fear how a change will impact their bottom line and individual might fear how it will affect their prospects at the company.

Bureaucracy

When a company grows (a good problem to have!), bureaucracy sets in but bureaucracy itself isn't a bad thing.  The truth is that when a company scales up it is going to become more complex and it will require organization.  A small 3 person start-up doesn't need any process to communicate effectively, but a 100 member engineering org will descend into chaos without some agreed upon method for working together.  Large companies often organically evolve into a matrix organization with defined roles and responsibilities, but fail to recognize the that they went from a single node to a graph of nodes.  Company leaders continue to try to optimize each node and they ignore the edges connecting the nodes.  

Big companies will have more people who can handle things at the node level while it is mainly the leadership who can affect the edges.  The irony is that leadership often focus more on the nodes while their teams struggles to navigate through the edges. 

Possible Solutions

So, how do we combat the corporate slow-down? While this isn't a complete solution, here are some strategies:

Embrace Small, Nimble Teams: Have small and empowered teams that can move nimbly.  Give the team autonomy to solve the problem which helps against complacency and hesitancy.  The small team also reduces need for a lot of process within the team for coordination.  It is key for leaders to communicate with them on expectations, be transparent and show trust and support.  Leaders should also focus on handling coordination between teams.    

Provide a "Guide": Shield engineering teams from excessive corporate overhead. Dedicated project managers (not just program managers who push the burden onto engineers) can handle the administrative load.  This is to address bureaucracy.

Focus on External Competition: Internal rivalry is a distraction. Aim for external benchmarks.  This addresses complacency and hesitancy when there is an external opponent to focus on.

Leadership Support: Leadership should recognize that they created a matrix for the org and the teams don't need help at the node level but the edge traversal.

Maintain Momentum: Long projects can drain morale. Celebrate small wins and define clear milestones.

Instill Urgency: Set targets based on external market realities, ensuring team buy-in.

The key is to recognize that speed and agility aren't just startup perks. They're essential for any company that wants to thrive in today's fast-paced world. By addressing these challenges head-on, we can unlock the true potential of big companies and empower them to innovate at the speed of change.

Tuesday, March 25, 2025

Why the Model Context Protocol (MCP) Is Confusing

**Update 3/26/2025 ** 

OpenAI added MCP support to their agent SDK.


--------------------------------

On Nov. 25, 2024, Anthropic published a blog post about the Model Context Protocol (MCP) .  It didn’t get too much attention at the time because it wasn’t an announcement of much significance.  Suddenly in 2025, MCP has gotten a lot of hype and attention and have also caused a lot of confusion as to why there are so many YouTube face talking about it.

It was nice that Anthropic published how they connect Claude with tools in the Claude Desktop app even if the post was a bit of marketing to sell it as an standard and to encourage an open community.  There is a technical aspect (a protocol) to it, but it felt like it was a business play to get developers to extend Claude with plugins.

Large Language Models like Claude cannot perform any actions.  They’re like a brain with no body.  They might know that an email should be sent, but they can’t actually send the email.  To connect the “thought” (send email) with the action requires basic programming.  Using MCP is how Anthropic does it but it isn’t the only way.  Let’s take a look at various ways that this is accomplished and then see how MCP fits in.

You Are the Agent

In this scenario, a person goes to claude.ai and has a conversation with Claude about writing an email to invite someone to lunch.  Claude generates the email body letting the person know to copy it an email program to send.  The person manually copies that text into their email or calendar app and sends the invitation.  The person is the agent because they are performing the action.

Using an AI Assistant

Here, a person uses an app (this can be a web app, desktop app, mobile app, etc.) such as a personal assistant ala Jarvis from Iron Man.  The user asks Jarvis to send an email to invite someone for lunch.  Jarvis composes the invitation message and sends the invitation through a calendar app so that it also records the event on the calendar.  So how does Jarvis do this?

Method 1

  1. Jarvis sends your question to LLM along with prompts describing available tool(s).
  2. Jarvis looks at the response to determine what tools to use.
  3. Jarvis executes the chosen tool(s) through the tool API
  4. The results are sent back to LLM
  5. LLM formulates a natural language response
  6. The response is displayed to you!

In the early days (2023), this might be done like this:

The user speaks to Jarvis, “Jarvis, invite Thor to lunch next Wednesday.”

The Jarvis code passes the text to an LLM along with an additional prompt:

Respond to the user, but if the request is to add to a calendar then respond in JSON:

  {
    Tool: “calendar”
    Invitee: name
    Date: date
    Time: time
    Body: message
  }

The Jarvis program will get the response and if the response is a tool response it will parse the JSON and call the calendar API.

The Jarvis code calls the LLM again with the text, “tell the user that the invite was successfully sent” and then return the response to the user.

Method 2

  1. Developer registers available tools
  2. Jarvis sends your question to LLM
  3. LLM analyzes the available tools and decides which one(s) to use
  4. Jarvis executes the chosen tool(s) through the tool API
  5. The results are sent back to LLM
  6. LLM formulates a natural language response
  7. The response is displayed to you!

An enhancement was added to many LLM’s API to allow developers to register tools, their purpose and parameters. The Jarvis code will register a tool called “calendar”, give it a description such as “Tool to add, update and remove user’s calendar.”, and what parameters it needed.

Now, when Jarvis passes “Jarvis, invite Thor to lunch next week,” to the LLM, it will respond with JSON and Jarvis can call the calendar API.

The Jarvis code calls the LLM again with the text, “tell the user that the invite was successfully sent” and then return the response to the user.

Method 3 (MCP)

  1. User registers available tools.
  2. Jarvis sends your question to Claude
  3. Claude analyzes the available tools and decides which one(s) to use
  4. Jarvis executes the chosen tool(s) through the MCP server who calls the tool API
  5. The results are sent back to Claude
  6. Claude formulates a natural language response
  7. The response is displayed to you!

With MCP, the user (on desktop/mobile) or developer (on cloud) registers MCP servers with Jarvis.  Jarvis can then get the tools description from the MCP Server which it passes to the LLM.

When Jarvis passes “Jarvis, invite Thor to lunch next week,” to the LLM, the LLM will determine the tool to use.

Jarvis will then call the MCP server to send the calendar invite.

The Jarvis code calls the LLM again with the text, “tell the user that the invite was successfully sent” and then return the response to the user.

Comparison

With the MCP, tool registration is passed to the user and the tool description is handed off to the tool developer, but otherwise the steps remain the same.

Method 2

Method 3

  1. Developer registers available tools
  2. Jarvis sends your question to LLM
  3. LLM analyzes the available tools and decides which one(s) to use
  4. Jarvis executes the chosen tool(s) through the tool API
  5. The results are sent back to LLM
  6. LLM formulates a natural language response
  7. The response is displayed to you!
  1. User registers available tools.
  2. Jarvis sends your question to Claude
  3. Claude analyzes the available tools and decides which one(s) to use
  4. Jarvis executes the chosen tool(s) through the MCP server who calls the tool API
  5. The results are sent back to Claude
  6. Claude formulates a natural language response
  7. The response is displayed to you!

Comparing the different methods shows that the steps are the same but just the implementation is different.  This is one reason there’s a lot of confusion because seems to be very little benefit.

Having a standard protocol can be advantageous but only when all the LLM adopts it otherwise it is just how to interact with Claude.


MCP servers are potentially reusable and might ease integration which is a benefit since it’ll be like having only one API to learn.  This requires wide adoption and availability which isn’t a given even if it is backed by one of the big LLM providers.

Shortcomings of the MCP

As a protocol, there are a lot of shortcomings and technical benefits are minor.  

Some technical shortcomings are:

  • There’s no discovery mechanism other than manual registration of MCP servers.
  • There’s now extra MCP servers in the tech stack that can be achieved by a library.
Thus the main benefits will mainly come if the protocol is adopted as a standard.

Friday, March 21, 2025

Running Kokoro-82M Text-to-Speech on Fedora with Nivdia GPU with Podman

I got interested in Kokoro, a new text-to-speech model that only uses 82 million parameters but is one of the top models on the TTS leaderboard.  I wanted to run it locally and a quick way to try it is to use Kokoro-FastAPI which comes in a Docker container.  The README on Kokoro-FastAPI’s github has instructions using Docker (with or without GPU), but I’m using Podman so I need to do some setup on Fedora to enable Podman access the GPU.

The instructions on the Podman and Nvidia site have you set up an Nvidia Repository to get the container kit that enables Podman to access the GPU, but in my previous post on installing Nvidia and CUDA drivers on Fedora I mentioned that there can be dependency conflicts.  I wasn't sure if the Nvidia container kit might also cause problems, but fortunately, you can just install the packages from Fedora's repo and avoid possible headaches: 

sudo dnf install golang-github-nvidia-container-toolkit

Assuming that you already installed Podman (if not, follow the Fedora doc on installing Docker and/or Podman) and you have an GPU, you can download and run:

docker run --device nvidia.com/gpu=all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.2

If SELinux blocks Podman from accessing the GPU, you can follow Podman's instruction about giving permission for containers to access the GPU

sudo setsebool -P container_use_devices true

Then run the `docker run ...` command above and it should start.

This a quick way to give Kokoro a try.  I'll probably try to run it next with Go by using the onnxruntime to load the Kokoro-Onnx model.

Tuesday, February 18, 2025

How I Avoid Doomscrolling/Doomsurfing

For those not familiar with term, doomscrolling, Wikipedia describes it as:

Doomscrolling or doomsurfing is the act of spending an excessive amount of time reading large quantities of news, particularly negative news, on the web and social media. (Wikipedia)

There are negative consequences of doomscrolling on people's mental and physical health such as increased stress, anxiety, depression, isolation, etc.  Suggestions on how to break the habit and combat its negative effects include limiting the amount of screen time and seek out more positive news.   In our current environment there are numerous powerful forces working to keep people doomscrolling such as corporations prioritizing engagement (keeping you hooked), publishers vying for your attention (often through negative news), and political leaders fueling fear.

Although I don't spend much time on social media, I do regularly read the news, follow current events and various feeds on topics I'm interested in.   To avoid doomscrolling some people are able to stop following the news altogether, but I find that to be difficult to achieve for myself.  Since publishers don't provide readers much control over what is shown, I built my own news aggregation site: news.lazyhacker.com.

Now, instead of seeing what publishers want me to see:



Or these set of headlines  from feeds (which also illustrate how much political news is pushed on to us:

- Judge Chutkan rejects call from Democratic AGs for temporary restraining order blocking DOGE’s access to federal data - CNN
- Russia and US agree to work toward ending Ukraine war in a remarkable diplomatic shift - The Associated Press
- Pope Francis, still hospitalized, has pneumonia in both lungs - The Washington Post
- Fact Sheet: President Donald J. Trump Expands Access to In Vitro Fertilization (IVF) - The White House
- National Science Foundation fires roughly 10% of its workforce - NPR
- 'Executive order' cited as reason for sudden closure of JFK Library in Boston - WCVB Boston
- Ensuring Accountability for All Agencies - The White House
- Native American Activist Leonard Peltier Released From Prison - The New York Times
- Donald Trump signals Ukraine should hold elections as part of Russia peace deal - Financial Times
- Senate GOP pushes ahead with budget bill that funds Trump's mass deportations and border wall - The Associated Press
- Brazil Charges Bolsonaro With Attempting a Coup - The New York Times

I see a variety of headlines based on my own preferences:

- Pope Francis, still hospitalized, has pneumonia in both lungs - The Washington Post
- National Science Foundation fires roughly 10% of its workforce - NPR
- 'Executive order' cited as reason for sudden closure of JFK Library in Boston - WCVB Boston
- Rare deep-sea ‘doomsday fish’ washes up on Canary Islands coast - The Independent
- Hamas to release 6 more hostages, bodies of 4 others - ABC News
- Dramatic video shows moment Delta plane flipped after landing in Toronto - ABC News
- Futures Rise After S&P 500 Hits High; Two Earnings Losers Late - Investor's Business Daily
- Nvidia’s 50-series cards drop support for PhysX, impacting older games - Ars Technica
- AMD Ryzen AI Max+ 395 Analysis - Strix Halo to rival Apple M4 Pro/Max with 16 Zen 5 cores and iGPU on par with RTX 4070 Laptop - Notebookcheck.net
- Nintendo is killing its Gold Points loyalty program - Engadget
iPhone 17 Air Leaks Look More Like Google Pixel - Forbes

The source of the headlines can come from different feeds from places like Google News, Reddit, and any source that offers a RSS feed.  The site takes the headlines from the feeds and run it through a set of rules that I defined in natural language (e.g. "Remove political headlines, headlines about political figures or those who are not politicians but politically active.") to strip out any headlines that I might not want to see.  I purposely don't show any images and only update the site every couple of hours.  The former reduces the chance of me wanting to read an article because of the image rather then the substance and the latter reduces my urge to constantly refresh because I know that there will be no new headlines for another 2 hours.

Now, instead of finding myself being lured into doomscrolling, I can go to my site and see something like this:


Saturday, February 15, 2025

WebAssembly (WASM) with Go (Golang) Basic Example

I first wrote about using Go for WebAssembly (WASM) 6 years ago right before the release of Go 1.11 which was the first time Go supported compiling to WASM.  Go's initial support for WASM had many limitations (some I listed in my initial article) which have since been addressed so I decided to revisit the topic with some updated example of using Go for WASM.

Being able to compile code to WASM now allow:

  • Go programs to run in the browser. 
  • Go functions to be called by JavaScript in the browser.
  • Go code to call JavaScript functions through syscall/js.
  • Go code access to the DOM.

Setup

Go's official Wiki now has an article on the basics of using Go for WASM including how to set the compile target and setup.  

A quick summary of the steps to the process:

Compile to WASM with the output file ending as wasm since it's likely that the mime type set in /etc/mime probably use the wasm extension.

> GOOS=js GOARCH=wasm go build -o <filename>.wasm

Copy the JavaScript support file to your working directory (wherever your http server will serve it from).  It's necessary to use the matching wasm_exec.js for the version of the Go being used so maybe put this as part of the build script.

> cp "$(go env GOROOT)/lib/wasm/wasm_exec.js" .

Then add the following to the html file to load the WASM binary: 

<script src="wasm_exec.js"></script>
<script>
    const go = new Go();
    WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
                go.run(result.instance);
    });
</script>

Keeping It Running

It is a good starting point but the Go code example is too simplistic.  It only demonstrates that the WASM binary that is created by Go can be loaded by having write a line to the browser's console.  The Go program basically gets loaded by the browser, prints a line and exits.   Most of the time, it's probably desirable to have the WASM binary get loaded and stay running.  This can be achieved by either having having a channel that keeps waiting:

c := make(chan struct{}, 0)
<- c

or even easier:

select {}

Have either of these at the end of main() will keep the program alive after it gets loaded into the browser.

In Place of JavaScript

Being able to access the DOM excites me the most because it allows me to avoid writing JavaScript followed by being able to run Go programs in the browsers.  While I think the inter-op between Go and JavaScript is probably the most practical application, it's not something I've had to do much since I'm not a front-end developing doing optimizations or trying to reuse Go code between the front-end and back-end.

I don't mind using HTML for UI development or even CSS, I'm just personally not a fan of JavaScript.  This isn't to say that it is bad, just I prefer other languages just like some people prefer C++, Java, Python, etc.  I don't have fun writing JavaScript like I do with with Go if though I know JavaScript.

Take a basic example of a web app (index.html) with a button to illustrate:

<!DOCTYPE html>                                                                 
  <html lang="en">                                                                  
  <head>                                                                          
      <meta charset="UTF-8">                                                        
      <meta name="viewport" content="width=device-width, initial-scale=1.0">        
      <title>Example</title>                                         
  </head>                                                                           
  <body>                                                                          
                                                                                  
      <button id="myButton">Click Me</button>                                                                                                     
                                                                                  
  </body>
  </html>

JavaScript is used to attach an event to it so that when the button is clicked, an alert message pops up:

    // Select the button element                                            
    const button = document.getElementById('myButton');                     
                                                                                  
    // Attach an event listener to the button                               
    button.addEventListener('click', function() {                           
       alert('Button clicked!');                                           
    }); 

With WASM, the JavaScript can be replaced with Go code:

 package main                                                                       
                                                                                     
  import (                                                                                                                                                   
                                                                                     
      "honnef.co/go/js/dom/v2"                                                       
  )                                                                                  
                                                                                  
  func main() {                                                                   
                                                                                  
      document := dom.GetWindow().Document()                                      
           
      // Select the button element                                                                       
      button := document.GetElementByID("myButton")                               
                                                                                  
      // Attach an event listener to the button
      button.AddEventListener("click", false, func(dom.Event) {                   
          dom.GetWindow().Alert("Button clicked!")                                
      })                                                                          
                                                                                  
      select {}
  }

In this case, the Go code looks extremely similar to the JavaScript code because I'm using the honnef.co/go/js/dom/v2 package.  It is a Go binding to the JavaScript DOM APIs and I find that it makes it more convenient than using syscall/js directly.

Why do I prefer this over writing JavaScript especially when they look so similar?   The main reason is that most code is not just calling an API.  There's other logic that are implemented and for those, I can use Go and Go's libraries along with the benefits of a compiled and type safe language. 

There are still things that needs to be considered before just using Go and WASM for general consumer production web app.  The binary size can be large so it needs to be considered for your audience, but if I'm doing my own hobby project for myself or corporate apps where I know the user have fast connections, or if app performance and functionality outweighs the initial download and memory usage, I'd try to use it.