Skip to content
Development
Skill

/artifact-path

Internal skill for commands. Resolve a unique, task-scoped, collision-safe path for an artifact written under .lets/ (plans, reviews, session snapshots, hand-off briefs, per-run agent report directories). Do not trigger on user conversation - only when a command is about to

From plugin
lets-workflow
1725 skills15 agents26 commands

Claude Code

$ npx -y skills add restarter/lets-workflow --skill artifact-path --agent claude-code

SKILL.md

artifact-path.SKILL.md
name: artifact-path
description: Internal skill for commands. Resolve a unique, task-scoped, collision-safe path for an artifact written under .lets/ (plans, reviews, session snapshots, hand-off briefs, per-run agent report directories). Do not trigger on user conversation - only when a command is about to write an artifact.
user-invocable: false

Artifact Path

`.lets/` is ONE directory shared by every worktree of the repo (whole-dir symlink). Two sessions writing the same artifact kind on the same day used to overwrite each other (lets-05c4s - a plan review was lost). This skill is the single place that names an artifact and guarantees the path is free.

**Contract:** args `kind=<kind> ext=<md|json|dir> [task=<task-id>]`. Output: ONE echoed line `ARTIFACT_FILE=<absolute path>`. The caller writes to that path VERBATIM - never recomputes the stamp, never strips the `-vN` suffix, never writes anywhere else. `ext=dir` CREATES the directory (the `mkdir` is the claim) and echoes its path; a file kind only names a free path.

Name shape

`{YYYY-MM-DD}-{HHMM}-{ID}-{KIND}[-vN].{EXT}` under the kind's directory:

| kind | directory | |------|-----------| | `plan` | `.lets/plans/` | | `idea` | `.lets/plans/` | | `review-local`, `review-branch`, `review-pr-<n>`, `review-plan` | `.lets/reviews/` | | `snapshot` | `.lets/sessions/` | | `handoff` | `.lets/handoffs/` | | `reports-<command>` (with `ext=dir`) | `.lets/reports/` - one directory per dispatching run, filled by the `agent-report` skill |

`ID` is the task id when one is active (MANDATORY whenever a task exists - same rule as the branch named by the active tracker convention). With no task: `{branch-slug}-{6hex}`, 6hex = first 6 chars of `$CLAUDE_CODE_SESSION_ID`, so two taskless sessions on `main` still get distinct names. `-vN` (v2, v3, ...) is appended whenever the path already exists - for task and taskless alike.

Step 1: Resolve the task id

If the caller passed `task=`, use it. Otherwise invoke `Skill(skill: "lets:detect-task", args: "fallback=no")` and use its result (may be empty). `fallback=no` is mandatory: the searched fallback asks a question, and a taskless snapshot on `/lets:end` must stay silent.

Step 2: Compute the path

LETS_PROJECT_ROOT=$(git rev-parse --show-toplevel)
KIND="{kind}"; EXT="{ext}"; TASK_ID="{task-id or empty}"
case "$KIND" in
  plan|idea) DIR=plans ;;
  review-*) DIR=reviews ;;
  snapshot*) DIR=sessions ;;
  handoff) DIR=handoffs ;;
  reports-*) DIR=reports ;;
  *) echo "artifact-path: unknown kind '$KIND'"; exit 1 ;;
esac
mkdir -p "$LETS_PROJECT_ROOT/.lets/$DIR"
STAMP=$(date +%Y-%m-%d-%H%M)
if [ -n "$TASK_ID" ]; then
  ID="$TASK_ID"
else
  HEX=$(printf '%s' "${CLAUDE_CODE_SESSION_ID:-$$}" | cut -c1-6)   # session-id prefix; PID outside Claude Code
  ID="$(git branch --show-current | tr '/' '-')-${HEX}"
fi
BASE="$LETS_PROJECT_ROOT/.lets/$DIR/${STAMP}-${ID}-${KIND}"
N=2
if [ "$EXT" = dir ]; then
  # mkdir without -p is atomic: two sessions in the same minute get two directories, never one shared
  ARTIFACT_FILE="$BASE"
  until mkdir "$ARTIFACT_FILE" 2>/dev/null; do
    [ -e "$ARTIFACT_FILE" ] || { echo "artifact-path: cannot create $ARTIFACT_FILE"; exit 1; }
    ARTIFACT_FILE="${BASE}-v${N}"; N=$((N+1))
  done
else
  ARTIFACT_FILE="${BASE}.${EXT}"
  while [ -e "$ARTIFACT_FILE" ]; do ARTIFACT_FILE="${BASE}-v${N}.${EXT}"; N=$((N+1)); done
fi
echo "ARTIFACT_FILE=$ARTIFACT_FILE"

Return

Return the echoed `ARTIFACT_FILE` to the caller. If the echo is missing or `exit 1` fired, the caller MUST NOT write anything - surface the error.

Rules

  • NEVER overwrite: the loop is the guard; the caller never "fixes" a path by hand.
  • `ext=dir`: the directory exists when the echo returns; the caller never creates or renames it.
  • NEVER compute a second `date` in the caller - the stamp is captured here once.
  • Task id in the name is mandatory when a task is active.
  • No tracker calls here beyond `detect-task`.
  • Go-owned state files are NOT artifacts and never come through here: `.lets/sessions/.task-*` (`lets worktree task-state`), `.lets/sessions/peers/last/*.last` (`lets peers who` / `orchestrator`; a legacy `.lets/sessions/peers/*.role` is never read or written), `.lets/cache/released-*` (`lets worktree release`), and `.lets/cache/ask-ro-mcp-empty.json` - their owner writes them.
Read more
@restarter
Ships withlets-workflow

A development workflow plugin for Claude Code Stop babysitting your AI. Start shipping with it.

1725 skills15 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
17
Star history of restarter/lets-workflow on GitHub, a chart by star-history.com

Other skills on lets-workflow.

goal-test

goal-test

Local sandbox for experimenting with Claude Code's /goal command (stop-hook condition + LLM-evaluator driving autonomous work…

loop-bb-pr

loop-bb-pr

Compose a /loop that monitors a Bitbucket PR for activity (new comments, review state changes, merge, decline) via the bb-api…

loop-gh-pr

loop-gh-pr

Compose a /loop that watches all open GitHub PRs for activity (new PRs, new commits, new comments) and auto-prepares a READ-ONLY…

loop-test

loop-test

Local sandbox for experimenting with Claude Code's /loop command (interval + dynamic/self-paced scheduling) applied to LETS…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills12d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc13d293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react3d252k
@facebook@facebookInstall Skill

Questions about artifact-path.

Which coding agents can use artifact-path?
artifact-path installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.