# Custom hashtag command (/ink/hashtag)



***ink*** gives the ability to use the `#` character to define custom hashtag commands (or *tags*).
The developer can manage and add these `#` command interactions as they like, by linking them to custom functions. This is done through the [`HashtagCommands.add`](/jsdoc/pixi-vn-ink/index/namespaces/HashtagCommands/functions/add) function.

<CodeBlockTabs defaultValue="content/ink/hashtag-commands.ts">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="content/ink/hashtag-commands.ts">
      content/ink/hashtag-commands.ts
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="ink/start.ink">
      ink/start.ink
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="content/ink/hashtag-commands.ts">
    ```ts
    import { HashtagCommands } from "@drincs/pixi-vn-ink";
    import zod from "zod";

    HashtagCommands.add(
        async (script, { navigate }) => {
            await navigate({ to: script[1] });
            return true;
        },
        {
            name: "navigate",
            description: `Navigates to a specified route within the game.

    \`\`\`ink
    # navigate <route>
    \`\`\``,
            validation: zod.tuple([zod.literal("navigate"), zod.string()]),
        },
    );
    ```
  </CodeBlockTab>

  <CodeBlockTab value="ink/start.ink">
    ```ink
    === start ===
    # navigate /game
    -> DONE
    ```
  </CodeBlockTab>
</CodeBlockTabs>

The `validation` option determines which hashtag commands this handler applies to. You can use either a regular expression or a [Zod](https://zod.dev) schema.

To use Zod, install it first:

<CodeBlockTabs defaultValue="npm">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="yarn">
      yarn
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="bun">
      bun
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npm install zod
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm add zod
    ```
  </CodeBlockTab>

  <CodeBlockTab value="yarn">
    ```bash
    yarn add zod
    ```
  </CodeBlockTab>

  <CodeBlockTab value="bun">
    ```bash
    bun add zod
    ```
  </CodeBlockTab>
</CodeBlockTabs>

`validation` accepts a `zod.tuple`, i.e. a tuple that validates the array of strings passed to the callback. The most useful sub-schemas are `zod.literal`, to match an exact string (typically the command name), and `zod.string`, to accept any string (typically a parameter value).

The callback function receives the parsed command as an array of strings, for example `["navigate", "/game"]`, so `script[1]` is the value after the command name.
