Flycms Dev
sunkaifei/FlyCms
FlyCms 项目(backend/ Spring Boot 4.1.1 + frontend/ vue-vben-admin v5)的架构地图与开发规范总纲。凡在本仓库做任何开发——写后端接口、新增/修改模块、管理页面、数据库变更、修 bug、重构——都要先加载本 skill 再动手,即使用户只说"改一下""加个功能";前端登录/菜单/权限专项另见…
Java conventions for the Opik backend: layered resource, service and DAO classes, naming rules, Lombok and Guice usage, and notes on MySQL, ClickHouse, migrations and testing.
$ npx skills add comet-ml/opik --skill opik-backend -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install comet-ml/opik opik-backend --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/comet-ml/opik.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/opik-backend .claude/skills/opik-backend && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "opik-backend" agent skill from https://github.com/comet-ml/opik/tree/main/.agents/skills/opik-backend into .claude/skills/opik-backend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opik-backend", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/comet-ml/opik/tree/main/.agents/skills/opik-backendType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add comet-ml/opik --skill opik-backend -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install comet-ml/opik opik-backend --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/comet-ml/opik.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/opik-backend .agents/skills/opik-backend && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "opik-backend" agent skill from https://github.com/comet-ml/opik/tree/main/.agents/skills/opik-backend into .agents/skills/opik-backend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opik-backend", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add comet-ml/opik --skill opik-backend -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install comet-ml/opik opik-backend --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/comet-ml/opik.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/opik-backend .cursor/skills/opik-backend && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "opik-backend" agent skill from https://github.com/comet-ml/opik/tree/main/.agents/skills/opik-backend into .cursor/skills/opik-backend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opik-backend", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/comet-ml/opik.git --path .agents/skills/opik-backend--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add comet-ml/opik --skill opik-backend -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install comet-ml/opik opik-backend --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/comet-ml/opik.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/opik-backend .gemini/skills/opik-backend && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "opik-backend" agent skill from https://github.com/comet-ml/opik/tree/main/.agents/skills/opik-backend into .gemini/skills/opik-backend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opik-backend", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install comet-ml/opik opik-backendInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add comet-ml/opik --skill opik-backend -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/comet-ml/opik.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/opik-backend .github/skills/opik-backend && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "opik-backend" agent skill from https://github.com/comet-ml/opik/tree/main/.agents/skills/opik-backend into .github/skills/opik-backend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opik-backend", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add comet-ml/opik --skill opik-backend -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install comet-ml/opik opik-backend --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/comet-ml/opik.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/opik-backend .opencode/skills/opik-backend && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "opik-backend" agent skill from https://github.com/comet-ml/opik/tree/main/.agents/skills/opik-backend into .opencode/skills/opik-backend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "opik-backend", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
opik-backendJava conventions for the Opik backend: layered resource, service and DAO classes, naming rules, Lombok and Guice usage, and notes on MySQL, ClickHouse, migrations and testing.
The architecture is layered, from Resource to Service to DAO, never skipping a layer, with Guice dependency injection through constructors. MySQL holds metadata and transactional data, while ClickHouse holds append-only analytics. Naming is split: resources, resource tests, URL paths and database tables are plural (TracesResource, /v1/private/traces, traces), while DAO and service classes are singular (TraceDAO, TraceService).
Lombok rules say to annotate records and DTOs with @Builder(toBuilder = true) and construct them through builders. Internal records use Lombok @NonNull on required fields, whereas request-body DTOs validated with Jakarta annotations should not stack @NonNull on top. Injection uses @RequiredArgsConstructor(onConstructor_ = @Inject), and validation annotations stay off interface parameters. A gotchas section covers a StringTemplate memory leak, and companion files cover ClickHouse, migrations, MySQL, permissions and testing.
Read from SKILL.md and the folder at commit 2982cd7. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are java).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Opik Backend Patterns loads about 2.4k tokens when it runs. Until then it costs about 33 tokens; SKILL.md has 549 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from comet-ml/opik at commit 2982cd7, republished under its Apache-2.0 licence (© comet-ml). 549 words, ~2,418 tokens.
.claude/skills/opik-backend/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.@InjectTracesResource, SpansResource, DatasetsResource (not TraceResource)TracesResourceTest, SpansResourceTest, DatasetsResourceTest (not TraceResourceTest)/v1/private/traces, /v1/private/spans (not /v1/private/trace)traces, spans, feedback_scores (not trace, span, feedback_score)TraceDAO, SpanDAO, DatasetDAO (not TracesDAO)TraceService, SpanService, DatasetService (not TracesService)// ✅ GOOD
@Path("/v1/private/traces")
public class TracesResource { }
// ✅ GOOD - DAO and Service use singular
public class TraceDAO { }
public class TraceService { }
// ✅ GOOD - test classes match plural resource name
public class TracesResourceTest { }
// ❌ BAD - singular test class
public class TraceResourceTest { }
// ❌ BAD - singular resource/URL
@Path("/v1/private/trace")
public class TraceResource { }
// ❌ BAD - plural DAO/Service
public class TracesDAO { }
public class TracesService { }@Builder(toBuilder = true)@NonNull on required fields — it generates a runtime null check at construction@Valid cascade (Jakarta validators like @NotNull/@NotBlank/@Size), use Jakarta annotations only — do not stack @NonNull on top. Bean Validation already enforces the contract at the API boundary; doubling up is redundant noise// ✅ GOOD - internal record, Lombok @NonNull
@Builder(toBuilder = true)
record MyData(@NonNull UUID id, @NonNull String name, String description) {}
MyData data = MyData.builder()
.id(id)
.name(name)
.build();
// ✅ GOOD - request-body DTO, Jakarta validators only
@Builder(toBuilder = true)
public record MyRequest(
@NotNull UUID id,
@NotBlank String name,
@NotNull @Size(min = 1, max = 1000) @Valid List<MyItem> items) {}
// ❌ BAD - plain constructor (positional mistakes, less readable)
new MyData(id, name, null);
// ❌ BAD - @Builder without toBuilder
@Builder
record MyData(UUID id, String name) {}
// ❌ BAD - stacking @NonNull and @NotNull on the same field
public record MyRequest(@NonNull @NotNull UUID id) {}@RequiredArgsConstructor(onConstructor_ = @Inject) instead of manual constructors// ✅ GOOD
@RequiredArgsConstructor(onConstructor_ = @Inject)
public class MyService {
private final @NonNull DependencyA depA;
private final @NonNull DependencyB depB;
}
// ❌ BAD - boilerplate constructor
public class MyService {
private final DependencyA depA;
@Inject
public MyService(DependencyA depA) {
this.depA = depA;
}
}@NonNull) on interface method parameters// ✅ GOOD
interface MyService {
void process(String workspaceId, UUID promptId);
}
// ❌ BAD - validation on interface
interface MyService {
void process(@NonNull String workspaceId, @NonNull UUID promptId);
}// ✅ GOOD
var template = TemplateUtils.newST(QUERY);
// ❌ BAD - causes memory leak via STGroup singleton
var template = new ST(QUERY);// ✅ GOOD
users.getFirst()
users.getLast()
// ❌ BAD
users.get(0)
users.get(users.size() - 1)Never build a query out of Java string operations. No +, no String.format /
.formatted(...), no StringBuilder, no MessageFormat, no String.join over clauses. A
query is declared once as a text block, and everything that varies goes through exactly one of
two mechanisms:
| What varies | Mechanism |
|---|---|
| A value — id, name, timestamp, list of ids | :placeholder + .bind("placeholder", value) |
| A fragment — predicate, sort clause, projected column, CTE | StringTemplate <if(x)>…<endif>, <else>, <x> + template.add("x", …) |
Why: interpolating values is the SQL-injection surface, and interpolating fragments hides which query a DAO actually runs — the declaration site stops being readable, and callers drift apart over time.
// ✅ GOOD - text block, values bound, structure via StringTemplate
@SqlQuery("""
SELECT * FROM datasets
WHERE workspace_id = :workspace_id
<if(name)> AND name like concat('%', :name, '%') <endif>
""")
// ❌ BAD - string concatenation
@SqlQuery("SELECT * FROM datasets " +
"WHERE workspace_id = :workspace_id " +
"<if(name)> AND name like concat('%', :name, '%') <endif> ")A predicate that differs between callers is a fragment, so it belongs in the template — not
in a %s slot the caller fills in:
// ❌ BAD - caller splices the predicate in
private static final String TOKEN_USAGE_NAMES_TEMPLATE = """
SELECT DISTINCT name FROM (
SELECT usage FROM spans FINAL
WHERE workspace_id = :workspace_id
AND %s
) ...
""";
static String tokenUsageNames(String projectPredicate) {
return TOKEN_USAGE_NAMES_TEMPLATE.formatted(projectPredicate);
}
// caller: tokenUsageNames("project_id IN :project_ids")
// ✅ GOOD - both shapes live in the template, the caller picks one
private static final String TOKEN_USAGE_NAMES = """
SELECT DISTINCT name FROM (
SELECT usage FROM spans FINAL
WHERE workspace_id = :workspace_id
<if(project_ids)> AND project_id IN :project_ids <endif>
<if(project_id)> AND project_id = :project_id <endif>
) ...
""";
var template = TemplateUtils.newST(TOKEN_USAGE_NAMES);
template.add("project_ids", true);
...
statement.bind("project_ids", projectIds.toArray(new UUID[0]));A fragment that genuinely can't be enumerated in the template — a user-chosen sort field or
filter clause — must be produced by the allow-listed builders (SortingQueryBuilder,
FilterQueryBuilder), never assembled from raw request strings.
.formatted(...) stays correct for log and exception messages. The rule is about SQL text only.
Some %s query templates predate this rule. Don't copy them and don't add new ones.
// ✅ GOOD
Set.of("A", "B", "C")
List.of(1, 2, 3)
Map.of("key", "value")
// ❌ BAD
Arrays.asList("A", "B", "C")exclude_category_names not exclude_category_name). Starting with a singular name and later adding a plural variant results in two redundant query params on the same endpoint. Plural names are backward-compatible since they work for both single and multiple values.throw new BadRequestException("Invalid input");
throw new NotFoundException("User not found: '%s'".formatted(id));
throw new ConflictException("Already exists");
throw new InternalServerErrorException("System error", cause);io.dropwizard.jersey.errors.ErrorMessagecom.comet.opik.api.error.ErrorMessage// ✅ GOOD - values in single quotes
log.info("Created user: '{}'", userId);
log.error("Failed for workspace: '{}'", workspaceId, exception);
// ❌ BAD - no quotes
log.info("Created user: {}", userId);Put the message first and the interpolated values at the end of the sentence, as a trailing
name '{}' list. This keeps a stable literal prefix that stays greppable during a production
debugging session — a message whose values are interleaved has no fixed substring to search for.
Applies to log.* format strings and to exception messages built with .formatted(...).
// ✅ GOOD - literal prefix first, values trailing
log.warn("Alert name is required, workspaceId '{}'", workspaceId);
log.debug("Webhook delivery failed, id '{}', status '{}'", eventId, status);
throw new DestinationGuardException("destination has no valid host, url '%s'".formatted(url));
// ❌ BAD - values interleaved, no greppable prefix
log.debug("Webhook '{}' failed with status '{}'", eventId, status);
throw new DestinationGuardException("destination '%s' has no valid host".formatted(url));@RequiredPermissions annotation guidance for endpoints© comet-ml, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files in .agents/skills/opik-backend of comet-ml/opik.
Open the folder on GitHubat commit 2982cd7
Opik Backend Patterns next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Opik Backend Patterns this skillcomet-ml/opik | 22k | — | ~2.4k | Automated safety check: Pass | Apache-2.0 | |
| Flycms Devsunkaifei/FlyCms | 656 | — | ~827 | Automated safety check: Pass | MIT | |
| Backend Dev Guidelineslitefuse/litefuse | 100 | 1 repos | ~5.8k | Automated safety check: Pass | Custom licence | |
| Springboot Init Skilljiushiwon/wg-skills | 114 | — | ~2.2k | Automated safety check: Notes | Apache-2.0 | |
| Dr Jskilljdubois/dr-jskill | 342 | — | ~4.6k | Automated safety check: Notes | Apache-2.0 | |
| Progensivaprasadreddy/sivalabs-agent-skills | 188 | — | ~2.7k | Automated safety check: Notes | MIT |
sunkaifei/FlyCms
FlyCms 项目(backend/ Spring Boot 4.1.1 + frontend/ vue-vben-admin v5)的架构地图与开发规范总纲。凡在本仓库做任何开发——写后端接口、新增/修改模块、管理页面、数据库变更、修 bug、重构——都要先加载本 skill 再动手,即使用户只说"改一下""加个功能";前端登录/菜单/权限专项另见…
litefuse/litefuse
Comprehensive backend development guide for Litefuse's Next.js 14/tRPC/Express/TypeScript monorepo.
jiushiwon/wg-skills
Spring Boot 项目一键初始化技能。面向零基础小白,提供环境探测、自动安装、完整 Web 骨架生成、SSE 流式框架、JWT 鉴权、统一响应封装、文件上传接口、一键启动/重启脚本、Swagger 文档,内置 MySQL(默认)/ PostgreSQL / MongoDB 数据库选择。用户只需说"帮我搭一个 Spring Boot…
jdubois/dr-jskill
Creates Java + Spring Boot projects: Web applications, full-stack apps with Vue.js or Angular or React or vanilla JS, PostgreSQL, REST APIs, and Docker.
sivaprasadreddy/sivalabs-agent-skills
A skill your agent uses when the user wants to create/generate/scaffold a new Spring Boot project (Maven or Gradle, REST API / Web App / Spring Boot + Angular full stack).
giuseppe-trisciuoglio/developer-kit
Provides and generates complete CRUD workflows for Spring Boot 3 services.
comet-ml/opik
Checklist for wiring a new linter into Opik's Code Quality pipeline: the four files to edit, the silent-failure gotchas and the pass/fail verification loop.
comet-ml/opik
Shows how to add product analytics events to Opik's frontend, Java backend and Python SDK, all reporting through Segment to PostHog with an opik_ name prefix.
comet-ml/opik
Investigates a failed Opik end-to-end test from CI, TestOps or a local run, decides regression versus flake, and proposes a fix without editing tests.
comet-ml/opik
Rules for writing PR descriptions, changelog entries and feature documentation in the Opik repository, including the exact headings that CI requires.
comet-ml/opik
Turns a code change into one committed, passing Playwright end-to-end spec by resolving the change scope and handing authoring to a companion skill.
comet-ml/opik
Starts, rebuilds, and troubleshoots the Opik local dev stack, including an optional Comet Platform integration mode for the Opik team.
Works with
Categories
Java conventions for the Opik backend: layered resource, service and DAO classes, naming rules, Lombok and Guice usage, and notes on MySQL, ClickHouse, migrations and testing. The architecture is layered, from Resource to Service to DAO, never skipping a layer, with Guice dependency injection through constructors. MySQL holds metadata and transactional data, while ClickHouse holds append-only analytics.
Opik Backend Patterns fits situations like: adding a REST resource, service or DAO to apps/opik-backend; writing ClickHouse or MySQL queries and migrations for Opik; naming new classes, URL paths and tables consistently; setting up Lombok annotations on new records and DTOs.
Run `npx skills add comet-ml/opik --skill opik-backend -a claude-code`. Or copy the skill folder (.agents/skills/opik-backend in comet-ml/opik) into .claude/skills/opik-backend in your project. Claude Code loads it when a task matches its description.
Run `npx skills add comet-ml/opik --skill opik-backend -a codex`. Or copy the skill folder (.agents/skills/opik-backend in comet-ml/opik) into .agents/skills/opik-backend in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add comet-ml/opik --skill opik-backend -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/opik-backend, .gemini/skills/opik-backend, .github/skills/opik-backend and .opencode/skills/opik-backend in your project.
SKILL.md names no scripts, command-line tools or credentials: Opik Backend Patterns is instructions for the agent only. Our summary lists: The Opik repository, specifically apps/opik-backend; MySQL and ClickHouse for running the backend.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Opik Backend Patterns is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.4k tokens (SKILL.md is roughly 9.7k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Opik Backend Patterns: Flycms Dev (sunkaifei/FlyCms, 656 stars), Backend Dev Guidelines (litefuse/litefuse, 100 stars), Springboot Init Skill (jiushiwon/wg-skills, 114 stars) and Dr Jskill (jdubois/dr-jskill, 342 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
comet-ml (a GitHub organization) maintains it in comet-ml/opik, which has 22,468 GitHub stars. The repository holds 19 skills in this directory. The repository was last updated on October 9, 2026.
Source: comet-ml/opik on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.