There’s a funny pattern that shows up when developers start using AI tools heavily. At first, we ask the model to do everything directly. Find all the JSON files with a certain property. Update them. Check whether they are valid. Summarize what changed. Then do the same thing again for another folder.
That works, and it can feel magical the first few times. But after a while, it starts to look less like software engineering and more like asking a brilliant assistant to manually click the same button 400 times. The assistant may be smart, but the workflow is not.
At some point, the better move is not to keep asking the model to perform the task. The better move is to ask the model to write the tool. That tool might be a Bash script, a PowerShell script, a Python utility, a small Node.js program, or even a Makefile target. The language matters less than the shift in thinking: use the LLM for judgment and code generation, then use deterministic scripts for repeatable execution.
This is one of the most underrated ways to save on AI usage. Once the script exists, you can run it again and again without spending another Copilot premium request, GitHub AI Credit, or frontier-model prompt. That is not just cheaper. It is also usually safer, faster, easier to review, and more repeatable.
Stop Using The Model As An Expensive File Scanner
A common example is repository cleanup. Suppose you need to find every C# file that does not contain a copyright header. The first instinct may be to ask your AI assistant to search the repository and list every .cs file missing the header. Then, after it gives you an answer, you ask it to add the header. Then you ask it to verify that all files now have the header.
This may work, but it is not the best use of the model. At that point, you are using AI as a very expensive file scanner. Computers are already good at scanning files. They can walk directories, read text, match patterns, update files, and print summaries without needing a language model in the loop every time.
A better prompt is not, “Please inspect all these files for me.” A better prompt is, “Write a script that scans these files deterministically, updates only the ones that need changes, supports a dry-run mode, excludes generated folders, and prints a clear summary.” Now the model is doing what it is good at: helping you create automation. The script is doing what computers are good at: repeating a well-defined process the same way every time.
That is the sweet spot. AI helps design and generate the tool. The tool does the repetitive work.
The Better Prompt Pattern
Instead of walking the model through the task one step at a time, you can ask for the tool up front:
Write a PowerShell script that recursively scans this repository for all .cs files,checks whether each file starts with the required copyright header, adds it if missing,and prints a summary of changed files.Requirements:- Do not modify files in bin or obj folders.- Use UTF-8.- Support a -WhatIf mode.- Make the script safe to re-run.
That prompt changes the entire workflow. You are no longer asking the model to do a one-time cleanup. You are asking it to create a reusable piece of engineering infrastructure. Once you have the script, you can inspect it, test it, commit it, share it with your team, and run it whenever you need. Or even create a AI Skill that uses it.
That is a much better use of your AI budget. It also creates something that survives beyond the chat session.
Example: Use AI To Generate A Repeatable PowerShell Script
Let’s say you need to add a standard copyright header to all C# files in a repository. Instead of repeatedly asking the AI to inspect and update files, ask it to generate a script like this:
<#.SYNOPSISAdds a standard copyright header to C# files that do not already have it..DESCRIPTIONRecursively scans the repository for .cs files, excluding bin and obj folders.The script is safe to re-run because it checks for the header before modifying files..PARAMETER PathThe root path to scan..PARAMETER WhatIfShows which files would be changed without modifying them.#>param( [string]$Path = ".", [switch]$WhatIf)$Header = @"// Copyright (c) Your Company.// Licensed under the MIT License."@$changedFiles = @()Get-ChildItem -Path $Path -Recurse -Filter "*.cs" | Where-Object { $_.FullName -notmatch "\\bin\\" -and $_.FullName -notmatch "\\obj\\" } | ForEach-Object { $filePath = $_.FullName $content = Get-Content -Path $filePath -Raw if (-not $content.StartsWith($Header)) { $newContent = $Header + [Environment]::NewLine + [Environment]::NewLine + $content if ($WhatIf) { Write-Host "Would update: $filePath" } else { Set-Content -Path $filePath -Value $newContent -Encoding UTF8 $changedFiles += $filePath } } }Write-Host ""Write-Host "Files changed: $($changedFiles.Count)"if ($changedFiles.Count -gt 0) { $changedFiles | ForEach-Object { Write-Host " - $_" }}
This script is not remarkable because it is complex. It is valuable because it is repeatable. It checks before modifying files, excludes common build folders, supports a -WhatIf mode, and reports what changed. Most importantly, it does not require another AI request every time you need to run the same process.
You generate it once. You review it. You test it. Then you can reuse it whenever needed.
Why This Saves More Than Money
The cost argument is easy to understand. If you ask a premium AI model to repeatedly scan, update, and verify a repository, you are spending AI capacity on work that a simple script could perform locally. Over time, that can mean fewer premium requests, fewer AI credits consumed, and fewer waits for model responses.
But the bigger benefit is trust. A script can be reviewed in a pull request. It can be committed to source control. It can be run in dry-run mode before it touches anything. It can be tested against a sample folder. It can be added to CI. It can be improved by the team over time.
A chat response, by contrast, is often temporary. It might be useful, but it is harder to audit. If an AI assistant says, “I checked all the files and everything looks good,” that might be true. It might also be a very confident hallucination wearing a tiny hard hat.
A script gives you inspectable, deterministic logic. You can see exactly which folders it scans, which files it excludes, what conditions it checks, how it writes files, and what it reports. That moves the work from fuzzy AI behavior into normal engineering practice, and normal engineering practice is where we know how to manage risk.
Use AI For Judgment, Not Button Clicking
The most useful dividing line is this: AI should help with judgment, while scripts should handle repetition. Ask AI to help you decide what kind of automation is appropriate, what edge cases matter, which scripting language fits the environment, how to make the script idempotent, and how to design useful output. Those are judgment-heavy questions.
Once the rules are clear, let a script execute them. Which files match this pattern? Which files are missing a property? Which files need to be updated? How many changes were made? Did every file pass validation? Those are deterministic questions, and deterministic questions are a natural fit for code.
This does not mean using less AI. It means using AI at the right level. You are not removing the model from the workflow. You are moving it away from repetitive execution and toward higher-value work.
Bash, PowerShell, Python: Pick The Right Hammer
The scripting language matters, but not as much as the pattern. Bash is usually a good fit for Unix-style file operations, container workflows, CI/CD automation, and simple text processing. PowerShell is often the better choice for Windows environments, Microsoft 365 tasks, and .NET repositories. Python shines when the task involves more logic, parsing, reporting, API calls, or cross-platform behavior.
Here is a practical rule of thumb:
| Task | Good Script Choice |
|---|---|
| Rename files in a Linux container | Bash |
| Update .NET project files on Windows | PowerShell |
| Parse JSON, CSV, or YAML | Python |
| Parse proprietary file format | Python |
| Generate reports | Python |
| Automate Azure or Microsoft 365 tasks | Bash or PowerShell |
| Run CI helper tasks | Bash or PowerShell |
| Validate repository conventions | Python or PowerShell |
| Call APIs and transform responses | Python |
| Glue together CLI tools | Bash |
| Manage structured Windows objects | PowerShell |
The goal is not to win a scripting-language debate. Those debates have consumed enough oxygen for several generations of developers. The goal is to create a reliable tool that your team can understand, review, and run again.
A Reusable Prompt For Generating Tools
Once you start thinking this way, the prompt pattern becomes reusable. Instead of asking the model to solve a single instance of the problem, frame the request around deterministic behavior:
Create a script that performs the following task deterministically.Task:[Describe the repetitive task]Environment:[Windows / macOS / Linux / CI pipeline / local dev machine]Language:[Bash / PowerShell / Python]Requirements:- Safe to re-run- Dry-run mode- Clear console output- Error handling- Exclude generated folders- Do not delete files unless explicitly approved- Print a summary at the endAlso include:- Usage examples- Assumptions- Edge cases- Unit Tests
This prompt does something important. It tells the model you do not want a one-time answer. You want a tool you can understand. That tends to push the output toward better engineering behavior: inputs, outputs, assumptions, failure modes, safety checks, and repeatability.
That is the kind of AI output that can become part of a repository instead of disappearing into chat history.
Add Scripts To Your AI Model Ladder
A lot of developers are starting to think in terms of a model ladder. Not every task needs the biggest or most expensive model. Some tasks need a local model for quick formatting or summarization. Some need a smaller coding model inside the IDE. Some need a frontier model for architecture, planning, complex debugging, or high-risk reasoning.
Scripts deserve a place on that ladder too. In fact, for repeatable work, they belong at the bottom of it:

Deterministic scripts Repeatable work, scanning, formatting, reports, migrationsLocal model Quick summaries, formatting, boilerplate, experimentationSmall Copilot model IDE-connected simple coding tasksMid-tier Copilot model Day-to-day feature implementation and testsLarge frontier Copilot model Architecture, planning, complex debugging, high-risk reasoning
The mistake is assuming every developer task should climb the ladder. Many tasks should move down the ladder. If the work is predictable, encode it. If the work is repetitive, automate it. If the work requires judgment, ask the model.
That is a healthier way to use AI, and will prevent you from burning extra premium requests or AI credits unnecessarily.
Deterministic Does Not Automatically Mean Safe
There is one important caveat. Scripts can do damage too. A bad script is just a hallucination with file-system permissions.
So treat AI-generated scripts like any other code. Read them before running them. Run them on a small sample first. Use source control so you can revert changes. Prefer dry-run modes. Avoid destructive operations by default. Do not pipe unknown scripts directly into your shell. Be especially careful with credentials, production data, and cloud resources.
This matters most when generating scripts that delete files, modify infrastructure, change permissions, update production data, rotate secrets, run cloud CLI commands, or rewrite large parts of a repository. The goal is not blind automation. The goal is reviewable automation, which is a very different thing.
Common Mistakes To Avoid
The first mistake is forgetting dry-run mode. Any script that changes files should have a way to show what it would do before it does it. In PowerShell, that may be -WhatIf. In Python, it may be --dry-run. In Bash, it may be a flag or environment variable. The name matters less than the behavior: preview first, change second.
The second mistake is forgetting generated folders. Most repository scripts should avoid folders like bin, obj, node_modules, .git, .vs, dist, build, and coverage by default. Generated folders are where automation goes to make a mess and then act surprised.
The third mistake is not printing a useful summary. A script that silently modifies 200 files is not helpful. Good scripts report what happened: files scanned, files changed, files skipped, errors found, and final status. If the script is meant for CI, it should also have sensible exit code behavior.
The fourth mistake is not making the script safe to re-run. A good automation script should usually be idempotent, meaning that running it twice should not create duplicate or incorrect changes. If a script adds a copyright header, it should first check whether the header already exists. Otherwise, every run adds another header. At that point, you have not created compliance. You have created legal lasagna.
The fifth mistake is running the script without reading it. This one sounds obvious, but it is the one people skip when they are moving quickly. AI can help generate code quickly, but it does not remove your responsibility to review it.
Where This Pattern Works Well
Once you see this pattern, you start seeing it everywhere. It works well for adding or validating file headers, updating project files, renaming files based on conventions, validating JSON or YAML, finding missing metadata, generating markdown reports, checking repository conventions, updating package references, running migration checks, creating release notes from structured data, converting CSV files, auditing configuration files, checking links in documentation, finding TODO comments, and enforcing naming conventions.
The common thread is repetition. If the task follows a rule, do not keep asking the model to repeat the rule. Ask the model to encode the rule. Then run the code.
What This Means For Developer Teams
This is not just an individual productivity trick. It has team implications.
A one-off prompt helps one developer once. A reusable script helps the whole team repeatedly. That changes the value of the AI interaction. Instead of spending AI capacity on private, temporary answers, teams can use AI to create shared assets: repository tools, validation scripts, migration helpers, CI checks, documentation generators, release utilities, and project cleanup tools.
Those assets can live in the repo. They can be reviewed in pull requests. They can be improved over time. They can outlive the original chat session. That is how AI becomes part of the engineering system instead of just another window on your desktop.
Final Thoughts
The point of AI-assisted development is not to replace engineering discipline. It is to amplify it.
The best use of AI is not always asking it to do the task. Sometimes the best use of AI is asking it to help you build the tool that does the task. That gives you something durable, deterministic, reviewable, and repeatable. It also saves your strongest AI tools for the work where they matter most: architecture, planning, debugging, tradeoff analysis, and hard reasoning.
So the next time you are about to ask an AI assistant to scan, update, validate, and repeat something across your repository, pause for a second and ask a better question: can this become a script?
If the answer is yes, that may be the cheapest AI request you make all week.
Key Takeaways
- Do not use AI as an expensive file scanner.
- Use AI to generate repeatable tools.
- Let deterministic scripts handle repeatable execution.
- Review AI-generated scripts like any other code.
- Add dry-run modes, clear output, and safety checks.
- Save your strongest AI models for reasoning-heavy work.
- Share reusable scripts with your team.
We have always automated the boring parts. AI just makes it faster to build the automation.
Have you started turning repeatable AI prompts into reusable scripts? What worked well? What went sideways? Share your experience in the comments.