AgentStack
SKILL verified Apache-2.0 Self-run

Agent Work Artifacts Layout

skill-chen3feng-agent-skills-agent-work-artifacts-layout · by chen3feng

Where to put transient files, one-off scripts, audit reports and PR bodies the agent creates while working.

No reviews yet
0 installs
10 views
0.0% view→install

Install

$ agentstack add skill-chen3feng-agent-skills-agent-work-artifacts-layout

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Agent Work Artifacts Layout? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Agent work artifacts: where do they go?

When to use

Any task where the agent produces files that are not the user's intended deliverable: PR body drafts for gh pr create --body-file, throwaway repro_*.py / check_*.sh scripts, audit reports, analysis dumps, temporary fixtures. Without a convention these end up either polluting the working tree (triggering "do I need to delete this?" round-trips) or getting lost across sessions even when they had reuse value.

Problem

Three recurring failure modes:

  1. PR body files left in the repo root (e.g. pr_body.md),

forcing the user to confirm deletion after every PR.

  1. One-off scripts committed to random places — sometimes in

the repo root, sometimes nowhere — making future contributors unsure whether they are project tooling or dead weight.

  1. Fixed temp paths like /tmp/pr_body.md that collide between

parallel agent sessions.

Solution

Route every artifact through this four-way decision:

1. Single-use (PR body, gh intermediate, shell pipe)?
   → system temp via  mktemp -t .XXXXXX.
     (POSIX: $TMPDIR or /tmp; Windows: %TEMP%)

2. Repo-scoped helper, human-authored, part of project lifecycle?
   → scripts/  (or  tools/  if the repo already uses that)
     with argparse CLI, docstring, usage example.

3. Repo-scoped helper, agent-authored, reviewed and reusable?
   → .agent/tools/  (tracked subdirectory of the agent working area,
     see the four-cell layout below)

4. General-purpose, useful across projects?
   → offer to publish as a GitHub Gist.

5. Agent working notes / drafts / caches NOT meant for sharing?
   → .agent/scratchpad/ | .agent/artifacts/ | .agent/context/
     (gitignored, local-only)

If none apply, delete the file rather than leaving it ambiguous.

.agent/ four-cell layout

.agent/ is not a single bucket — split it by lifetime and tracking intent:

| Subdirectory | Purpose | Tracked? | | --- | --- | --- | | .agent/scratchpad/ | Free-form notes, pseudo-code, drafts. | No | | .agent/artifacts/ | Generated deliverables (exported docs, images, one-off reports). | No | | .agent/tools/ | Reviewed agent-authored helpers for this repo. | Yes | | .agent/context/ | Project index / knowledge-base caches / embeddings. | No |

The tracked subset is surfaced via a whitelist-style .gitignore (see Example). Keeping .agent/tools/ in Git lets genuinely reusable agent-authored helpers survive across sessions without mixing with the project's human-authored scripts/.

scripts/ vs .agent/tools/

They coexist, with clear provenance separation:

  • scripts/ (if/when the repo has one) = human-authored core

tooling that's part of the project's normal lifecycle (release, lint, bootstrap).

  • .agent/tools/ = helpers written by an agent, reviewed, and

kept because they proved useful. Provenance is tagged at the directory level — no silent promotion to scripts/, only via a dedicated "graduation" PR.

Example

Right way — PR body in system temp

body=$(mktemp -t pr_body.XXXXXX.md)
# write body via the editor tool, targeting "$body"
gh pr create --repo / --base  --head  \
  --title '' --body-file "$body"

Wrong way — PR body in repo root

# Leaves pr_body.md in the working tree after the PR is filed.
# The user then has to approve its deletion in a follow-up turn.
vi pr_body.md
gh pr create --body-file pr_body.md

Right way — commit message via repo-local scratchpad

In an agent terminal, commit flows that chain mktemp + git commit

  • rm often trigger human-confirmation prompts on every commit.

.agent/scratchpad/ sidesteps this by removing both mktemp and the trailing rm:

MSG=.agent/scratchpad/commitmsg.$$.txt
printf '%s\n' 'Subject line' '' 'Body paragraph.' > "$MSG"
git commit -F "$MSG"
# .agent/scratchpad/ is gitignored; sweep occasionally.

This applies to commit messages, not PR bodies — PR bodies should still use system temp (see previous example) because they are one-shot and benefit from OS-level cleanup.

See [shell-heredoc-and-multiline-strings](../shell-heredoc-and-multiline-strings/SKILL.md) for when to choose each temp location.

Right way — repo-scoped helper that others might reuse

/scripts/check_doc_consistency.py     # committed, with argparse + docstring

Right way — agent working area with whitelist gitignore

/.agent/
  README.md            # tracked: layout convention for contributors
  scratchpad/          # ignored: notes, drafts
  artifacts/           # ignored: generated deliverables
  context/             # ignored: indexes, caches
  tools/
    README.md          # tracked: intake standard
    .py        # tracked: reviewed agent-authored helpers
    .sh        # tracked

Corresponding .gitignore block (whitelist pattern — blanket ignore first, then un-ignore each tracked path):

/.agent/*
!/.agent/README.md
!/.agent/tools/
/.agent/tools/*
!/.agent/tools/*.py
!/.agent/tools/*.sh
!/.agent/tools/README.md

Verify with git check-ignore -v after editing — it's the only way to be sure reopens line up with blanket ignores.

Intake standard for .agent/tools/

Because helpers here are tracked, they need a quality bar. Every committed script should have:

  1. Provenance header naming the agent session.
  2. argparse CLI with --help.
  3. Dry-run default; --apply / --write to mutate.
  4. Module-level docstring with a real usage example.
  5. Stdlib-only (or deps the project already has).
  6. UTF-8 safe (encoding="utf-8" on file I/O).
  7. Introduced in its own dedicated PR, not smuggled in.

Document this in a .agent/tools/README.md at repo setup time.

Pitfalls

  • The convention is inert without an actual .gitignore. Writing

this skill, or a .agent/README.md, or just telling the agent to "put drafts in .agent/scratchpad/" does not make those files ignored. Without a committed .gitignore entry they show up as ?? in git status, and a single git add -A (easy to type when rushing a commit) sweeps them into the tree. Verify on day one:

``bash git check-ignore -v .agent/scratchpad/anyfile.txt # expect: .gitignore::.agent/ .agent/scratchpad/anyfile.txt ``

If that command prints nothing, the convention is a lie and the next git add -A will betray it. This skill's own repo shipped without a .gitignore for its first nine PRs — nobody got bitten only because every commit used explicit git add . Don't rely on that.

  • .agent/ is convention, not project API. A tracked

.agent/README.md explaining the layout is fine (similar in spirit to .github/'s own README), but nothing in the build, tests, or CI should read from .agent/. If a file needs to run on fresh clones or other contributors' machines, it doesn't belong here — promote it to scripts/ with a dedicated PR.

  • Whitelist gitignore is order-sensitive. The blanket

/.agent/* must come before the !-prefixed reopens, otherwise the reopens have no effect. Always verify with git check-ignore -v for both a tracked path and an ignored path before committing.

  • Use .agent/scratchpad/ for commit-message drafts, not PR bodies.

Commit messages are produced many times per session and benefit from a fixed local path (no mktemp, no rm, fewer agent-terminal confirmation prompts). PR bodies are one-shot, often contain the final version of release notes, and should stay in system temp so the OS cleans them up — a lingering draft under .agent/scratchpad/ invites confusion about which version made it to GitHub.

  • **Do not rely on .agent/scratchpad/, /artifacts/, or

/context/ for anything needed on another machine** — they are gitignored. Only .agent/tools/ survives cloning.

  • Windows: /tmp and mktemp are not portable. Prefer

tempfile.gettempdir() from Python when the caller might be on Windows.

  • Do not confuse scripts/ with contrib/. In PostgreSQL /

Git, contrib/ means "distributed alongside core but not part of it". Unless the target repo already uses that convention, stick with whichever of scripts/ or tools/ the repo already has.

  • **Do not silently "graduate" .agent/tools/ scripts to

scripts/.** Promotion is a conscious decision that warrants a PR of its own (with a new provenance line: "originally authored by agent, audited and graduated"). Silent moves destroy the provenance signal the .agent/tools/ location exists to preserve.

  • Industry precedent: CPython, Django, Kubernetes, Rust, LLVM

all ship a top-level scripts/ or tools/. No mainstream project formalises an "AI agent working area" yet; .agent/ is the convention this skill proposes, sitting alongside existing local caches like .pytest_cache/, .mypy_cache/, .idea/.

See also

  • [github-pr-via-gh-cli](../github-pr-via-gh-cli/SKILL.md)
  • [shell-heredoc-and-multiline-strings](../shell-heredoc-and-multiline-strings/SKILL.md)
  • [workspace-path-constraints](../workspace-path-constraints/SKILL.md)

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.