DEV Community

Dencio
Dencio

Posted on

Your Coding Agent Can Read the Code—but Can It See the App Fail?

TailFlow gives coding agents compact, queryable evidence from the applications
they are changing—without sending local logs to a hosted platform.

Coding agents are increasingly capable of navigating repositories, editing
multiple files, running tests, and explaining unfamiliar systems.

But there is still a gap in the typical agent workflow:

The agent can read the code, but it often cannot see what happens after the
application starts.

A build may pass while the development server fails during startup. A frontend
may compile but crash during hot reload. A background worker may begin retrying
indefinitely. A Docker container may restart with a configuration error.

If the agent cannot observe that output, the workflow usually becomes:

agent edits code
→ checks pass
→ application fails at runtime
→ developer notices the terminal error
→ developer copies the error back to the agent
→ agent tries again
Enter fullscreen mode Exit fullscreen mode

That manual handoff is the problem
TailFlow is designed to solve.

Runtime verification for coding agents

TailFlow is an open-source, local runtime-verification layer for coding agents.

It collects output from:

  • Development processes
  • Local Docker containers
  • Log files
  • Piped standard input

TailFlow then exposes the same bounded runtime view through:

  • MCP tools for coding agents
  • A shell CLI for scripts and terminal-based agents
  • An interactive terminal UI
  • A local web dashboard
  • An HTTP API and Server-Sent Events stream

The goal is not simply to display logs. The goal is to let an agent answer
concrete questions:

  • Did the expected services actually start?
  • Did my edit trigger a successful rebuild?
  • What failed after this change?
  • Is this a new failure or an old one?
  • Is the service healthy, or did it never start?
  • Is this one error repeated hundreds of times?

The resulting loop looks like this:

capture the stack
→ establish a baseline
→ make the change
→ wait for the runtime outcome
→ inspect failures
→ verify the fix
Enter fullscreen mode Exit fullscreen mode

Why tests are not enough

Tests remain essential, but they prove only what they exercise.

A passing test suite does not necessarily prove that:

  • Environment variables are available
  • Ports can be bound
  • Containers can communicate
  • A development server completed startup
  • Hot reload succeeded
  • A background job finished
  • A real request followed the expected path

Runtime output contains evidence that static analysis and isolated tests cannot
provide. TailFlow makes that evidence accessible to the agent without requiring
the developer to continually watch several terminal tabs.

Getting started in about five minutes

Install TailFlow through npm:

npm install -g tailflow
Enter fullscreen mode Exit fullscreen mode

This installs four commands:

Command Purpose
tailflow Interactive TUI and project initializer
tailflow-daemon Runtime collector and local API
tailflow-mcp MCP bridge for coding agents
tailflow-logs Shell client for queries and automation

From the root of a project, run:

tailflow init
Enter fullscreen mode Exit fullscreen mode

TailFlow detects common runtime sources, including:

  • dev, serve, and start scripts in package.json
  • pnpm, Yarn, Bun, and npm project metadata
  • Docker Compose files
  • Common local log directories

It then proposes a configuration:

TailFlow v0.3.2

TailFlow found:

  1. process web: pnpm run dev [recommended]
  2. Docker containers (compose.yml) [recommended]
  3. file worker: logs/worker.log [recommended]

Select sources:
Enter fullscreen mode Exit fullscreen mode

After selection, TailFlow writes a tailflow.toml file. Existing configurations
are never replaced unless --force is explicitly provided.

For noninteractive environments:

tailflow init --yes
Enter fullscreen mode Exit fullscreen mode

You can also specify sources directly:

tailflow init \
  --docker \
  --process 'api=go run ./cmd/api' \
  --file logs/worker.log
Enter fullscreen mode Exit fullscreen mode

Start the collector:

tailflow-daemon
Enter fullscreen mode Exit fullscreen mode

The local dashboard becomes available at
http://127.0.0.1:7878.

Verify the connection from another terminal:

tailflow-logs status
tailflow-logs sources
Enter fullscreen mode Exit fullscreen mode

Connecting a coding agent

For Claude Code:

claude mcp add tailflow -- tailflow-mcp
Enter fullscreen mode Exit fullscreen mode

For another MCP-compatible client:

{
  "mcpServers": {
    "tailflow": {
      "command": "tailflow-mcp"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

The MCP server gives the agent four focused tools.

list_log_sources

Shows which sources are running, exited, failed, or merely observed.

This distinction matters. An empty error list does not prove that a service is
healthy—it may never have started.

get_recent_errors

Returns distinct recent failures with occurrence counts and related stack
context.

Instead of filling the agent's context window with the same crash 400 times,
TailFlow can condense it into one failure group:

x400 connection refused: postgres:5432
     at Pool.connect (...)
Enter fullscreen mode Exit fullscreen mode

search_logs

Returns exact records with source, severity, time, regular-expression, and
cursor filters. This is useful when exact values or event ordering matter more
than deduplication.

wait_for_logs

Waits inside the daemon until a runtime event appears. An agent can wait for:

compiled successfully
server listening
migration complete
request finished
error|failed|panic
Enter fullscreen mode Exit fullscreen mode

This replaces arbitrary sleep-and-poll loops with event-driven verification.

Separating new failures from old failures

One of TailFlow's most important features is its cursor model.

Every captured record receives a monotonically increasing sequence number. The
agent can save the current cursor before making a change and request only
records that appeared afterward.

baseline cursor: 241
        │
        ├── edit application code
        ├── hot reload begins
        └── wait after cursor 241
              ├── compilation succeeded
              └── server ready
Enter fullscreen mode Exit fullscreen mode

This changes the question from:

Are there errors in the logs?

to:

What happened after this specific edit?

TailFlow also reports when the requested cursor has fallen outside its bounded
buffer. That prevents an agent from presenting incomplete evidence as proof
that nothing failed.

One runtime model for developers and agents

TailFlow deliberately gives humans and agents access to the same underlying
data.

Developers can use the terminal UI:

tailflow
Enter fullscreen mode Exit fullscreen mode

Or inspect Docker directly:

tailflow --docker
Enter fullscreen mode Exit fullscreen mode

Shell-based agents and scripts can query the daemon:

tailflow-logs errors --since 5m
tailflow-logs search 'timeout' --source api
tailflow-logs wait --grep 'compiled successfully|Failed to compile'
Enter fullscreen mode Exit fullscreen mode

The web dashboard provides live following, severity filters, source counts, and
regular-expression search.

This shared model makes agent behavior easier to audit: the developer can
inspect the same runtime evidence the agent used to reach its conclusion.

TailFlow is intentionally local

TailFlow is not trying to replace production observability platforms.

It does not provide:

  • Hosted log storage
  • Distributed tracing
  • Metrics or profiling
  • Production alerting
  • Multi-tenant access control
  • Autonomous service remediation

Instead, it focuses on one job:

Give a coding agent timely, compact evidence from the local software it is
changing.

The daemon binds to loopback, stores a bounded in-memory buffer, and does not
require an account or hosted service.

That makes it useful during development, but it also creates important
limitations:

  • History disappears when the daemon restarts
  • High-volume stacks can evict older records
  • Severity detection and error grouping are heuristic
  • Docker discovery currently follows all local containers
  • Logs may contain secrets, and TailFlow does not redact them
  • The local API should not be exposed directly to a network

These boundaries are documented rather than hidden behind a generic “healthy”
result.

What arrived in TailFlow 0.3.2

Version 0.3.2 focuses on reducing setup friction and making the project easier
to understand and operate.

The release includes:

  • Guided project initialization with tailflow init
  • Automatic discovery of development scripts, Compose files, and log files
  • Package-manager-aware generated commands
  • Safe interactive and noninteractive configuration
  • Explicit process, file, and Docker source flags
  • Version banners across the TUI, dashboard, initializer, daemon, and MCP startup
  • Reworked documentation organized around the runtime-verification problem
  • Clearer limitations, architecture guidance, feature framing, and roadmap

The broader direction is to make runtime verification a normal step in an agent
coding loop—not a manual debugging step performed only after the agent declares
success.

What comes next

Planned directions include:

  • Letting the MCP bridge optionally start a local daemon
  • Serving MCP directly from the daemon over streamable HTTP
  • Comparing failure groups before and after an edit
  • Better startup and readiness signals
  • Compose-aware container selection
  • Optional bounded local persistence
  • Correlation across services using request or job identifiers

TailFlow will remain local-first, bounded for agent context, and explicit about
incomplete evidence.

Try TailFlow

TailFlow is open source and licensed under MIT.

npm install -g tailflow
cd your-project
tailflow init
tailflow-daemon
Enter fullscreen mode Exit fullscreen mode

Then connect your coding agent or explore the local dashboard at
http://127.0.0.1:7878.

Project links:

If your coding agent has ever produced a change that looked correct while the
application was visibly failing in another terminal, TailFlow is built for that
missing part of the loop.

Top comments (0)