qory

command module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

README

🐝 qory

A harness is what your coding agent reads before it works: instructions, skills, agents, commands and settings. qory builds the harness of a repository from modules. Each module is one piece of harness: the piece every repository of your team shares, the piece for apps built on your framework, the piece this repository alone needs. The repository commits the list of modules, not a copy of their files.

The problem

Your coding agent reads its harness from the repository. You have many repositories, and more than one agent. Claude Code reads .claude, Codex reads .codex, Gemini CLI reads .gemini. So every repository holds one copy per tool. When the shared part improves, the copies drift, and nothing tells you which version a checkout runs with.

Don't worry, use Qory

What qory does

A stack lists modules in order: the harness your team shares, the harness for apps built on the framework, the harness this repository alone needs. qory composes them into one tree and writes that tree the way each tool reads it. The tree is linked into the checkout and kept out of git. A report says which module every entry came from.

A module is written once and serves Claude Code, Codex CLI, Gemini CLI, OpenCode, Cursor, GitHub Copilot CLI, Amp, Goose, and every tool that reads AGENTS.md and .agents/skills. A checkout can serve two tools at once, and both read the same harness.

The model is Docker's: a module is an image, the stack is the Compose file, and the composed tree is what runs. One rule differs on purpose. When two modules provide the same entry, qory refuses to compose until the stack says which one to keep. Nothing wins by coming last.

Three steps

  1. Write qory.yaml in the repository, or let qory setup repo write it:

    apiVersion: qory.ai/v1alpha1
    harness:
      target:
        runtime: claude          # or both at once: [claude, codex]
        model: opus
      modules:
        - name: core             # what every repository of yours gets, pinned to a tag
          source: {git: https://github.com/acme/harness, ref: v2.4.0, path: core}
        - name: nextjs           # the harness for Next.js apps
          source: {path: ../harness/nextjs}
        - name: app              # this repository's own, committed with it
          source: {path: ./harness}
    

    Every module has a qory-module.yaml that names it. A repository can also take a stack someone else delivers, a qory-stack.yaml: it names that stack under extends instead of target, and adds its own modules. The delivered modules cannot be changed. A delivered stack states the qory it needs, qory: ">=0.3.0", and every repository extending it inherits the range.

  2. Compose it:

    qory harness compose
    
  3. Start your agent in the checkout. It reads the composed tree through the files it already looks for.

Install

With Homebrew:

brew install qoryai/tap/qory

With the install script, which puts the release binary in ~/.local/bin:

curl -fsSL https://raw.githubusercontent.com/qoryai/qory/main/install.sh | sh

From source, with Go 1.27 or later:

go install github.com/qoryai/qory@latest

Try it

mkdir hello && cd hello
qory setup example       # writes a stack and two modules
qory harness compose     # or: qory hc; for Codex: qory hc --runtime codex
claude                   # type /hello
qory harness remove      # or: qory hr

Both modules ship a greet skill. The README that qory setup example writes says which line to delete to watch qory refuse the collision. For a real repository, run qory setup repo instead.

Worktrees

One branch per worktree, beside the main checkout. qory prepares the worktree the way the repository's qory.yaml says and composes the harness into it:

# qory.yaml, committed, beside the harness section
apiVersion: qory.ai/v1alpha1
worktree:
  base: main                     # a new branch starts here; default: the remote's HEAD
  link: [.env, .env.local]       # linked from the main checkout into the worktree
  run:
    add: [pnpm install]          # run in the new worktree
qory worktree add feature        # ../wt-feature on branch feature, pushing to origin/feature
qory worktree remove             # the worktree you stand in; the branch stays
qory setup shell                 # make your shell cd into a new worktree, and back on remove

Where a worktree goes and what it is called is your choice, not the repository's: worktree.dir and worktree.name in your own qory.yaml, which qory setup machine writes.

Commands

qory setup repo          # write the repository's qory.yaml: its stack, module and worktree settings
qory setup example       # write the hello example into the current directory
qory setup machine       # write your qory.yaml in ~/.config/qory: how qory runs here
qory setup shell         # completions, and a shell that follows worktree add and remove
qory harness compose     # compose the stack into the checkout you stand in   (qory hc)
qory harness inspect     # the report: every entry and the module it came from (qory hi)
qory harness remove      # remove the composed tree and its links               (qory hr)
qory worktree add        # add a worktree for a branch and prepare it            (qory wa)
qory worktree remove     # remove a worktree and keep its branch                 (qory wr)
qory worktree list       # every worktree with its branch                        (qory wl)
qory config              # every setting, its value and the file it came from

Flags worth knowing on compose:

--dry-run              print the report and write nothing
--runtime claude,codex render for these runtimes instead of the stack's
--model opus           write this model instead of the stack's
--force                replace a tracked, unmodified file where a link goes
--update               fetch every git source again
--check                exit 6 when the composed tree is behind the stack and modules

Two qory.yaml files are read. Every setting has a default, so both are optional. The repository's file is committed and holds what the repository decides: its stack, and what a worktree needs. Your file, in ~/.config/qory, holds how qory runs on this machine for every repository: the runtime to compose for, where worktrees go, the git timeout. The repository's file is read on top of yours. qory config shows every setting and the file it came from. The reference, one page per command, is under docs/commands.

What you get

  • The files your tool reads, linked to a composed tree under .qory and kept out of git. Your own settings.local.json stays yours.
  • Settings merged from every module, in the tool's own format. Permission lists and hooks join. A value set twice to different things is a collision, never a silent override.
  • MCP servers, one file each in a module, written where every tool reads them.
  • Modules from a directory beside the repository, or from a git repository at a tag, pinned by commit in the report.
  • One instruction file, joined from the modules in order, under the name each tool wants.
  • A report that names the module of every entry. When two modules provide the same entry, a refusal with the lines that resolve it.
  • Part of a module, when that is all you want. exclude leaves entries, the instruction section, settings fragments or variables out. only takes the named things, plus what they need as the module's manifest declares it, and nothing else: only: {skills: [deploy]} is the deploy skill, the command it runs and the agent it calls, from a module full of other things. A required entry you take from another module instead is one exclude line beside the only.

The composed tree

The home, .qory/harness, holds one directory per runtime. Most of what is in it is a symlink to a file in a module: every skill, agent, command and hook. Beside the links are the generated copies: AGENTS.md at the root of the home, the instruction file each runtime wants, its settings and its MCP file, each joined from the modules' fragments.

Editing a module's file is live through the link. Editing a module's instruction section or a settings fragment is not: the merged copy is generated, and it stays as it was until the next compose. qory harness compose --check compares the home with what the stack and modules say now and exits 6 when a merged copy is behind, which is the check a CI job runs.

What the checkout holds is links too. .claude is a real directory with one symlink per entry, so Claude Code's own settings.local.json stays beside them; .mcp.json and a root AGENTS.md are symlinks. A tool that walks the tree has to follow them:

  • find needs -L.
  • grep -R given a symlink as its operand without a trailing slash reads nothing with BSD grep on macOS and follows the link with GNU grep on Linux, and neither reports an error. Give it the directory with the slash, grep -R pattern .claude/, or use -R -L.
  • rg needs --follow.

git status does not show the tree. Every path qory writes is listed in .git/info/exclude, which every worktree of a repository shares.

The format

The stack, the module manifest, qory.yaml, the composition rules and the runtimes are specified in contracts/harness/v1, with JSON schemas and the fixtures the test suite runs.

Contributing

See CONTRIBUTING.md. Contributions are made under the agreement in CLA.md.

Licence

Apache License 2.0. See LICENSE. Qory™ is a trademark of 8wonders GmbH; TRADEMARKS.md says what you may do with the name.

Documentation

Overview

Command qory composes the harness a runtime loads from modules.

Directories

Path Synopsis
Package cmd is the command tree of the qory binary: one command per noun, one subcommand per verb.
Package cmd is the command tree of the qory binary: one command per noun, one subcommand per verb.
internal
checkout
Package checkout locates the git checkout a command works on and names it.
Package checkout locates the git checkout a command works on and names it.
compose
Package compose turns a stack into one flat tree: every entry once, from one module.
Package compose turns a stack into one flat tree: every entry once, from one module.
config
Package config reads qory.yaml: the repository's own document and the machine's.
Package config reads qory.yaml: the repository's own document and the machine's.
gendocs command
Command gendocs writes the command reference, one Markdown page per command, into the directory given as its argument.
Command gendocs writes the command reference, one Markdown page per command, into the directory given as its argument.
module
Package module reads one directory of harness material: its optional manifest, the entries it ships per kind, its settings fragments and its instruction file.
Package module reads one directory of harness material: its optional manifest, the entries it ships per kind, its settings fragments and its instruction file.
render
Package render writes a composed harness into a checkout the way one runtime reads it.
Package render writes a composed harness into a checkout the way one runtime reads it.
render/amp
Package amp renders for Amp, which reads a project's .amp directory for its settings, AGENTS.md at the checkout root, and skills from .agents/skills.
Package amp renders for Amp, which reads a project's .amp directory for its settings, AGENTS.md at the checkout root, and skills from .agents/skills.
render/any
Package any renders for a program that follows the AGENTS.md convention and has no package of its own, reading the instructions from AGENTS.md at the checkout root and skills from .agents/skills.
Package any renders for a program that follows the AGENTS.md convention and has no package of its own, reading the instructions from AGENTS.md at the checkout root and skills from .agents/skills.
render/claude
Package claude renders for Claude Code, which reads a project's .claude directory: the skills, agents, commands, output styles and hooks under it, its settings.json, and CLAUDE.md beside them, and .mcp.json at the checkout root for the MCP servers.
Package claude renders for Claude Code, which reads a project's .claude directory: the skills, agents, commands, output styles and hooks under it, its settings.json, and CLAUDE.md beside them, and .mcp.json at the checkout root for the MCP servers.
render/codex
Package codex renders for Codex CLI, which reads a project's .codex directory, skills from .agents/skills, and AGENTS.override.md ahead of AGENTS.md.
Package codex renders for Codex CLI, which reads a project's .codex directory, skills from .agents/skills, and AGENTS.override.md ahead of AGENTS.md.
render/copilot
Package copilot renders for GitHub Copilot CLI, which reads agents from .github/agents, hook files from .github/hooks, AGENTS.md at the checkout root, and skills from .agents/skills.
Package copilot renders for GitHub Copilot CLI, which reads agents from .github/agents, hook files from .github/hooks, AGENTS.md at the checkout root, and skills from .agents/skills.
render/cursor
Package cursor renders for Cursor and the Cursor CLI, which read a project's .cursor directory for agents, hooks and settings files such as hooks.json, cli.json and mcp.json, AGENTS.md at the checkout root, and skills from .agents/skills.
Package cursor renders for Cursor and the Cursor CLI, which read a project's .cursor directory for agents, hooks and settings files such as hooks.json, cli.json and mcp.json, AGENTS.md at the checkout root, and skills from .agents/skills.
render/gemini
Package gemini renders for Gemini CLI, which reads a project's .gemini directory, holding its settings.json and the skills, agents, commands and hooks under it, and GEMINI.md at the checkout root.
Package gemini renders for Gemini CLI, which reads a project's .gemini directory, holding its settings.json and the skills, agents, commands and hooks under it, and GEMINI.md at the checkout root.
render/goose
Package goose renders for Goose, which reads AGENTS.md at the checkout root, skills from .agents/skills and agents from .agents/agents.
Package goose renders for Goose, which reads AGENTS.md at the checkout root, skills from .agents/skills and agents from .agents/agents.
render/opencode
Package opencode renders for OpenCode, which reads a project's .opencode directory for agents, commands and hooks, opencode.json for its config, AGENTS.md at the checkout root, and skills from .agents/skills.
Package opencode renders for OpenCode, which reads a project's .opencode directory for agents, commands and hooks, opencode.json for its config, AGENTS.md at the checkout root, and skills from .agents/skills.
report
Package report is the JSON record of one compose: every module with its pin, every entry with its module.
Package report is the JSON record of one compose: every module with its pin, every entry with its module.
source
Package source resolves a module's source to a directory on disk and a pin.
Package source resolves a module's source to a directory on disk and a pin.
stack
Package stack reads qory-stack.yaml.
Package stack reads qory-stack.yaml.
ui
Package ui prints everything a person reads on the terminal, in one vocabulary.
Package ui prints everything a person reads on the terminal, in one vocabulary.
user
Package user reads the name to greet a person with from the local configuration.
Package user reads the name to greet a person with from the local configuration.
worktree
Package worktree adds, removes and lists the linked worktrees of a repository, and prepares a new one the way the repository's qory.yaml says: files linked or copied from the main checkout and commands run in the new worktree.
Package worktree adds, removes and lists the linked worktrees of a repository, and prepares a new one the way the repository's qory.yaml says: files linked or copied from the main checkout and commands run in the new worktree.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL