Sr. Content Developer at Microsoft, working remotely in PA, TechBash conference organizer, former Microsoft MVP, Husband, Dad and Geek.
149712 stories
·
33 followers

4 Reasons That Make Tailwind Great for Building Layouts

1 Share

When I talk about layouts, I’m referring to how you place items on a page. The CSS properties that are widely used here include:

  • display — often grid or flex nowadays
  • margin
  • padding
  • width
  • height
  • position
  • top, left, bottom, right

I often include border-width as a minor item in this list as well.

At this point, there’s only one thing I’d like to say.

Tailwind is really great for making layouts.

There are many reasons why.

First: Layout styles are highly dependent on the HTML structure

When we shift layouts into CSS, we lose the mental structure and it takes effort to re-establish them. Imagine the following three-column grid in HTML and CSS:

<div class="grid">
  <div class="grid-item"></div>
  <div class="grid-item"></div>
</div>
.grid {
  display: grid;
  grid-template-columns: 2fr 1fr;

  .grid-item:first-child {
    grid-column: span 2
  }

  .grid-item:last-child {
    grid-column: span 1
  }
}
Two blue rectangles side-by-side illustrating a two-column layout where the left column is twice the width of the right column.

Now cover the HTML structure and just read the CSS. As you do that, notice you need to exert effort to imagine the HTML structure that this applies to.

Now imagine the same, but built with Tailwind utilities:

<div class="grid grid-cols-3">
  <div class="col-span-2"></div>
  <div class="col-span-1"></div>
</div>

You might almost begin to see the layout manifest in your eyes without seeing the actual output. It’s pretty clear: A three-column grid, first item spans two columns while the second one spans one column.

But grid-cols-3 and col-span-2 are kinda weird and foreign-looking because we’re trying to parse Tailwind’s method of writing CSS.

Now, watch what happens when we shift the syntax out of the way and use CSS variables to define the layout instead. The layout becomes crystal clear immediately:

<div class="grid-simple [--cols:3]">
  <div class="[--span:2]"> ... </div>
  <div class="[--span:1]"> ... </div>
</div>
Two blue rectangles side-by-side illustrating a two-column layout where the left column is twice the width of the right column.

Same three-column layout.

But it makes the layout much easier to write, read, and visualize. It also has other benefits, but I’ll let you explore its documentation instead of explaining it here.

For now, let’s move on.

Why not use 2fr 1fr?

It makes sense to write 2fr 1fr for a three-column grid, doesn’t it?

.grid {
  display: grid;
  grid-template-columns: 2fr 1fr;
}

Unfortunately, it won’t work. This is because fr is calculated based on the available space after subtracting away the grid’s gutters (or gap).

Since 2fr 1fr only contains two columns, the output from 2fr 1fr will be different from a standard three-column grid.

Three examples of multi-column layouts stacked. The first is an equal three-column layout, the second and third are two columns where the left column is double the width of the right column.

Alright. Let’s continue with the reasons that make Tailwind great for building layouts.

Second: No need to name layouts

I think layouts are the hardest things to name. I rarely come up with better names than:

  • Number + Columns, e.g. .two-columns
  • Semantic names, e.g. .content-sidebar

But these names don’t do the layout justice. You can’t really tell what’s going on, even if you see .two-columns, because .two-columns can mean a variety of things:

  • Two equal columns
  • Two columns with 1fr auto
  • Two columns with auto 1fr
  • Two columns that spans total of 7 “columns” and the first object takes up 4 columns while the second takes up 3…

You can already see me tripping up when I try to explain that last one there…

Instead of forcing ourselves to name the layout, we can let the numbers do the talking — then the whole structure becomes very clear.

<div class="grid-simple [--cols:7]">
  <div class="[--span:4]"> ... </div>
  <div class="[--span:3]"> ... </div>
</div>

The variables paint a picture.

Example of a seven-column layout above a two-column layout with equally-sized columns.

Third: Layout requirements can change depending on context

A “two-column” layout might have different properties when used in different contexts. Here’s an example.

Two two-by-two layouts next to each other. In both cases, the third item wraps to the second line, followed by the fourth item.

In this example, you can see that:

  • A larger gap is used between the I and J groups.
  • A smaller gap is used within the I and J groups.

The difference in gap sizes is subtle, but used to show that the items are of separate groups.

Here’s an example where this concept is used in a real project. You can see the difference between the gap used within the newsletter container and the gap used between the newsletter and quote containers.

A two-column layout for a newsletter signup component with the form as the left column that is wider than the width of the right column, containing content.

If this sort of layout is only used in one place, we don’t have to create a modifier class just to change the gap value. We can change it directly.

<div class="grid-simple [--cols:2] gap-8">
  <div class="grid-simple gap-4 [--cols:2]"> ... </div>
  <div class="grid-simple gap-4 [--cols:2]"> ... </div>
</div>

Another common example

Let’s say you have a heading for a marketing section. The heading would look nicer if you are able to vary its max-width so the text isn’t orphaned.

text-balance might work here, but this is often nicer with manual positioning.

Without Tailwind, you might write an inline style for it.

<h2 class="h2" style="max-width: 12em;">
  Your subscription has been confirmed
</h2>

With Tailwind, you can specify the max-width in a more terse way:

<h2 class="h2 max-w-[12em]">
  Your subscription has been confirmed
</h2>
A centered heading in black that says Your subscription has been confirmed.

Fourth: Responsive variants can be created on the fly

“At which breakpoint would you change your layouts?” is another factor you’d want to consider when designing your layouts. I shall term this the responsive factor for this section.

Most likely, similar layouts should have the same responsive factor. In that case, it makes sense to group the layouts together into a named layout.

.two-column {
  @apply grid-simple;
  /* --cols: 1 is the default */

  @media (width >= 800px) {
    --cols:2;
  }
}

However, you may have layouts where you want two-column grids on a mobile and a much larger column count on tablets and desktops. This layout style is commonly used in a site footer component.

Since the footer grid is unique, we can add Tailwind’s responsive variants and change the layout on the fly.

<div class="grid-simple [--cols:2] md:[--cols:5]">
  <!-- span set to 1 by default so there's no need to specify them -->
  <div> ... </div>
  <div> ... </div>
  <div> ... </div>
  <div> ... </div>
  <div> ... </div>
  <div> ... </div>
</div>
Example of a footer that adapts to the screen size. It goes from a two-column layout on small screens to a five-column layout on wider screens.

Again, we get to create a new layout on the fly without creating an additional modifier class — this keeps our CSS clean and focused.

How to best use Tailwind

This article is a sample lesson from my course, Unorthodox Tailwind, where I show you how to use Tailwind and CSS synergistically.

Personally, I think the best way to use Tailwind is not to litter your HTML with Tailwind utilities, but to create utilities that let you create layouts and styles easily.

I cover much more of that in the course if you’re interested to find out more!


4 Reasons That Make Tailwind Great for Building Layouts originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

Read the whole story
alvinashcraft
23 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Anthropic makes a pricing change that matters for Claude’s longest prompts

1 Share
Illustration of a cartoon robot inserting a coin while holding a stack of coins, depicting the cost of running large language models.

Anthropic announced Friday that the 1-million-token context window for Claude Opus 4.6 and Claude Sonnet 4.6 is now generally available, with standard pricing replacing the premium long-context rates that previously kicked in once prompts crossed a certain size threshold.

The company debuted the two models within weeks of each other in February. Claude Opus 4.6 is Anthropic’s flagship model for enterprise workloads that require sustained reasoning across large internal datasets and complex coding tasks. Claude Sonnet 4.6, meanwhile, is the company’s more efficient general-purpose model, designed for high-throughput developer use and production applications that need strong reasoning performance at lower cost than Opus.

Both models shipped with a 1-million-token context window — a limit that allows developers to place very large amounts of information into a single prompt. That can include entire code repositories, lengthy research papers, legal filings, or large collections of internal documents that an AI system needs to analyze together.

There was, however, an important caveat: While the models technically supported prompts approaching the 1-million-token limit, requests exceeding roughly 200,000 tokens were billed at higher “long-context” pricing tiers, moving the entire request into a premium rate band.

That pricing distinction is what Anthropic has now removed.

Under the new arrangement, requests are billed at the same per-token rate regardless of prompt size. A prompt containing hundreds of thousands of tokens is now priced using the same per-token rate as a much smaller request.

The road to 1 million tokens

Anthropic’s move toward million-token context windows has unfolded in stages over the past two years.

Earlier Claude models launched with a 200,000-token limit, already one of the largest publicly available context windows at the time. When Anthropic introduced the Claude 3 family in early 2024, the company noted that the models were technically capable of processing inputs exceeding one million tokens, though access to those larger contexts was initially limited to “specific use-cases” and available only on request.

The first public release of a 1-million-token window arrived in August 2025, when Anthropic introduced the capability in Claude Sonnet 4. The jump represented a fivefold increase over the earlier Sonnet models, albeit with a tiered pricing structure tied to prompt size.

It’s also worth noting that Anthropic was, in some respects, playing catch-up: both Google and OpenAI had already introduced models capable of handling prompts approaching one million tokens.

Still, the million-token milestone has become an increasingly visible benchmark among AI model providers. Larger context windows allow models to process longer documents or broader datasets without breaking the task into multiple steps.

Under the current pricing, Claude Opus 4.6 costs about $5 per million input tokens and $25 per million output tokens, while Claude Sonnet 4.6 costs roughly $3 per million input tokens and $15 per million output tokens. Previously, Sonnet input pricing rose from about $3 to roughly $6 per million tokens once prompts exceeded the long-context threshold, while Opus input pricing increased from about $5 to around $10 per million tokens. Output token pricing also rose under the premium tier.

Anthropic said the 1-million-token context window is available on the Claude Platform natively and through Amazon Bedrock, Google Cloud’s Vertex AI, and Microsoft Foundry. Claude Code Max, Team, and Enterprise users running Opus 4.6 will also get the full 1-million-token context window by default.

What cheaper long prompts change for developers

For developers, the removal of the long-context surcharge could influence how applications are designed.

A popular mechanism for keeping costs down has been to minimize the amount of information sent to a model at once. Retrieval systems — which pull only the most relevant snippets of data — became a common architectural pattern partly because sending very large prompts could quickly become expensive.

With the premium tier gone, so is that constraint. Developers can still rely on retrieval systems to manage token usage, but they may also choose to send larger bodies of information directly to the model when a broader context is useful.

That could make certain workflows simpler. Instead of chunking documents into smaller segments or orchestrating multiple model calls, developers can sometimes place a larger slice of data into a single prompt and ask the model to reason across it.

For AI-native coding tools, this approach is particularly attractive. A model with access to a large context window can inspect more of a codebase at once — including multiple files, documentation, and previous conversations — which can improve tasks such as debugging, code refactoring, or generating pull requests.

Brad Feld, Techstars co-founder and venture capitalist, said the larger context window can remove some of the engineering workarounds developers previously needed to manage limited context sizes.

“The 1M token context window for Claude Code changes the engineering calculus completely,” Feld writes in a LinkedIn post. “I built four markdown state machines totaling 4,700 lines to manage my development workflow — from ticket to deployment. Most of that complexity existed because of the 200K context limit.”

With a larger window, he writes, many of those mechanisms become unnecessary.

“With 1M tokens, reliability is largely solved by having enough room. The constraint shifts to wall-clock speed — and speed comes from parallelism.”

Translated, the model now has enough memory to keep track of long tasks, and the main bottleneck becomes how quickly it can process all that information.

It’s worth stressing that removing the surcharge doesn’t make large prompts free. Token usage still increases with input size, and developers must weigh this cost against other architectural approaches.

But by eliminating the pricing threshold, Anthropic has made long-context workloads easier to experiment with — and potentially easier to deploy in production systems.

The post Anthropic makes a pricing change that matters for Claude’s longest prompts appeared first on The New Stack.

Read the whole story
alvinashcraft
23 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

AWS Weekly Roundup: Amazon S3 turns 20, Amazon Route 53 Global Resolver general availability, and more (March 16, 2026)

1 Share

Twenty years ago this past week, Amazon S3 launched publicly on March 14, 2006. While Amazon Simple Storage Service is often considered the foundational storage service that defined cloud infrastructure, what began as a simple object storage service has grown into something far larger in scope and scale.

As of March 2026, S3 stores more than 500 trillion objects, serves more than 200 million requests per second globally across hundreds of exabytes of data, and the price has dropped to just over 2 cents per gigabyte — an approximately 85% reduction since launch. My colleague Sébastien Stormacq wrote a detailed look at the engineering and the road ahead in Twenty years of Amazon S3 and building what’s next, and if you want to read about those earliest customers and how they shaped what AWS became, I recommend How three startups helped Amazon invent cloud computing and paved the way for AI. Twenty years is worth pausing to celebrate.

Alongside the 20th anniversary of S3, Channy Yun also wrote about a new S3 feature this week: Account regional namespaces for Amazon S3 general purpose buckets. With this feature, you can create general purpose buckets in your own account regional namespace by appending your account’s unique suffix to your requested bucket name, ensuring your desired names are always reserved exclusively for your account. You can enforce adoption across your organization using AWS IAM policies and AWS Organizations service control policies with the new s3:x-amz-bucket-namespace condition key. Read Channy’s post to learn more about account regional namespaces for Amazon S3 general purpose buckets.

This week’s featured launch is one I have a personal connection to: the general availability of Amazon Route 53 Global Resolver. I wrote about the preview of this capability back in December at re:Invent 2025, and I had a great time putting that post together, so I am happy to hear that it’s generally available now.

Amazon Route 53 Global Resolver is an internet-reachable anycast DNS resolver that provides DNS resolution for authorized clients from any location. It is now generally available across 30 AWS Regions, with support for both IPv4 and IPv6 DNS query traffic. Route 53 Global Resolver gives authorized clients in your organization anycast DNS resolution of public internet domains and private domains associated with Route 53 private hosted zones — from any location, not just from within a specific VPC or Region. It also provides DNS query filtering to block potentially malicious domains, domains that are not safe for work, and domains associated with advanced DNS threats such as DNS tunneling and Domain Generation Algorithms (DGA). Centralized query logging is included as well. With general availability, Global Resolver adds protection against Dictionary DGA threats.

Last week’s launches
Here are some of the other announcements from last week:

  • Amazon Bedrock AgentCore Runtime now supports stateful MCP server features — Amazon Bedrock AgentCore Runtime now supports stateful Model Context Protocol (MCP) server features, enabling developers to build MCP servers that use elicitation, sampling, and progress notifications alongside existing support for resources, prompts, and tools. With stateful MCP sessions, each user session runs in a dedicated microVM with isolated resources, and the server maintains session context across multiple interactions using an Mcp-Session-Id header. Elicitation enables server-initiated, multi-turn conversations to gather structured input from users during tool execution. Sampling allows servers to request LLM-generated content from the client for tasks such as personalized recommendations. Progress notifications keep clients informed during long-running operations. To learn more, see the Amazon Bedrock AgentCore documentation.
  • Amazon WorkSpaces now supports Microsoft Windows Server 2025 — New bundles powered by Microsoft Windows Server 2025 are now available for Amazon WorkSpaces Personal and Amazon WorkSpaces Core. These bundles include security capabilities such as Trusted Platform Module 2.0 (TPM 2.0), Unified Extensible Firmware Interface (UEFI) Secure Boot, Secured-core server, Credential Guard, Hypervisor-protected Code Integrity (HVCI), and DNS-over-HTTPS. Existing Windows Server 2016, 2019, and 2022 bundles remain available. You can use the managed Windows Server 2025 bundles or create a custom bundle and image. This support is available in all AWS Regions where Amazon WorkSpaces is available. For more information, visit the Amazon WorkSpaces FAQs.
  • AWS Builder ID now supports Sign in with GitHub and Amazon — AWS Builder ID now supports two additional social login options: GitHub and Amazon. These options join the existing Google and Apple sign-in capabilities. With this update, developers can access their AWS Builder ID profile — and services including AWS Builder Center, AWS Training and Certification, and Kiro — using their existing GitHub or Amazon account credentials, without managing a separate set of credentials. To learn more and get started, visit the AWS Builder ID documentation.
  • Amazon Redshift introduces reusable templates for COPY operations — Amazon Redshift now supports templates for the COPY command, allowing you to store and reuse frequently used COPY parameters. Templates help maintain consistency across data ingestion operations, reduce the effort required to execute COPY commands, and simplify maintenance by applying template updates automatically to all future uses. Support for COPY templates is available in all AWS Regions where Amazon Redshift is available, including the AWS GovCloud (US) Regions. To get started, see the documentation or read the Standardize Amazon Redshift operations using Templates blog.

For a full list of AWS announcements, be sure to keep an eye on our News Blog channel the What’s New with AWS page.

Upcoming AWS events
Check your calendar and sign up for upcoming AWS events:

AWS Summits – Join AWS Summits in 2026, free in-person events where you can explore emerging cloud and AI technologies, learn best practices, and network with industry peers and experts. Upcoming Summits include Paris (April 1), London (April 22), and Bengaluru (April 23–24).

AWS Community Days – Community-led conferences where content is planned, sourced, and delivered by community leaders, featuring technical discussions, workshops, and hands-on labs. Upcoming events include Pune (March 21), San Francisco (April 10), and Romania (April 23-24).

AWS at NVIDIA GTC 2026 — Join us at our AWS sessions, booths, demos, and ancillary events in NVIDIA GTC 2026 on March 16 – 19, 2026 in San Jose. You can receive 20% off event passes through AWS and request a 1:1 meeting at GTC.

AWS Community GameDay Europe — Taking place on March 17, 2026, AWS Community GameDay Europe is a team-based, hands-on AWS challenge event running simultaneously across 50+ cities in Europe. Your team is dropped into a broken AWS environment — misconfigured services, failing architectures, and security gaps — and has two hours to fix as much as possible. Find your nearest city and sign up at awsgameday.eu.

Join the AWS Builder Center to connect with builders, share solutions, and access content that supports your development. Browse here for upcoming AWS-led in-person and virtual events and developer-focused events.

That’s all for this week. Check back next Monday for another Weekly Roundup!

— Esra

This post is part of our Weekly Roundup series. Check back each week for a quick roundup of interesting news and announcements from AWS!

Read the whole story
alvinashcraft
23 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Agents write code. They don’t do software engineering.

1 Share
Abstract illustration of a software developer standing at a crossroads, representing the human judgment and strategic trade-offs required in software engineering alongside AI agents.

Long-running and background coding agents have hit a new threshold. When an agent runs for hours, manages its own iteration loop, and submits a pull request without hand-holding, it stops being a tool you invoke and starts being more like a worker you assign tasks to. Like any worker, the question isn’t how closely you supervise them. It’s what work you assign them in the first place.

We are all figuring this out in real time, and I see many teams making an understandable but critical error. They tune the autonomy dial, adding more review checkpoints or removing them, when the actual variable that matters is which categories of work agents should own versus which categories developers should own. That distinction isn’t about risk tolerance. It’s about capability boundaries.

Code writing and software engineering are not the same job

Writing code is pattern recognition. Take what’s been done before, apply it to a new context, and scaffold it out. Large language models are exceptional at this because that’s exactly what they do: recognize and reproduce patterns from massive corpora of prior work.

Software engineering is something else. It’s trade-offs. Constraints. Decisions that require context no model has access to: your business domain, your product strategy, your customers, your technical debt, the conversation your team had last week about why you chose one approach over another.

Most teams split on importance or risk tolerance. The real divide is between work that can be reasoned from prior patterns and work that requires context, strategy, and judgment that lives outside the codebase.

What developers actually own

The work that actually requires developers is more specific than “anything important,” but it doesn’t reduce to a tidy list of task types. It cuts across every part of the engineering process.

“Agents can read code. They cannot read the room.”

Developers own the work where the right answer depends on context that doesn’t exist in the codebase. Product strategy, business constraints, team dynamics, conversations in Slack threads, and architecture reviews are part of the history of why a system is built the way it is. Agents can read code. They cannot read the room.

Developers own the work where the risk profile is ambiguous, or the failure modes are hard to predict. Some changes cascade in ways that depend on organizational boundaries, deployment timing, or data contracts baked into a system over years of iteration. Evaluating correctness in those cases requires judgment that no model can drive from code alone. The higher the uncertainty, the more you need someone who understands not just what the code does but why it was written that way.

Developers own the work where the output is a decision, not an artifact: what to build, what to cut, and which technical bets to place six months from now. Agents can generate options. They cannot tell you which option is right for your situation because “right” depends on factors that reside in human heads and organizational contexts, not in training data.

And all of this is still evolving. As teams invest in making context more explicit through better documentation, clearer contracts, and more structured decision records, the boundaries shift. Work that once required a developer’s institutional knowledge becomes accessible to an agent. But the frontier of unstructured, high-judgment work keeps moving, too, and that’s where developer time is most valuable.

In distributed systems, this problem gets worse. The more services you spread across multiple teams and codebases, the more that critical context lives outside any single codebase. A change to one service’s event schema can break downstream consumers in ways that no test in that service’s own suite will catch.

Also: The agent doesn’t know what it doesn’t know. The developer on that team does — not because they wrote the code — but because they were in the meeting where the schema was agreed upon. For cloud-native teams, this scales badly: the more services, the more implicit contracts, and the more context that only people carry.

Where agents deliver the most value

There is a mountain of work in every codebase that is a waste of human brainpower. Boilerplate, scaffolding, repetitive refactors, unit test generation, configuration templating, and data formatting. This work is rote, mechanical, and can be reasoned entirely from prior patterns. Agents should own it.

Once a developer specifies the interface, contract, and expected behavior, an agent can implement faster and more consistently than a developer could. The implementation is the repeatable part. The reasoning that precedes it is not.

“The developers who thrive in this model won’t be the ones who write the most code. They’ll be the ones who make the best decisions.”

Iteration speed matters here, too. Generating multiple implementations, running test suites, checking contract conformance: agents do this at a pace no developer can match. Circle CI’s State of Software Delivery Report found that throughput bottlenecks most commonly appear in the feedback and validation loop, not the code-writing phase. Agents compress that loop significantly when the acceptance criteria are clear and they have access to the runtime environment and tools they need to validate their work.

The developers who thrive in this model won’t be the ones who write the most code. They’ll be the ones who make the best decisions about what to build and how to architect it, then hand off the execution to agents that can move faster than any human.

A three-column infographic detailing a task-division model between developers and AI agents, moving along a bottom spectrum from "Pattern execution" to "Engineering judgment." It outlines Tier 1 (Agent-Led, Developer-Reviewed) for routine tasks like boilerplate generation where the agent owns the work; Tier 2 (Agent-Assisted, Developer-Guided) for scoped feature work where developers provide judgment and agents provide throughput; and Tier 3 (Developer-Led, Agent-Supported) for complex tasks like architecture decisions where the developer drives and the agent merely assists.

A three-tier model for dividing the work

In our team, we have found it useful to implement a rough framework for bucketing engineering work categories to make decisions about how it is distributed between agents and developers.

Tier 1: Agent-led, developer-reviewed

Tasks where agent execution is high-confidence and the output is self-verifiable. Boilerplate generation, configuration templating, adding endpoints within established patterns, running and reporting on test suites, and scaffolding new services or modules from existing conventions. The developer reviews the output, but the agent owns the work.

Routing this to developers wastes your most expensive resource. This category should expand as teams get better at making their patterns explicit and testable.

Tier 2: Agent-assisted, developer-guided

Tasks that require context beyond the codebase to validate. The agent implements, but the developer defines the scope, constraints, and success criteria. Feature work within a well-understood domain, refactoring within established boundaries, and test implementation for developer-defined strategies fall here.

The developer provides the engineering judgment. The agent provides the implementation throughput. Most feature work, across any architecture, falls into this tier.

Tier 3: Developer-led, agent-supported

Tasks where the core work is judgment, not implementation. Architectural decisions, cross-boundary contract changes, debugging emergent failures, and defining what to build next. Agents can assist with subtasks: drafting proposals, analyzing logs, and generating candidate implementations for evaluation. But a developer must drive because the work itself is reasoning, not pattern execution.

The distinction from Tier 2 is that the developer isn’t just validating output. They’re doing the intellectual work that no amount of training data can substitute for.

The cost of getting the split wrong

Most teams I speak to are either under-allocating or over-allocating work to agents. Both are expensive mistakes.

Over-allocation is the more visible failure. Push agents into Tier 3 work, and they produce output that requires significant rework because the necessary context wasn’t available to them. The rework cost is real, but the opportunity cost is worse: developers who should be doing Tier 3 work are instead reviewing and correcting agent output that shouldn’t have been delegated in the first place.

Under-allocation is quieter but equally damaging. Teams that default to developer-owned work because agent output seems uncertain are paying developer rates for Tier 1 tasks. Developer time is the highest-cost resource on the team. Burning it on pattern-execution work that agents could handle is a slow drag on velocity that compounds over months.

This is why many teams adopting agentic workflows see limited gains or even slight decreases in merged code throughput. They haven’t solved the allocation problem. They’ve added a new tool without changing how work gets distributed.

Audit the work, not just the agents

The question isn’t whether agents replace developers. It’s what the right engineering model looks like when agents handle the mechanical work, and humans focus on the strategic work.

The teams navigating this well don’t just audit their agents. They audit their work. They ask which tasks could be agent-led if the boundaries were made explicit, then invest in making those boundaries explicit. That investment returns developer time to the high-judgment, context-dependent work that agents won’t own well anytime soon.

The answer won’t come from the AI labs. It’ll come from engineering teams actually building software this way every day, figuring out where the line is through practice, and learning what their specific codebase, team, and domain require on each side of the divide.

The post Agents write code. They don’t do software engineering. appeared first on The New Stack.

Read the whole story
alvinashcraft
24 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Introducing sshimg.nvim: Paste Images into Remote Neovim over SSH

1 Share

The problem

When you write Markdown locally, pasting images is trivial - plenty of Neovim plugins handle it. But when you're editing files on a remote server over SSH, your clipboard lives on a different machine than your editor. The remote Neovim has no access to your local clipboard, so none of those plugins work.

I ran into this while writing blog posts and documentation on remote machines. Taking a screenshot is easy, but getting that image from my local clipboard to the server and into the Markdown file required a manual workflow every time: save the screenshot locally, scp it over, then type the Markdown image link by hand.

How sshimg.nvim solves it

sshimg.nvim connects your local clipboard to your remote Neovim through a small daemon and an SSH reverse tunnel.

The flow looks like this:

Screenshot (local) → imgd daemon → SSH reverse tunnel → scp → Remote Neovim
  1. You take a screenshot on your local machine (it lands in the clipboard).
  2. You press <leader>pa or <leader>pp in Neovim.
  3. The plugin contacts the local daemon through the SSH reverse tunnel.
  4. The daemon reads the image from the clipboard, sends it to the server via scp.
  5. Neovim inserts a Markdown image link at the cursor position.

The result:

![](assets/2026-03-15-23-25-25.png)

Setup

Local machine

1. Install the daemon

The daemon imgd is a small Python script that reads images from wl-paste (Wayland) and serves them over a local port.

cp daemon/imgd.py ~/.local/bin/imgd
chmod +x ~/.local/bin/imgd

2. Start the daemon

Start it as a systemd user service:

cp daemon/imgd.service ~/.config/systemd/user/imgd.service
systemctl --user enable --now imgd

Or run it manually:

imgd

3. Connect with a reverse tunnel

The reverse tunnel forwards port 9999 from the remote server back to your local machine, so the plugin can reach the daemon.

ssh -R 9999:localhost:9999 yourserver

Or add it to ~/.ssh/config so you don't have to type it every time:

Host yourserver
    RemoteForward 9999 localhost:9999

Remote server

Install the plugin with your package manager. For lazy.nvim:

return {
"AlexZeitler/sshimg.nvim",
config = function()
require("sshimg").setup({
port = 9999,
host = "127.0.0.1",
keymaps = {
assets = "<leader>pa", -- Save to ./assets/
parallel = "<leader>pp", -- Save to same dir as current file
},
})
end,
}

The values shown are the defaults - you only need to change them if your tunnel uses a different port.

Usage

  1. Take a screenshot (it lands in your local clipboard).
  2. Open a Markdown file in remote Neovim.
  3. Press <leader>pa to save the image to ./assets/ or <leader>pp to save it next to the current file.

The plugin inserts the Markdown image link at your cursor position automatically.

Neovim with a pasted Markdown image link over SSH

Requirements

Local machine:

  • wl-paste (Wayland)
  • scp
  • Python 3

Remote server:

  • Neovim
  • Python 3

Early days

sshimg.nvim currently supports Linux with Wayland. Support for X11 and macOS is planned. If you run into issues or have ideas, feel free to open an issue or send a pull request on GitHub.

Read the whole story
alvinashcraft
24 minutes ago
reply
Pennsylvania, USA
Share this story
Delete

Why Your Growth Strategy Needs Auth0 Tenancy-as-a-Service

1 Share
Scale your B2B SaaS faster with Auth0 Tenancy-as-a-Service. Automate multi-tenancy, SCIM, and SSO to close enterprise deals without the engineering overhead.

Read the whole story
alvinashcraft
24 minutes ago
reply
Pennsylvania, USA
Share this story
Delete
Next Page of Stories