SLOPSHOPPER

agent-charter

Pin an agent charter into the system prompt: skills-first workflow, per-language comment standards, commit format and branch discipline.

newprompt
A shopper browsing a rack in a slop shop
README

agent-charter

Claude Code Mod:给智能体立一份行为宪章,覆盖 skill 使用、注释规范、 提交格式、分支纪律。

内容

宪章是静态文本(plus:agent-charter),默认追加在 shared 阵营末尾, 不花缓存、四 Mod 行为:

  • Skill 优先:开工先列相关 skill/plugin,有现成的不重造;不臆造 API。
  • 注释规范:只解释为什么;Java Javadoc、Python Docstring、C# XML、 PHP PHPDoc、C/C++ Doxygen、Go Go Doc、Rust Rustdoc、Ruby RDoc/YARD、 Kotlin KDoc。
  • 提交格式:[模块][n/m]{【类型】【版本】中文\英文描述}(需求号)。
  • 分支纪律:一事一分支,主分支不动;自测通过才合,合完删分支; PR 讲清改了什么、为什么、怎么验证。

两种模式

charterMode: append(默认):保留引擎原 composition,工具说明和 安全边界都在,只加宪章。replace: constitutional charter 之外 全部丢掉——模型会变笨、工具会残、安全会裸奔,只给知道自己在干什么 的人用:

{ "charterMode": "replace" }

使用

claude --plugin-dir mods/agent-charter
claude plugin test mods/agent-charter
claude plugin install plus@claudecode-plus-mod --scope user
Source 2 files
hooks/register.ts 43 lines
1import type { On } from 'claude-code'
2
3import { CHARTER_ID, applyCharter, buildCharter, resolveCharterMode } from './charter'
4
5type CharterOptions = {
6  charterMode?: string
7  verbose?: boolean
8}
9
10function report($: unknown, message: string, verbose: boolean): void {
11  const ui = ($ as { ui: { log: (text: string, opts?: object) => void } }).ui
12  if (verbose) {
13    ui.log(message)
14  } else {
15    ui.log(message, { to: 'debug' })
16  }
17}
18
19/**
20 * Pins the agent charter into the system prompt. Append mode (default) keeps
21 * the engine's composition, tools and safety rails included, and adds the
22 * charter last among shared sections. Replace mode drops everything else:
23 * use it only when you accept a dumber, unguarded agent.
24 *
25 * @param on the engine's registrar
26 * @param options `charterMode` append or replace; `verbose` surfaces lines
27 */
28export function register(on: On, options: CharterOptions = {}): void {
29  const mode = resolveCharterMode(options.charterMode)
30  const verbose = options.verbose === true
31  const mine = { id: CHARTER_ID, text: buildCharter(), scope: 'shared' as const }
32
33  on('session.start', ($, e, next) => {
34    report($, `[agent-charter] active in ${mode} mode`, verbose)
35    return next(e)
36  })
37
38  on('prompt.compose', async (_$, e, next) => {
39    const out = await next(e)
40    return { sections: applyCharter(out.sections, mine, mode) }
41  })
42}
43
hooks/charter.ts 86 lines
1/**
2 * Agent charter: one static section pinned into the system prompt. Static on
3 * purpose, so it sits on the shared side of the cache boundary in append
4 * mode. Replace mode drops the engine's own composition entirely, tools
5 * included: only for operators who know what they are giving up.
6 */
7
8export const CHARTER_ID = 'plus:agent-charter'
9
10export type CharterMode = 'append' | 'replace'
11
12const CHARTER = [
13  '# 代理宪章',
14  '',
15  '## Skill 与 Plugin 优先',
16  '开工前先列出本次任务相关的 skill 和已装 plugin,有现成能力先用,不重复造轮子。',
17  '项目级 skill 优先于通用做法;调用了哪个 skill,在总结里注明。',
18  '不要臆造不存在的 skill、命令或 API,不确定就先查。',
19  '',
20  '## 注释规范(按语言)',
21  '注释只解释为什么,不解释是什么;禁止装饰性注释(分隔线、星号框、ASCII 艺术)。',
22  '- Java: Javadoc',
23  '- Python: Docstring',
24  '- C#: XML 文档注释',
25  '- PHP: PHPDoc',
26  '- C / C++: Doxygen',
27  '- Go: Go Doc,注释紧贴声明并以名称开头',
28  '- Rust: Rustdoc(/// 对外,//! 对内)',
29  '- Ruby: RDoc / YARD',
30  '- Kotlin: KDoc',
31  '',
32  '## 提交信息格式',
33  '严格遵守:[模块][n/m]{【类型】【版本】中文\\英文描述}(需求号)',
34  '示例:[鉴权][2/5]{【修复】【v2.3】登录超时 Login timeout}(REQ-1234)',
35  'n/m 是本次系列提交的序号与总数;无需求号时括号内写实际事由,不许空着。',
36  '',
37  '## 分支与 PR 纪律',
38  '每次修改从主分支切新分支,一事一分支,禁止直接在主分支上改。',
39  '自测通过、确认无误后才合并;合并后删除分支,不许堆积。',
40  'PR 必须讲清三件事:改了什么、为什么改、怎么验证的;缺任何一件都不许合。',
41].join('\n')
42
43/**
44 * @param raw the `charterMode` option as received, anything unexpected falls back
45 * @returns append by default, replace only when explicitly asked
46 */
47export function resolveCharterMode(raw: unknown): CharterMode {
48  if (raw === 'replace') {
49    return 'replace'
50  }
51  return 'append'
52}
53
54/**
55 * @returns the full charter text
56 */
57export function buildCharter(): string {
58  return CHARTER
59}
60
61export type ComposableSection = {
62  id: string
63  text: string
64  scope: 'shared' | 'session'
65}
66
67/**
68 * @param sections the engine's composed list, every shared one ahead of every session one
69 * @param mine the charter section to add
70 * @param mode append keeps the engine's composition and adds the charter last
71 * among shared; replace drops everything and returns the charter alone
72 * @returns the sections the model will read
73 */
74export function applyCharter(
75  sections: readonly ComposableSection[],
76  mine: ComposableSection,
77  mode: CharterMode,
78): ComposableSection[] {
79  if (mode === 'replace') {
80    return [mine]
81  }
82  const shared = sections.filter((section) => section.scope === 'shared')
83  const session = sections.filter((section) => section.scope !== 'shared')
84  return [...shared, mine, ...session]
85}
86