Skip to content
Back to skills

Warehouse

BSecurity

The guild's warehouse — how to read and write guild data with SQL. Load this before touching anything in the guild database: tasks, requirements, plans, goals, projects, bugs, review findings, work logs, coverage, the execution graph, gates, ticket capabilities, or the event feed. Also load it for the LIBRARY — documentation, decisions and ADRs, how a page relates to the work it describes, what superseded what, and which pages went stale. Also for the board, the brief, bounties, "what's next"...

  • 5 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 2, 2026
ai-agentsgoshellbashsqlnodegitapidatabasedocumentation

Works with

  • cli
  • api

Security analysis

B88/100
  • criticalSends environment variables or credentials to an external URL

Pro scans all 6 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add HirogaKatageri/hirokata --skill warehouse --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Warehouse?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Warehouse
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/hirogakatageri-warehouse/badge)](https://www.skillsdirectory.com/skills/hirogakatageri-warehouse)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: warehouse
description: >
  The guild's warehouse — how to read and write guild data with SQL. Load this
  before touching anything in the guild database: tasks, requirements, plans,
  goals, projects, bugs, review findings, work logs, coverage, the execution
  graph, gates, ticket capabilities, or the event feed. Also load it for the
  LIBRARY — documentation, decisions and ADRs, how a page relates to the work it
  describes, what superseded what, and which pages went stale. Also for the
  board, the brief, bounties, "what's next", "what moved", roster gaps, or a
  capability match — the roster itself lives in the agent files, and this skill
  says where. Trigger phrases include "guild board", "guild brief", "next task",
  "claim a task", "open bounties", "file a bug", "log work", "review finding",
  "ready nodes", "resolve a gate", "the roster", "match an agent", "guild.db",
  "tursodb", "warehouse", "guild database", "guild SQL", "write a doc",
  "the library", "knowledge graph", "decision record", "ADR", "link a doc",
  "supersede a decision", "stale docs", "undocumented work".
version: 1.1.0
allowed-tools: Bash(tursodb *)
---

# The warehouse

`tursodb` is the tool. There is no guild CLI — you write SQL. The schema carries the
guild's rules as CHECK constraints, views and triggers, so the way to be correct is to
read what is already there rather than invent your own spelling of a rule.

## Connect

```bash
export PATH="$HOME/.turso:$PATH"
printf "SELECT fact, value FROM v_brief;\n" | tursodb -q -m list .guild/guild.db
```

Cloud boards (`.guild/config.yaml` has `mode: cloud`) use the other binary and the URL
from the env var named in that file:

```bash
printf "SELECT fact, value FROM v_brief;\n" | turso db shell "$(printenv TURSO_DATABASE_URL)"
```

The schema lives at `${CLAUDE_PLUGIN_ROOT}/schema.sql`. Applying it is idempotent —
`tursodb .guild/guild.db < schema.sql` — and is how a rule change reaches a live board.

## Seven rules that are always true

1. **Free text crosses as hex.** A `;` that ends a line ends the statement, even inside a
   string literal — and requirement bodies quote code. Every title, body, rationale, log
   entry and finding goes in as `CAST(x'<hex>' AS TEXT)`, which is always one line:
   `hex=$(printf '%s' "$v" | xxd -p | tr -d '\n')`. Never `echo`. Never round-trip the
   value through `$( )` — that eats trailing newlines. Empty string is `''`.
   Ids, enum values, agent names, capabilities and timestamps you generated are closed
   alphabets and may be quoted literals.
2. **The SQL itself must not pass through a `%`-interpreting layer.** Rule 1 protects the
   DATA; this protects the QUERY. Guild SQL is full of `printf('%03d', …)` and
   `strftime('%Y-%m-%dT%H:%M:%SZ','now')`, and a shell `printf` used to BUILD a statement
   eats those `%` sequences before SQLite sees them. The write then succeeds, exit code 0,
   `RETURNING` prints a row, and the stored value is literally `TASK-%03d`. Put SQL in a
   **quoted** heredoc (`<<'SQL'`) and use `printf` only for hex, where the format is a
   constant and the payload is the argument. See `references/tursodb-gotchas.md` §9a.
3. **`PRAGMA foreign_keys = ON;` at the top of every writing script.** It is
   per-connection and defaults to OFF, and every invocation is a fresh connection.
4. **Never parse `-m list` output positionally.** It is pipe-separated with no quoting,
   and free text contains pipes *and newlines* — a newline forges a whole row. Either
   `json_object(...)`, or select exactly one column when you need a value byte-exact, or
   flatten in SQL before it leaves the engine.
5. **Read the view, do not re-derive the rule.** `v_next_task`, `v_open_bounties`,
   `v_task_actionable`, `v_ready_nodes`, `v_board`, `v_brief`, `v_doc_current`,
   `v_doc_stale` and the rest each hold ONE
   definition of a rule. Two members writing their own version of "which task is next"
   gives the guild two answers to one question, and both look right. **The one rule with
   no view is the agent match** — the roster is not in this database — and its single
   definition is `guild:check-in` §3.3.
6. **A failing statement does not stop the script, and `COMMIT` still commits.** There is
   no `-bail`. Keep scripts to one logical change, put `RETURNING` on every mutation so
   "did it land" is answered by output, and do the referential check *inside* the write
   (`INSERT … SELECT … FROM parent WHERE parent.id = 'REQ-001'` — the `FROM` is the check).
7. **Errors print on stdout, not stderr.** `out=$(… | tursodb …)` captures the error as if
   it were a row. Always check the exit code, and never `>/dev/null` the failure path.

Set your name once per script so the triggers attribute the events to you:
`UPDATE guild_state SET value = 'developer-svelte' WHERE key = 'actor';`
It is a label, not an identity — nothing authenticates it.

## The library is a graph, not a pile

`doc` rows are nodes, `knowledge_edge` rows are typed relations between them **and any other
row on the board**, and `doc_revision` is the history a trigger writes for you. Three habits
make it work, and skipping any of them turns it back into a pile:

1. **Tag the `kind`.** `business` / `technical` / `decision` / `research` / `runbook` /
   `reference`. Every reader branches on it, and `reference` is what you pick when you have
   not decided.
2. **Link it to something.** A document with no edge is invisible to `v_doc_stale` (nothing
   to compare against) and counts for nothing in `v_undocumented_work`. Find the orphans with
   `SELECT slug FROM v_doc_current WHERE edges = 0`.
3. **Supersede — never overwrite — a decision.** Write the new ADR as its own row and add a
   `supersedes` edge. The old one stays and `v_doc_current` hides it. Editing the old body to
   say "we don't do this any more" destroys the only record of what was believed.

**There is no traversal.** `WITH RECURSIVE` is a parse error on tursodb, so a chain is one
query per hop, looped in the caller and **capped** — unlike the execution graph, this one may
legitimately contain a cycle.

## References — load what the task needs

- **`references/schema.md`** — what every table is FOR, how the tables relate, and which
  rules the database enforces versus which are conventions you must honor yourself. Load
  it when you are deciding *where a piece of information belongs*, or when you need to
  know whether something is actually guaranteed.
- **`references/queries.md`** — the canonical, verified queries: creating a requirement /
  plan / task / bug with derived ids, moving something through status, the
  daily reads (board, brief, bounties, what moved), the execution graph, and §5 on the
  roster — which is where to find it, since it is not in SQL. **§1 also carries the whole
  library**: writing a typed doc, linking it with the write-time check that stands in for
  the missing foreign key, superseding a decision, walking the graph one hop at a time,
  and the two drift reads. Load it when you are about to write SQL. Copy from it rather
  than improvising.
- **`references/tursodb-gotchas.md`** — the traps, each reproduced against the real
  binary: the statement splitter, invalid UTF-8, `-m list` forgery, no `WITH RECURSIVE`,
  no FTS5, `LIKE` escaping, output-channel injection, non-atomic scripts, and the
  local-vs-cloud engine split. Load it before writing any *shell* around the SQL, before
  rendering guild data into a document or a board, or when something behaved strangely.

Files in this skill

  • SKILL.md6.8 KB
  • references/queries.md33.6 KB
  • references/schema.md27.2 KB
  • references/templates/maintenance.md22.8 KB
  • references/templates/standard.md25.3 KB
  • references/tursodb-gotchas.md23.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…