8.4 KiB
AI Agent Instructions
This file provides guidance on how to work with code in the Zammad repository.
Project Overview
Zammad is an open-source helpdesk/support platform. The backend is Ruby on Rails. There are two frontend stacks: the current production frontend is CoffeeScript (served via the Rails asset pipeline), and the new frontend is Vue 3 + TypeScript served via Vite (managed by pnpm), which is being built alongside it. PostgreSQL is used for persistence, Redis for ActionCable/GraphQL subscriptions, and GraphQL is the API layer between the new Vue apps and the backend.
Architecture
CoffeeScript frontend ──→ REST controllers ──→ Rails backend ──→ PostgreSQL
↑
Vue 3 frontend (desktop/mobile) ──→ GraphQL API ────┘
New features target the Vue 3 + GraphQL stack. The CoffeeScript frontend uses REST controllers.
Key Directories (non-standard)
app/services/service/— Service objects encapsulating business logicapp/graphql/gql/— GraphQL schema, types, mutations, subscriptionsapp/policies/— Authorization policies (Pundit)app/frontend/apps/desktop/— Vue 3 desktop appapp/frontend/apps/mobile/— Vue 3 mobile appapp/frontend/shared/— Shared Vue components, composables, stores, GraphQL types, form systemapp/assets/javascripts/— CoffeeScript frontend (Spine + jQuery, legacy, still actively maintained)lib/— Library code, prefer minimal Rails coupling
General Guidelines
- All new files except Markdown files (
*.md) must include the Zammad copyright header. - Never edit translation files (
i18n/*.po) directly — translations are managed via translations.zammad.org.
Code Comments
Comment only what the code cannot say itself: a non-obvious why, a workaround with its reason, a spec/protocol quirk, or a deliberate deviation from a pattern. Otherwise add no comment — clear naming and small methods are preferred over explanation.
- One or two short lines, in the style of the surrounding file.
- Never restate what the next line does, summarise a block, label
sections (
# --- setup ---), or narrate a change (# new,# was …,# fixed). - Keep out reasoning that belongs in the commit message, the issue or the MR description.
- Never reference an issue from an internal repository (
coordination-*) — this repository is publicly mirrored. Reference a publiczammad/zammadissue, or state the reason without a link. - Never mark a fix for a security vulnerability as such — this repository is publicly mirrored, and the comment points at the vulnerable code in installations that are not updated yet.
UI Principles
- Icon-only buttons need
v-tooltipsupplying the accessible name. - Hover/focus-only visible actions need to display on touch fallback
- Responsive grids should adapt to their container
- Translatable strings: use complete, meaningful source strings, sentence case for English source strings, and check for existing near-duplicate strings before adding new ones.
- Red marks the point of no return:
dangerandremovestay only on controls that act immediately. A trigger that only opens a confirmation dialog or a confirming flyout is not red: a button becomestertiarywith an icon naming the action (trash3for delete and discard,arrow-counterclockwisefor reset), a menu item carries no variant, aremoveicon button keeps its icon and takes the variant UX names per place. The decisive button in the dialog or flyout isdanger.
Essential Commands
Backend
RAILS_ENV=test VITE_TEST_MODE=1 bundle exec rspec spec/path/to/file_spec.rb # Run specific RSpec test
bundle exec rubocop --autocorrect app/path/to/file.rb # Lint specific Ruby file(s)
Frontend
Always use pnpm for frontend and cross-stack commands.
pnpm test --run app/frontend/path/to/file.spec.ts # Run specific Vitest test (never add `--`)
pnpm lint # Run all linters
pnpm generate-graphql-api # Regenerate GraphQL types after schema changes
pnpm generate-setting-types # Regenerate Config types after setting changes
Development stack
A browser-clickable instance for this checkout. Start it via bin/dev rather
than forego directly, and wait for it to answer before using it.
RAILS_ENV=development bundle exec rake db:create zammad:bootstrap:reset # once per checkout
bin/dev # does not exit; run it in the background
It serves on localhost:3000, with the websocket server on 6042 and Vite on
3036. Export ZAMMAD_RAILS_PORT, ZAMMAD_WEBSOCKET_PORT and
VITE_RUBY_PORT before bin/dev to move them — the whole stack has to agree
on them, so export, do not set them per process.
zammad:bootstrap:reset migrates, seeds and runs the auto wizard, which creates
admin@example.com / test. Plain zammad:db:init skips the wizard and leaves
the browser on the getting-started screen. Never run zammad:bootstrap:init or
zammad:setup:db_config: they overwrite config/database.yml and prompt on
stdin, which hangs a non-interactive session.
The test suite uses its own ports (3001 and 6043) and its own database, so
it can run while the stack is up. Several checkouts, however, share the
development database and Redis — only one stack per machine unless
DATABASE_URL and REDIS_URL say otherwise.
Development Lifecycle
Issues are tracked on GitHub, code is developed on a self-hosted GitLab.
GitHub hosts a read-only mirror. The agent uses the GitHub MCP server for
issues and glab CLI for GitLab operations.
Stories are refined and broken down into task issues before this lifecycle
starts (/refine-story → /plan-story). Bugs skip that and enter it directly.
Lifecycle: Understand → Research → Plan → Branch (/prepare-issue-branch) →
Implement → Test → Review → Commit → MR (/create-mr) → Cherry-pick
(/cherry-pick-to-stable)
See .dev/agent_docs/development_workflow.md for the full lifecycle and
workflow rules.
Agent Reference Docs
You MUST read the relevant file(s) below before responding when working on that area — do NOT read them all upfront:
.dev/agent_docs/graphql_patterns.md— How to add/modify GraphQL types, mutations, queries, and subscriptions.dev/agent_docs/frontend_patterns.md— Vue component conventions, composables, routing, and the form system.dev/agent_docs/frontend_addon_layer.md— How an addon extends the Vue frontend via the build-time weave (Vapor-safe, multi-addon).dev/agent_docs/legacy_model_patterns.md— Concerns needed by new models used in the legacy stack: REST assets (one-to-one relations only) and client notifications.dev/agent_docs/testing.md— How to write and run backend and frontend tests.dev/agent_docs/testing_services_and_graphql.md— How to split spec coverage between a service and the query, mutation or subscription that calls it.dev/agent_docs/service_patterns.md— Service object conventions and structure.dev/agent_docs/knowledge_base_patterns.md— Knowledge base rules for the new stack (Vue/GraphQL/services) only: the single active knowledge base and the deliberate exceptions to it.dev/agent_docs/database_migrations.md— How to write migrations and work with seeds
CodeGraph
In repositories indexed by CodeGraph (a .codegraph/ directory exists at the repo
root), reach for it before grep/find or reading files when you need to understand
or locate code:
- MCP tool (when available):
codegraph_exploreanswers most code questions in one call — the relevant symbols' verbatim source plus the call paths between them, including dynamic-dispatch hops grep can't follow. Name a file or symbol in the query to read its current line-numbered source. If it's listed but deferred, load it by name via tool search. - Shell (always works):
pnpm exec codegraph explore "<symbol names or question>"prints the same output using the repository-pinned CodeGraph version.
If there is no .codegraph/ directory, skip CodeGraph entirely — indexing is the
user's decision. If they ask to initialize it, run pnpm codegraph:init. Developer
setup and removal are documented in
doc/developer_manual/development_environment/codegraph-setup.md.