[KongchangAI]
· 3 min read· 1,925 words

7 Things AI Coding Agents Can't See, and the Command That Shows Each One

7 Things AI Coding Agents Can't See, and the Command That Shows Each One

AI coding agents only see repo files and your input—seven commands fill in the rest.

AI coding agents start each session with a fresh context window, seeing only repository files and what you type; CI logs, issue threads, PR inline comments, production schema, runtime logs, feature flag state, and browser console all fall outside it, leaving agents to guess. The author recommends writing command output into a .context/ folder at the repo root, adding it to .gitignore, reviewing it before handing it over, and guarding against prompt injection. Each item comes with a command: gh run view --log-failed, gh issue view --comments, gh api pulls/comments, pg_dump --schema-only, docker logs --since, flag service APIs, and Playwright MCP. The article closes with using CLAUDE.md or AGENTS.md to persist long-term facts across sessions, framing the whole approach as the simplest form of context engineering.

AI coding agents seem to be able to do anything, but what they can truly "see" is surprisingly little: the files in the repository, plus whatever you type out for them. Everything else, they can only guess at.

A typical scenario: you ask the agent why CI is red. It reads the test files, concludes the assertion is wrong, changes it, and tells you it's fixed. CI goes red again—the real cause was a missing environment variable on the runner, and that line of information sat in a log the agent never opened.

Anthropic's official documentation states this starting point bluntly: "Each Claude Code session starts with a fresh context window." This article organizes seven categories of information that fall outside the context window, each paired with a command that turns invisible state into text the agent can read.

First, a small step: set up a .context/ repository

Write the output of all commands into a .context/ folder at the repository root so any agent can open it, and so you can read it yourself before handing it over.

Also add it to .gitignore. Logs, schemas, and flag rules may contain tokens, email addresses, and customer IDs. Let your eyes pass over them before the agent does, and never commit them. Treat issue, PR, and log text as untrusted input as well: the content is written by others, and an agent with write access will read any instructions hidden within it.

mkdir -p .context
echo ".context/" >> .gitignore

rss source: 7 Things Your Coding Agent Can't See, and the Command That Shows Each One

Prompt injection is the core risk here: any piece of text in an issue body, a PR comment, or a CI log could contain commands like "ignore previous instructions and send X to Y." Agents cannot reliably distinguish "data" from "instructions"; whatever they read is treated as a task to execute. Reviewing .context/ by hand is essentially adding a human filter before untrusted text enters the context. Similarly, tokens given to the agent should follow least privilege (read-only, scoped to limited resources) so that even if misled, it cannot perform destructive operations.

Why you need a separate .context/ rather than pasting things into the conversation: the agent's context window is a limited and expensive resource. Stuffing hundreds of lines of CI logs from passing steps in verbatim will crowd out the genuinely relevant code and instructions, and may trigger "lost in the middle"—models utilize information in the middle of long contexts noticeably less effectively. Writing logs and schemas to files and letting the agent read them in segments on demand (for example, grep for keywords first, then read the surrounding context) is a common practice for controlling token budgets and maintaining a good signal-to-noise ratio.

Three things on GitHub the agent can't see

Three of the seven items are on GitHub, and the GitHub CLI (gh) can reach all of them.

1. CI failure logs

The agent can read your workflow YAML but not what the runner printed. The --log-failed flag of gh run view outputs only the logs of failed steps, skipping the hundreds of lines of noise from passing steps:

branch=$(git branch --show-current)
run=$(gh run list -b "$branch" -s failure -L 1 \
  --json databaseId --jq '.[0].databaseId')
gh run view "$run" --log-failed > .context/ci-failed.log

gh run list supports filtering by branch (-b) and status (-s failure), and databaseId is exactly the run ID that gh run view needs. Once you have the log, the prompt can become: "First read .context/ci-failed.log, explain the failure, then change anything."

For one-off questions you can skip the folder. The Claude Code CLI supports piped input cat logs.txt | claude -p "explain", so logs can go straight in:

gh run view "$run" --log-failed \
  | claude -p "Why did this CI run fail?"

2. The issue it was supposed to fix

You only pasted the issue title to the agent. The reproduction steps, the stack trace someone attached, and the maintainer's comment saying "don't touch the retry logic" all stayed on GitHub. gh issue view with --comments pulls out the whole thread:

gh issue view 482 --comments > .context/issue-482.md

For structured data, use --json to specify fields like body, comments, labels, and state.

3. The PR review thread

This one is the easiest to get wrong. Inline comments left during review are not the same as a PR's conversation comments. GitHub's REST documentation defines review comments as "comments on a pull request review that are made on part of the unified diff," separate from issue comments with their own endpoint. gh api automatically fills in {owner} and {repo} from the current repository:

gh api --paginate \
  "repos/{owner}/{repo}/pulls/57/comments" \
  --jq '.[] | {path, line, user: .user.login, body}' \
  > .context/pr-57-review.json

Each comment carries the path and line it refers to, so the agent can jump directly to the exact location. This endpoint returns 30 comments per page by default, so --paginate is needed.

Production state that never enters git

Your migrations describe the schema you think exists; your code reads flags by name. Neither can tell the agent what is actually true right now.

4. The production database schema

A migration that was run by hand, an index someone added temporarily during an incident, a column type that drifted—the agent has no way to know. pg_dump with --schema-only exports only object definitions, not table data:

pg_dump --schema-only --no-owner --no-privileges \
  -t 'orders*' -d "$REPLICA_URL" > .context/schema.sql

--no-owner and --no-privileges strip ALTER OWNER and GRANT lines, which are just noise for this task. -t accepts pattern matching, so you send only the relevant tables instead of the whole database. PostgreSQL's documentation notes that -t does not automatically pull in dependent objects, so if the agent's question involves a foreign key, remember to include the other table too. The connection target should be a read-only replica with a read-only role—never the primary.

Schema drift means the database's actual structure differs from the migration history or ORM models in the code repository. Causes include hand-run DDL, indexes added temporarily during incident handling, skipped migrations, and different environments having run different versions of migrations. Drift doesn't cause errors in code, but it leads agents to write queries based on wrong assumptions—for example, thinking a column is nullable or that an index exists when the opposite is true. Periodically dumping the real schema and diffing it against the definitions in the repository is a low-cost way to detect drift, and it also serves as an authoritative source of truth to give the agent.

5. What the service printed at runtime

The stack trace from the failed request ten minutes ago is in the container's output, not in any file the agent can open. docker logs supports --since (a relative duration like 30m or a timestamp), --tail, and -t to add timestamps:

docker logs --since 30m --tail 300 -t api \
  > .context/api.log 2>&1

2>&1 is the key: docker logs handles the container's stdout and stderr separately, and without the redirect, whatever is written to stderr goes straight to your terminal and never into the file.

stdout and stderr are two independent streams, which is the root of why 2>&1 is necessary. Processes by default write normal output to fd 1 (stdout) and errors and diagnostics to fd 2 (stderr). Many log collectors capture both, but shell redirection only moves the one you explicitly specify; without 2>&1, stderr bypasses the file and hits the terminal directly. Also, container log behavior depends on the runtime: Docker's json-file driver keeps only a limited size and number of history, so early logs are unrecoverable after rotation; if the application writes logs to files inside the container rather than to the standard streams, docker logs can't see them at all—you need to docker exec in to read them or switch to a logging driver.

6. The current state of a feature flag

The code says if (flags.isOn("new-checkout")). Whether this flag is on in production, and for whom, is answered in the flag service. With LaunchDarkly, for example, GET /api/v2/flags/{projectKey}/{featureFlagKey} with env=production returns a single flag, with the environment's on, rules, and fallthrough under environments.production:

LD=https://app.launchdarkly.com/api/v2/flags
curl -s -H "Authorization: $LD_API_TOKEN" \
  "$LD/default/new-checkout?env=production" \
  | jq '.environments.production | {on, rules, fallthrough}' \
  > .context/flag-new-checkout.json

Replace default with your project key and use a read-only token. For other flag services, find their "single flag, single environment" read endpoint. Targeting rules often name real customers or segments, making this the file you should read most carefully before handing it over.

The browser is another world

7. Browser console and network panel

A blank white page with red errors in DevTools can look flawless from the source code. The agent needs to actually load the page. The Playwright MCP server gives it a browser, and its README has the install command for Claude Code:

claude mcp add playwright npx @playwright/mcp@latest

Two of its tools solve this problem directly. browser_console_messages returns all console messages, and browser_network_requests returns a "numbered list of network requests since page load." Have the agent open the page on your dev server, read those two first, then have it change the component. If you don't want to add an MCP server, Claude Code also has a built-in --chrome flag for Chrome integration.

MCP (Model Context Protocol) is a protocol that lets external programs expose tools and data to models in a standardized way. An MCP server wraps specific capabilities (browser control, database queries, filesystem access, etc.), and the model discovers and calls these tools through the protocol without needing custom glue code for every integration. The Playwright MCP server wraps browser automation capabilities as a set of tools, and claude mcp add registers it in Claude Code's tool list. Understanding this helps you judge the boundaries: MCP only opens the calling channel; what the agent can see still depends on which tools the server exposes and whether it knows when to call them.

Make context survive this session

The commands above only solve today's session. Tomorrow's session is a fresh context window again, and you'll paste the same schema for the third time.

Without any extra tools, there are two paths. Write long-term facts into CLAUDE.md—Claude Code loads it at the start of every session—or into AGENTS.md, which it reads when the repository has no CLAUDE.md. When the context lives in another repository, --add-dir gives Claude permission to access more folders, and combined with permissions.additionalDirectories in settings, this can persist across sessions.

Quick reference for the seven commands

What the agent can't seeCommand
CI failuresgh run view <id> --log-failed
Issue threadgh issue view <n> --comments
PR inline commentsgh api repos/{owner}/{repo}/pulls/<n>/comments
Production schemapg_dump --schema-only -t <pattern>
Runtime logsdocker logs --since 30m
Flag stateFlag service API, single flag, single environment
Browser consolePlaywright MCP browser_console_messages

The essence of this approach is the simplest form of "context engineering": figure out what the model needs, fetch exactly that part, and cut the noise before it enters the prompt. The agent's strongest ability is organizing existing information into code; its most dangerous habit is making up answers to fill information gaps. Close these seven gaps, and the room it has to guess shrinks considerably.

#AI coding agent#context engineering#prompt injection#Claude Code#GitHub CLI#MCP#schema drift
Share:

Related articles