# Stash Maker's Guide

This guide walks through building a stash from scratch and sharing it so others
can install it with `akm add`.

## Step 1: Organize Your Assets

You can organize a stash however you like. akm classifies assets by
**file extension and content**, so directory names are not required to
follow any particular pattern.

That said, using these preferred directory names is an **opt-in convention**
that increases classification confidence during indexing:

```text
my-stash/
  scripts/        # .sh, .ts, .js, .py, .rb, .go, etc.
  skills/         # Directories containing SKILL.md
  commands/       # .md prompt templates (agent frontmatter, $ARGUMENTS)
  agents/         # .md files with model, tools, or toolPolicy frontmatter
  knowledge/      # .md reference documents
  env/            # .env environment files (mode-0600)
  workflows/      # .md step-by-step workflow documents
  wikis/          # Multi-wiki knowledge bases (see docs/wikis.md)
  lessons/        # .md distilled feedback lessons
  memories/       # .md recalled context fragments
```

These directories are hints, not requirements. A `.sh` file is a script
whether it lives in `scripts/`, `deploy/`, or at the stash root. A `.md` file
with `model` in its frontmatter is an agent definition no matter where you
put it. Nesting is fully supported — `scripts/azure/deploy/run.sh` works
just as well as `scripts/run.sh`. Organize your stash in whatever way makes
sense for your project.

## Step 2: Add Assets

### Scripts

Drop executable scripts into `scripts/`. Supported extensions: `.sh`, `.ts`,
`.js`, `.ps1`, `.cmd`, `.bat`, `.py`, `.rb`, `.go`, `.pl`, `.php`, `.lua`,
and more.

```sh
# scripts/deploy.sh
#!/usr/bin/env bash
# Deploy the application to production.
# @param release_tag - Release tag to deploy.
# @run bash "$0" "$@"
set -euo pipefail
echo "Deploying $1..."
```

When an agent runs `akm show script:deploy.sh`, it gets back a `run` command
it can execute directly. Interpreters are auto-detected for a wide range of
extensions (`.sh`, `.ts`, `.js`, `.py`, `.rb`, `.go`, `.pl`, `.php`, `.lua`,
`.r`, `.swift`, `.kt`/`.kts`, `.ps1`, `.cmd`/`.bat`).

If your script has dependencies, add a `package.json` in the script's
directory or a parent. When akm detects a `package.json`, it sets the
working directory to that package root.

### Skills

A skill is a directory containing a `SKILL.md` file. The directory name
becomes the skill name.

```text
skills/
  code-review/
    SKILL.md
```

Write `SKILL.md` as instructions the agent should follow:

```markdown
# Code Review

Review the changed files for bugs, security issues, and style violations.

## Steps

1. Run `git diff --cached` to see staged changes
2. Check each file for common issues
3. Report findings with file paths and line numbers
```

### Commands

Markdown files whose body is a prompt template. Commands follow the
[OpenCode convention](https://opencode.ai/docs/commands/): frontmatter
supports `description`, `model`, and `agent` (dispatch target). The body
can use `$ARGUMENTS` for the full argument string, or `$1`/`$2`/`$3` for
positional arguments:

```markdown
---
description: "Run the release workflow"
model: "claude-sonnet-4-20250514"
agent: build
---
Tag the current commit with the next semantic version, push the tag, and
wait for CI to complete. Target environment: $ARGUMENTS.
```

Commands are automatically detected by content signals -- `agent`
frontmatter or `$ARGUMENTS`/`$1`-`$3` placeholders -- even outside the
`commands/` directory.

### Agents

Markdown files in `agents/`. Frontmatter supports `description`, `model`,
and `tools` fields:

```markdown
---
description: "TypeScript architecture advisor"
model: "claude-sonnet-4-20250514"
tools: ["Read", "Grep", "Glob"]
---
You are a senior TypeScript architect. When reviewing code, focus on
type safety, module boundaries, and dependency management.
```

The `model` field is a hint -- the consuming agent uses it to pick a
compatible model. The `tools` field suggests which tools the agent needs.

### Knowledge

Markdown files in `knowledge/`. These are reference documents agents can
navigate by section:

```markdown
---
title: "API Reference"
---
# Authentication

Use Bearer tokens in the Authorization header.

# Rate Limits

Default: 100 requests per minute per API key.
```

Agents can request just the table of contents (`toc`) or a specific
section (`section "Rate Limits"`) to avoid loading the entire document:

```sh
akm show knowledge:api-guide toc
akm show knowledge:api-guide section "Rate Limits"
```

### Memories

Markdown files in `memories/`. These are recalled context fragments that
provide situational information the agent should consider:

```markdown
---
description: "Team coding standards for TypeScript projects"
---
- Always use strict mode
- Prefer `const` over `let`
- Use named exports, not default exports
```

The `memories/` directory is primarily used by agent memory systems that
write markdown files. You generally don't create memories by hand — they're
populated by file-based memory agents or tools that emit markdown. You can
also add one directly with `akm remember`. Memories are surfaced alongside
other assets in search results, giving the agent relevant context without
requiring explicit prompts.

## Step 3: Add Metadata

Metadata makes your stash searchable. Prefer metadata that travels with the
asset itself.

### Preferred: inline metadata

For markdown assets, add frontmatter near the content it describes:

```markdown
---
description: "Release workflow for tagged builds"
tags: [release, ci, automation]
params:
  version: "Version to release"
---
```

For scripts, keep metadata in the file header so it stays in sync with the code:

```sh
#!/usr/bin/env bash
# Release the current build to production.
# @param version - Version to release.
# @setup bun install
# @cwd .
```

When someone installs your stash and runs `akm index`, metadata is generated
from frontmatter, code comments, filenames, and `package.json`. This works well
for most stashes and keeps descriptions close to the asset body.

### Legacy: `.stash.json`

`.stash.json` support was removed in v0.8.0. Do not create new stashes with
it. If you are upgrading from v0.7, migrate any existing `.stash.json` sidecars
to inline metadata using the guidance below before indexing.

If you still have `.stash.json`, migrate the fields into the asset whenever
possible:

- Move `description`, `tags`, and `params` into markdown frontmatter.
- Move script execution hints into header comments such as `@run`, `@setup`,
  and `@cwd`.
- Move script parameter docs into `@param` comments.
- Let filenames and nearby `package.json` provide the remaining fallback
  metadata.

Legacy example:

```json
{
  "entries": [
    {
      "name": "deploy",
      "type": "script",
      "description": "Deploy the application to production",
      "tags": ["deploy", "infrastructure", "ci"],
      "searchHints": [
        "deploy the app",
        "push to production",
        "ship a release"
      ],
      "usage": ["Pass a release tag as the first argument"],
      "filename": "deploy.sh",
      "quality": "curated",
      "source": "manual",
      "confidence": 1.0
    }
  ]
}
```

See [technical/filesystem.md](technical/filesystem.md) for the legacy field reference.

## Step 3.5: Orient Readers with `.meta/` (optional)

Add a `.meta/` directory at the stash root to give agents and humans a quick
orientation to the stash *as a whole* — what it's for, where to start, and the
conventions to follow. This is separate from per-asset metadata: `.meta/`
describes the stash, not individual assets.

```text
my-stash/
  .meta/
    index.md          # akm show meta
    about.md          # akm show meta:about
    conventions.md    # akm show meta:conventions
```

`.meta/index.md` is the default doc. A useful starting shape:

```markdown
---
purpose:
  - Release engineering + changelog automation for the CLI
entry_points: [skill:git-release, command:changelog-entry, script:bump-version]
conventions:
  - "Scripts are bun-first; shebang #!/usr/bin/env bun"
maintainer: you <you@example.com>
---
# About this stash

Start with `skill:git-release`. The bump→changelog→tag→push flow lives in
`script:bump-version` then `command:changelog-entry`.
```

Key properties:

- **Not indexed.** `.meta/` is a dot-directory, so the indexer skips it — these
  docs never appear in `akm search` and never compete for ranking. They are
  read directly via `akm show meta[:<name>]` (or `akm show <stash>//meta[:<name>]`
  once installed).
- **Travels with the stash.** It's committed files in your tree, so installers
  get your conventions automatically.
- **Open-ended.** Add any doc by dropping a file — `akm show meta:<name>`
  resolves `.meta/<name>.md` (then an extensionless `.meta/<name>`) with no
  configuration or code changes.

> **npm publishing note:** if you ship via npm with an `akm.include` allowlist
> (see "Sharing on npm" below), add `.meta` to the list — dot-directories are
> otherwise easy to leave out of the published tarball. GitHub tarball installs
> include `.meta/` automatically.

## Step 4: Test Locally

Before sharing, install your stash locally to verify everything works:

```sh
# Install from the local directory
akm add ./my-stash

# Check it appears in the list
akm list

# Search for your assets
akm search "deploy"

# Show an asset to verify the output
akm show script:deploy.sh
```

## Sharing on GitHub

1. Push your stash to a GitHub repository.

2. Add the `akm-stash` topic to your repo so it appears in registry search:

   ```sh
   gh repo edit --add-topic akm-stash
   ```

   Or add it from the repository settings page under "Topics". `akm-cli`
   0.6.0 indexes only the `akm-stash` topic; the pre-0.6.0 `akm-kit` and
   `agentikit` topics are **not** honored as fallbacks. If you are migrating
   a 0.5.x stash, add the new topic (and remove the old ones once your
   audience has moved). See the
   [v0.5 → v0.6 migration guide](migration/v0.5-to-v0.6.md) for the full
   publisher checklist.

3. Others can now install it:

   ```sh
   akm add github:your-username/my-stash
   ```

4. To pin a version, create a GitHub release. When a release exists, `akm add`
   uses the latest release tarball. Otherwise it uses the default branch.

   ```sh
   # Install a specific tag
   akm add github:your-username/my-stash#v1.0.0
   ```

## Sharing on npm

1. Add a `package.json` with `"akm-stash"` in the keywords:

   ```json
   {
     "name": "@your-scope/my-stash",
     "version": "1.0.0",
     "description": "Scripts and skills for deployment workflows",
     "keywords": ["akm-stash"]
   }
   ```

2. If your repo contains files that should not be part of the stash (source
   code, tests, CI config), use `akm.include` to declare which paths
   to ship:

   ```json
   {
     "name": "@your-scope/my-stash",
     "version": "1.0.0",
     "keywords": ["akm-stash"],
     "akm": {
       "include": ["scripts", "skills", "knowledge"]
     }
   }
   ```

   Paths are relative to the `package.json`. Only the listed directories and
   files are copied into the install cache. The `.git` directory is always
   excluded.

3. Publish to npm:

   ```sh
   npm publish --access public
   ```

4. Others can now install it:

   ```sh
   akm add @your-scope/my-stash
   ```

## Submitting to the Registry

The official [akm-registry](https://github.com/itlackey/akm-registry) gets
your stash listed in three ways:

- Publish an npm package with `akm-stash` in `keywords`
- Add the `akm-stash` GitHub topic to your repository
- Open a PR updating `manual-entries.json` for a curated entry or override

Auto-discovered entries are merged into `index.json` on the registry's
build cycle. Curated entries are reviewed before inclusion.

CLI-based submission (`akm` driving the PR) is planned for a future release.

## Sharing on a Network Directory

For teams that want to share assets without publishing to a registry, use
stashes.

1. Place your stash on a shared filesystem (NFS, SMB, cloud-synced folder):

   ```text
   /mnt/shared/team-stash/
     scripts/
     skills/
     commands/
   ```

2. Each team member adds it as a source:

   ```sh
   akm add /mnt/shared/team-stash
   ```

   Or add it directly to `~/.config/akm/config.json`:

   ```json
   {
     "sources": [{ "type": "filesystem", "path": "/mnt/shared/team-stash" }]
   }
   ```

3. Assets from the stash appear in search results immediately --
   no `akm add` needed. To fork an asset into the primary stash, use clone:

   ```sh
   akm clone script:deploy.sh
   ```

   Or clone directly to a project directory with `--dest`:

   ```sh
   akm clone script:deploy.sh --dest ./my-project/.claude
   ```

You can mount multiple directories. They are searched in the order listed,
after the working stash.

## Env Security

> The `vault` asset type was removed in 0.9.0; `env` replaces it. See the
> [0.8 → 0.9 migration guide](migration/v0.8-to-v0.9.md).

If your stash includes env files under `env/`, be aware of how `akm` handles
them during install.

**Dangerous key detection.** `akm add` and `akm lint` scan env files for
environment variable names that can be used to hijack process execution when
the file is loaded via `akm env run`. The flagged names include `LD_PRELOAD`,
`PATH`, `DYLD_INSERT_LIBRARIES`, `NODE_OPTIONS`, and 20 others. When these keys
are found, `akm add` pauses in interactive mode and asks the user to confirm
before continuing. In non-interactive (CI) mode the install fails unless the
user passes `--allow-insecure`. `akm env run` applies the same scan at run time:
a third-party-sourced stash is refused outright; a first-party stash warns and
proceeds.

This is not a ban — it is a speed bump. If your stash legitimately needs one
of these keys (for example, a `PATH` override for a hermetic toolchain), do
the following before publishing:

1. Document the reason clearly in your `README.md`. Explain which key is set,
   why it is needed, and what the value does.
2. Run `akm lint` against your stash locally to see the `dangerous-vault-key`
   findings before your users do:

   ```sh
   akm lint
   ```

3. Consider whether the value can be set by the user after install rather than
   shipped in the env file. Env files that ship without values — just key names
   and comments — do not trigger the audit.

**Key names are metadata, not secrets.** Env key names appear in `akm env list`
and search results by design. Only values are protected. The `--sensitive` flag
on `akm env create` hides a file from `env list` but does not prevent key names
from appearing in search results or agent context when the file is shown
directly.

## Stash Structure Tips

- **Keep it focused.** A stash with 5 great scripts is more useful than one with
  50 mediocre ones.

- **Write good descriptions.** The `description` field (preferably in
  frontmatter, otherwise in script comments or `package.json`) is the primary
  signal for search ranking.

- **Use frontmatter in markdown assets.** A `description` in frontmatter is
  extracted automatically with high confidence (0.9), making your commands,
  agents, and knowledge documents more discoverable.

- **Use structured header comments for scripts.** `.sh`, `.ts`, `.py`, etc. get
  strong results from good filenames plus leading comments and tags like
  `@param`, `@run`, `@setup`, and `@cwd`.

- **Test the search experience.** After installing your stash, search for it
  using the terms you expect users to try. If results are poor, improve the
  descriptions, tags, and searchHints.

- **Document usage in the asset itself.** For skills, put the instructions in
  `SKILL.md`. For commands, put the workflow in the markdown body. The agent
  reads these directly.

- **Version your stash.** Use npm versions or GitHub releases so users can pin
  to a known-good state with `akm add npm:pkg@1.2.3` or
  `akm add github:owner/repo#v1.2.3`.
