AI Engineering · 2026-09-25 · 8 min read
The Tool Built to Publish Had No Rule About What Never Gets Published
An open source Claude Code skill turned your repo into a public launch video, with no rule keeping secrets out. Here is the fix we got merged, and the lesson.

An AI agent that reads your whole repository and produces something shareable turns every file it reads into potential output. If nobody writes down what must never leave the machine, secrets sit on the default path, one step from a public post. Keeping secrets out of AI agent output takes two things: an exclusion list at read time, and a stated rule for everything the list misses.
We learned that the concrete way, by reviewing an open source Claude Code skill and sending the fix upstream. This note covers the gap, the fix that got merged, what the review taught us about contributing to AI tooling, and a short checklist for anyone building or adopting an agent that turns internal material into public output.
Why does an AI tool that publishes need a rule about what never gets published?
Most agent tooling was designed around a private loop. The agent reads your code, proposes a change, you review it, and it stays in your repo. Mistakes are contained because the output never leaves the building.
A newer class of tools breaks that loop on purpose. They read internal material and emit something meant for strangers: a launch video, a changelog post, a demo, a social caption. That is useful. It also means the agent's reading list and your public surface are now connected by a straight line.
In a private loop, reading a .env file by accident is usually harmless. In a publishing loop, it is a leak waiting for a render.
What /brag does, and where the gap was
/brag is an open source Claude Code skill that turns a project into a short launch video, complete with music, motion, and share copy. You run it inside a project, and it works through a few steps: inspect the project, plan the video, compose it, render it, and hand you a folder with the video and ready-to-post copy.
The inspection step is the interesting one. It tells the agent to read the landing page, the stylesheet, the README, the package manifest, and then go further: route files, feature components, state stores, and example or demo folders, because the product in use makes better footage than the product's marketing page. The agent lifts that material, often verbatim, into the plan and onto the screen. The skill's own delivery notes describe the result as postable as-is to X, LinkedIn, or Discord.
The skill also had a "don't read" list. It covered build artifacts, lock files, test files, and the .git directory. Those exclusions are about noise, not safety. Nothing on the list covered environment files, credentials, or key material.
So the path looked like this: a secret sitting in a local config file, read during inspection as context, carried into a plan, dropped into a composition as "real UI data," rendered into a frame, and posted. Each step is reasonable on its own. Nobody would intend the chain. That is exactly why it needs a rule.
The fix: exclusions plus the rule they serve
The change we submitted did two things.
First, it extended the skip list. Environment and secret files (.env, .env.*), credential and key material (private keys, service-account JSON, anything under a secrets/ or credentials/ directory), local config that commonly holds tokens, and anything the project's .gitignore excludes for those reasons.
Second, and more important, it stated the rule behind the list. Everything read during inspection can end up on screen in a public video. So nothing read in that step carries secrets, API keys, tokens, internal hostnames or URLs, real customer or user names, email addresses, or personal data into the plan, the composition brief, the composition, the rendered video, or the share copy. Where the real product UI contains that kind of data, the agent substitutes plausible fictional stand-ins and says so in the plan.
Why both? Because a list goes stale. A new framework invents a new config file name, a team keeps credentials somewhere odd, and the list misses it. Worse, some of the most sensitive material is not in a secrets file at all. A customer's name in a seed fixture, an internal hostname in a route file, a real email in a demo folder. No file-pattern list catches those. A stated rule does, because the agent can reason about the category instead of matching a filename.
Substitution matters too. A blurred customer name still tells a viewer there is a real customer there, and blurs fail. A fictional stand-in, flagged in the plan so the human knows it was swapped, keeps the footage honest and the data private.
The change was pull request #24. It was docs only, one file. It merged with no changes requested and shipped in brag v0.3.0.
What review taught us about contributing to AI tooling
The secrets fix was the one with real consequence, but it was not a lone idea. It came out of a full security and usability review of the skill: the skill definition, every reference document, the bundled script, the plugin manifests, the published site, and the commit history. Six issues came out of that pass. Two were fixed upstream by another contributor, independently, before we submitted anything. The other four went in as separate pull requests. Here is what the review of those four taught us.
Start from a review, not a feature idea. A feature pitch asks the maintainer to share your vision. A finding asks them to look at a gap in what they already built. The second is a much easier yes.
One idea per pull request. Each change was small and single-purpose, so each could be judged on its own merits. The merged one went through untouched. A bundle of four ideas would have been sent back to be split, or merged at the speed of its most debatable part.
Preventative hardening without an observed failure does not survive review, and it should not. One of our pull requests pinned a tool version for every run. The maintainer asked a fair question: had we actually hit the problem, or was it preventative? It was preventative. They also pointed out that version resolution belongs in the underlying renderer, where it helps everyone, not as bookkeeping inside a deliberately thin skill. Both points were right, so we said so and closed it. Withdrawing cleanly is part of contributing well. Defending a guess costs the maintainer more time than the patch is worth.
Take the better wording. On the two changes still under review as of this writing, the maintainer rewrote parts of our text. One note asked us to drop specific CLI command names so the docs would not go stale as the tool evolves. That was better than what we wrote, and we used it. Arguing for our own phrasing would have been slower and worse.
Respect the architecture you are contributing to. This skill is kept thin on purpose, so it inherits improvements from the renderer underneath it for free. Changes that move that boundary, or create a second source of truth, get declined. Knowing that up front would have saved us one pull request.
A checklist for agent tools that turn internal material into public output
If you are building a tool like this, or adopting one on a private codebase, here is what we would check.
- Exclude secrets at read time, not just at write time. Output filters are a last line of defense. If the agent never reads the
.envfile, it cannot quote it. - State the rule, not only the list. Write down the categories that never leave: secrets, tokens, internal hostnames, real customer names, personal data. The rule covers what the list misses.
- Substitute, do not blur. Replace real data with plausible fictional stand-ins, and have the agent say what it swapped so a human can check.
- Keep the whole run local until a human says ship. Render and review on your machine before anything uploads. A tool that can publish should never publish by default.
- Review the first output like it is a pull request. Watch the video, read the share copy, look at every frame with text in it. The first run on a new codebase is where surprises live.
- Treat demo and seed folders as sensitive. Teams often test with real data and forget it is there. Those folders are exactly what a publishing agent is told to read.
None of this is exotic. It is the same discipline you would apply to a new employee writing your launch post: tell them what is off limits, and look before it goes out.
FAQ
Is it safe to run a repo-reading agent skill on a private codebase? It can be, if the skill excludes secret files at read time, states what must never appear in output, and keeps the run local until you review it. Read the skill's instructions before you run it. With Claude Code skills, those instructions are plain text files you can open.
What files should an AI agent never read? Environment files, credential and key material, service-account JSON, anything in a secrets or credentials directory, and local config that holds tokens. For publishing tools, also be careful with seed data and demo folders that may contain real customer information.
How do you get a first pull request merged on an AI tooling project? Start with a careful review of what exists, submit one small change per pull request, back each one with an observed problem, and take the maintainer's edits gracefully. Small, specific, and grounded beats big and clever.
Where this leaves us
Agent tools that publish are going to multiply, because they are genuinely useful. The boundary on what leaves the machine has to be designed in, not bolted on after the first leak. We keep a running record of the fixes we send upstream to the tools we build with on our open source work page.
If your team is adopting agent tooling on a private codebase and wants the boundaries set up right from day one, start a project with us. And if you are the person installing skills and want to get comfortable reading what they actually do, our learn Claude one on one sessions are built for exactly that.
Liked this?
Want this built for your team, or want to learn it yourself? Either way, start here.
Next read →
AI for Solo Practitioners: The Setup Before the Tools