◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 3 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 3 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/Dev Tools
⟐ Dev Tools/2026-10-20Intermediate

Typed @config and the Wrong File Went In? Checking Gemini CLI's @ Reference for Silent First-Match Picks

A bug report says Gemini CLI's @ reference silently picks the first hit when a name is ambiguous. Here is how I check for same-name files before typing @, with a small Python script and a test run.

gemini-cli9troubleshooting92at-commandglobpython110

One evening I was about to hand a settings file to Gemini CLI from one of my own projects. I typed @config and stopped. As an indie developer I keep two config.json files in that repository, one for the app and one for the server, and I could not say which of them would go in.

That reminded me of a GitHub issue I had read a few days earlier. It says that when an @ reference does not resolve directly, the CLI falls back to a glob and uses only the first line of its output. Below I lay out what the report says and the check I now run in folders full of same-name files.

I should say up front that I have not reproduced this behavior myself. Everything under "What the report says" is a summary of the issue, nothing more.

What the report says

Issue #29318 points at the fallback in atCommandProcessor.ts:

The glob output is split by newline and a fixed line index is read, which is fragile. Even when several files match, only the first one is used. The fallback path skips the workspace-trust check. With several workspace roots, the roots are searched one after another instead of in parallel.

The reproduction is short: type an ambiguous reference such as @config, and the first of two or more matches is chosen without asking. The expected behavior listed is to ask the user to disambiguate.

The report names commit 9c1b0a610 on main and gives no version or OS. The only comment is someone offering to take the fix, and no workaround is mentioned. So what I can say for certain is limited to "this has been reported."

Why a silent pick hurts

Nothing errors. The model answers from whatever file arrived, and the answer reads fine. If server/config.json goes in when you meant app/config.json, a reply like "this configuration looks fine" is a verdict on the wrong file. You find out when the real device behaves differently.

The check: count before you type

I cannot change the CLI, so I changed my habit. Before writing a short name after @, I count how many paths it matches. One match, go ahead. Two or more, write the full path.

This script lists files and directories whose names contain a fragment, skipping folders like node_modules:

#!/usr/bin/env python3
"""Count how many files an @name would match before you type it."""
import fnmatch
import os
import sys
 
SKIP = {".git", "node_modules", ".next", "build", "dist"}
 
 
def find_matches(root, needle):
    hits = []
    for base, dirs, files in os.walk(root):
        dirs[:] = [d for d in dirs if d not in SKIP]
        for name in files + dirs:
            if fnmatch.fnmatch(name.lower(), f"*{needle.lower()}*"):
                hits.append(os.path.relpath(os.path.join(base, name), root))
    return sorted(hits)
 
 
if __name__ == "__main__":
    needle = sys.argv[1]
    root = sys.argv[2] if len(sys.argv) > 2 else "."
    hits = find_matches(root, needle)
    for h in hits:
        print(h)
    if len(hits) > 1:
        print(f"ambiguous: {len(hits)} matches. Write the full path after @", file=sys.stderr)
        sys.exit(1)
    sys.exit(0 if hits else 2)

I walk files and directories together because ls and a quick glance both miss a directory that shares a name with a file. The exit codes are separate (1 for ambiguous, 2 for nothing found) so a shell wrapper can tell the two apart.

Running it on a small tree

I built a throwaway tree with app/config.json, server/config.json, app/config/dev.yaml and node_modules/x/config.json, then ran the script.

ArgumentOutputExit code
configapp/config, app/config.json, server/config.json1 (ambiguous)
dev.yamlapp/config/dev.yaml0

The node_modules copy stays out, and the directory app/config is counted. So @config there had at least three plausible readings.

The lines I drew

First, I write the full path after @ whenever I can. A short name is fine only after I have confirmed a single match.

Second, I ask the model to mention something specific from the attached file at the start of its answer, so a mix-up shows early.

Third, when same-name files keep piling up, I rename them or exclude some with .geminiignore.

That last one is partly a workaround and partly housekeeping. If the repository has five files with the same name, people mix them up too.

For related habits, see grepping a known-bug table before loading context and auditing approval policies that never matched.

Clues that the wrong file went in

Even with the habit, there are days I type a short name anyway. I have a few clues for catching it afterwards.

If the answer mentions keys or function names I have not seen in the file I meant, I suspect the attachment. The reverse is just as telling: nothing at all about a setting I know is there. When a reply says "the configuration is fine" without touching a single concrete value, I ask what was actually read.

The follow-up can be tiny. "Tell me the path of the file you just read, in one line" is usually enough to expose a mix-up. Early on I skipped that check and worked for hours on the wrong assumption before backing out. Now I ask once, right after attaching a settings file.

If a fix lands

The issue proposes using the structured glob API, asking when several files match, and applying the trust check. If that ships, part of this check becomes unnecessary. Even so, knowing how many same-name files you have is cheap and keeps paying off.

One thing to try today: take the names you type most often (config, index, README) and pass each to the script once. The counts will show you where a bare name is safe after @ and where it is not.

A bare name only when I know there is exactly one. I intend to keep that rule whatever the CLI does next.

Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

⟐ Dev Tools2026-09-29
Gemini CLI Kept Saying 'API key not valid' After I Gave It a New Key — It Was Reading an Old One From a Third Place
I switched Gemini CLI from Google login to a paid API key, and the 400 'API key not valid' error would not go away. The key can come from four places — the shell, a project .env, a home .env, and settings.json — and a short script that lights them up in order narrows the cause to one.
⟐ Dev Tools2026-09-15
The approval rules I had written never matched once — auditing my Gemini CLI policies
A deny rule I trusted for half a year had never matched. The pattern was tested against a JSON string, the folder I kept my rules in is not read, and ask_user turns into deny the moment nobody is watching. Here is the audit, and the script I wrote to keep doing it.
⟐ Dev Tools2026-10-19
I Set the MCP Timeout to 10 Minutes and It Still Cuts Off at 1 — Tracing Which Layer Decides the Value
You raised an MCP server's timeout in Gemini CLI and it still ends early. A small script lists the value from every config layer, catching unit slips and extension overrides, plus the order I check things in.