<p>Most people use Elyra by typing natural language. "Fix the auth module." "Add tests for the user service." That works, and it's the right default. But there are four single-character prefixes that unlock a different way of working — one where you control exactly what the agent sees and what it doesn't.</p><h2><code>!</code> — run a command, show the agent</h2><pre><code>!npm test
</code></pre><p>This runs <code>npm test</code> in your shell and sends the output to the agent as context. The agent sees everything — pass, fail, error traces, warnings.</p><p>Why this matters: instead of telling the agent "run the tests and fix what's broken," you run the tests yourself and the agent sees the real output. No interpretation layer. No "I'll run the tests for you" followed by a tool call. You already have the result.</p><pre><code>!npm test -- --run test/auth.test.ts
3 tests failed. Fix them.
</code></pre><p>Two lines. The agent has the exact failure output and your instruction. No ambiguity about which tests, no wasted turn running them again.</p><p>This is especially useful for commands you run constantly:</p><pre><code>!php artisan route:list --path=api
Add a PATCH route for updating user profiles, following the same pattern.
</code></pre><pre><code>!cat .env | grep DB_
The database credentials are wrong. Update them for the staging environment.
</code></pre><pre><code>!curl -s localhost:3000/api/health | jq .
The health endpoint is returning a 500. Fix it.
</code></pre><p>The output becomes part of the conversation. The agent can reference it, reason about it, and act on it.</p><h2><code>!!</code> — run a command, keep it private</h2><pre><code>!!git log --oneline -10
</code></pre><p>Same as <code>!</code>, but the output stays between you and your terminal. The agent never sees it.</p><p>This is for when you need to check something without polluting the context window. Every token in the agent's context costs money and affects quality. If you're just checking whether a branch exists or glancing at a log, the agent doesn't need to carry that information for the rest of the session.</p><pre><code>!!git status
!!cat package.json | jq .version
!!ls src/components/
</code></pre><p>You see the output. You make a decision. Then you tell the agent what to do based on what you saw — in your own words, with only the relevant parts.</p><p>The difference between <code>!</code> and <code>!!</code> is the difference between "here's a dump of 200 lines of test output, figure it out" and "three auth tests are failing because the session token format changed." The second is cheaper and often more effective.</p><h2><code>/</code> — talk to Elyra, not the agent</h2><pre><code>/model
/tree
/goal npm run check
/rewind
/update
</code></pre><p>Slash commands control Elyra itself. They don't send anything to the LLM. They're free — zero tokens, zero latency.</p><p>The ones you'll use most:</p><p>Command What it does <code>/goal npm run check</code> Agent keeps working until the command passes <code>/tree</code> Navigate the session tree, switch branches <code>/rewind</code> Roll back conversation and files to a previous point <code>/model</code> Switch models mid-session <code>/compact</code> Compress conversation to free context space <code>/update</code> Update Elyra and restart without leaving</p><p>Extensions add their own. <code>/workflow deploy</code> runs a pipeline. <code>/ext</code> browses installable extensions. Type <code>/</code> and let autocomplete show you what's available.</p><h2><code>@</code> — point at a file</h2><pre><code>@src/auth/service.ts What does the login method do?
</code></pre><p>The <code>@</code> prefix fuzzy-matches a file in your project and includes its content in your message. Tab completes the path.</p><p>This is faster than asking the agent to read the file. The agent would call the read tool, wait for the result, then process it. With <code>@</code>, the content is already in the message — one round trip instead of two.</p><p>You can reference multiple files:</p><pre><code>@src/auth/types.ts @src/auth/service.ts
Refactor the service to use the new AuthResult type from types.ts
</code></pre><p>Both files arrive in the same message. The agent sees them together and can reason about the relationship without separate read calls.</p><p>It works for images too:</p><pre><code>@screenshot.png What's wrong with this layout?
</code></pre><h2>Putting them together</h2><p>Here's a real workflow that uses all four:</p><pre><code>!!git diff --stat                          # Check what's changed (private)
!npm run check                             # Run type checker (agent sees errors)
Fix all the type errors                    # Agent works on the errors
/goal npm run check                        # Keep going until it passes
</code></pre><p>Four lines. The first checks the state without adding noise. The second gives the agent the exact errors. The third is the instruction. The fourth automates the loop.</p><p>Or a different pattern — investigating before acting:</p><pre><code>!!php artisan route:list | grep user       # Check existing routes (private)
@app/Models/User.php                       # Include the model
Add a phone verification endpoint following the project's route conventions
</code></pre><p>You looked at the routes privately, decided what was needed, then gave the agent the model and a clear instruction. The agent didn't waste tokens reading route files — you already knew the pattern.</p><h2>The mental model</h2><p>Think of it as four channels:</p><ul><li><p><strong>Plain text</strong> → goes to the agent as a message</p></li><li><p><code>!</code> → runs in your shell, agent sees the result</p></li><li><p><code>!!</code> → runs in your shell, only you see it</p></li><li><p><code>/</code> → talks to Elyra, agent is not involved</p></li><li><p><code>@</code> → includes a file in your message</p></li></ul><p>The agent's context window is finite and expensive. These prefixes give you precise control over what goes in and what stays out. Use <code>!</code> when the agent needs to see something. Use <code>!!</code> when it doesn't. Use <code>@</code> when you already know which file matters. Use <code>/</code> when you're steering the tool, not the model.</p>