bama
BAMA: Build Any Mac App. Agent skills to research, clone, design, build, optimize, and test native macOS apps with Swift and SwiftUI.
Agentic discipline plugin for Codex, Claude Code, Pi, and OpenCode—with always-active response, planning, engineering, and task-tracking skills.
SkillsJavaScriptGitHub @DinoQuintenSelf-installOwner unconfirmed
Paste into Claude or ChatGPT for installation instructions suited to your environment.
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Installable projects can be verified without a deployment domain. Use GitHub sign-in for a personal repository, or the repository verification file above for an organization repository.
Ask about other verification options
Loading the full README. The saved excerpt is shown below.
Always-active engineering standards for Codex, Claude Code, Pi, and OpenCode.
Discipline is an agentic plugin with four shared skills: clear technical communication, implementation planning, engineered software work, and task tracking. Every supported host reads the same files under skills/.
Codex and Claude Code use lifecycle hooks. Pi uses a native package extension. OpenCode supports a native plugin or global instructions. Response, engineering, and task-registry rules stay active throughout the session. Planning rules apply while a plan is being created or reviewed.Read the full README ↗Always-active engineering standards for Codex, Claude Code, Pi, and OpenCode.
Discipline is an agentic plugin with four shared skills: clear technical communication, implementation planning, engineered software work, and task tracking. Every supported host reads the same files under skills/.
Codex and Claude Code use lifecycle hooks. Pi uses a native package extension. OpenCode supports a native plugin or global instructions. Response, engineering, and task-registry rules stay active throughout the session. Planning rules apply while a plan is being created or reviewed.
| Skill | Enforced workflow |
|---|---|
response-discipline | ASD-STE100 writing, direct answers, Yes/No fixability reports, evidence before conclusions, concise structure, RCA-formatted failure reports, and minimal targeted changes. |
engineering-discipline | Official-docs-first implementation, a docs-used.md ledger, the YAGNI ladder, root-cause fixes, behavior-level tests, blast-radius checks, and executed verification. |
task-registry | Append-only registry.jsonl recording every task any agent, sub-agent, or worker job performs — including no-diff work like audits, RCA, and decisions. |
planning-discipline | Host-neutral decomposition, alternative analysis, self-consistency, ReAct investigation, root-cause planning, and optional user-approved debate. |
| Host | Always-active mechanism | On-demand discovery |
|---|---|---|
| Codex | SessionStart and SubagentStart hooks | agents/openai.yaml and ~/.agents/skills |
| Claude Code | SessionStart and SubagentStart hooks | Claude skill discovery |
| Pi | Native before_agent_start extension | Package skills resources |
| OpenCode | Native plugin or global instructions | Skills CLI installation for all four skills |
The package and extension shapes follow docs-used.md D7 and D8. OpenCode instruction and skill behavior follows docs-used.md D9 and D10.
codex plugin marketplace add DinoQuinten/engineering-skill
codex plugin add discipline@dinoquinten
Start a new session. Open /hooks, review the two plugin hook definitions, and trust them. Codex skips non-managed plugin hooks until their current definitions are trusted.
codex plugin marketplace add /absolute/path/to/engineering-skill
codex plugin add discipline@dinoquinten
Codex manages installed copies under ~/.codex/plugins/cache/dinoquinten/discipline/. Do not edit the cache. Edit the checkout, refresh or reinstall the marketplace plugin, then start a new session.
Codex also discovers standalone personal skills under ~/.agents/skills/<skill-name>/SKILL.md. Standalone installation does not include the always-active hooks.
/plugin marketplace add DinoQuinten/engineering-skill
/plugin install discipline@dinoquinten
Restart the session. Use /context to confirm that the four skills appear in the SessionStart hook context.
/plugin marketplace add /absolute/path/to/engineering-skill
/plugin install discipline@dinoquinten
Claude Code manages installed copies under ~/.claude/plugins/cache/dinoquinten/discipline/. Edit the checkout rather than the cache, then update or reinstall the plugin and restart the session.
The .claude-plugin/ files are intentional compatibility metadata, not leftovers.
Install the GitHub package at the release tag:
pi install git:github.com/DinoQuinten/[email protected]
From the cloned repository root:
pi install .
Pi reads package.json, discovers all four skills, and loads extensions/always-active.js. The extension requires the three always-active skills, adds a compact planning reminder, and exposes the full planning body through the planner bridge.
On every before_agent_start, the extension appends the preamble and three always-active skill bodies to the current system prompt. It preserves the existing prompt and returns no persistent conversation message.
OpenCode has two ways to auto-inject the skills: global instructions (simplest) or a self-contained plugin for conditional Plan-agent loading.
extensions/opencode-discipline.js loads the skills through one classic OpenCode plugin:
response-discipline, engineering-discipline, and task-registry are appended to every system prompt.planning-discipline is appended only while the Plan agent is active.Reference it from the plugin array by absolute path. This keeps the skill source in the checkout and avoids copied files:
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["/absolute/path/to/engineering-skill/extensions/opencode-discipline.js"]
}
Or copy extensions/opencode-discipline.js and extensions/skill-body.js into ~/.config/opencode/plugin/ and copy skills/ into ~/.config/opencode/skills/; the plugin resolves skill files relative to its own directory.
The plugin uses chat.message to learn the active agent, because the classic experimental.chat.system.transform hook carries no agent identity. Verified on OpenCode 1.18.31: the build agent gets the always-active block only, the Plan agent gets the always-active block plus planning-discipline, and neither block is duplicated within one system build.
Known overhead: OpenCode rebuilds the system prompt for auxiliary calls (session title, compaction), and the classic transform cannot distinguish them. The always-active block is therefore added to those calls; while the tracked agent is Plan, planning-discipline can be added too. Use the instructions route below if that cost matters. Do not load opencode-planning-classic.js alongside this plugin — it is the earlier reminder-only adapter and is superseded by this one.
Merge the instructions entries below into the existing ~/.config/opencode/opencode.json. Preserve every existing key and every existing instruction entry; do not replace the file.
{
"instructions": [
"https://raw.githubusercontent.com/DinoQuinten/engineering-skill/v1.12.0/skills/response-discipline/SKILL.md",
"https://raw.githubusercontent.com/DinoQuinten/engineering-skill/v1.12.0/skills/engineering-discipline/SKILL.md",
"https://raw.githubusercontent.com/DinoQuinten/engineering-skill/v1.12.0/skills/task-registry/SKILL.md",
"https://raw.githubusercontent.com/DinoQuinten/engineering-skill/v1.12.0/skills/planning-discipline/SKILL.md"
]
}
The v1.12.0 tag pins instruction behavior. Upgrade all four URLs together when adopting a later release. With this route, all four bodies are present automatically in every session; planning-discipline limits its workflow to planning tasks through its own instructions, so no explicit skill invocation is required.
Clone or download the repository, then use absolute local paths instead of the remote URLs. OpenCode resolves relative instruction paths from the active working directory, so global configuration should use absolute paths.
{
"instructions": [
"/absolute/path/to/engineering-skill/skills/response-discipline/SKILL.md",
"/absolute/path/to/engineering-skill/skills/engineering-discipline/SKILL.md",
"/absolute/path/to/engineering-skill/skills/task-registry/SKILL.md",
"/absolute/path/to/engineering-skill/skills/planning-discipline/SKILL.md"
]
}
On Windows, use JSON paths such as C:/absolute/path/to/engineering-skill/skills/response-discipline/SKILL.md.
Install all four skills globally for OpenCode with one command:
npx skills add DinoQuinten/engineering-skill -g -a opencode -y
Verify the merged global configuration and discovered skills:
opencode debug config
opencode debug skill
OpenCode always includes configured instructions. Discovered skills work differently: OpenCode advertises their names and descriptions, then adds a body only when the model or user invokes the skill tool. Use both steps: instructions provide automatic behavior, while the Skills CLI command makes response-discipline, engineering-discipline, task-registry, and planning-discipline explicitly invokable.
After the host-specific installation, normal prompts need no prefix:
Fix the failed sync and verify the behavior through its public API.
Expected workflow:
Codex users can still invoke $engineering-discipline or $response-discipline. Pi and OpenCode also discover the skills for on-demand use. In Codex, Claude Code, and Pi, the always-active preamble tells the model not to load the full bodies again. OpenCode keeps its skill tool available even when global instructions already loaded the same bodies.
| Host | Moment | Integration | Result |
|---|---|---|---|
| Codex and Claude Code | New, resumed, cleared, or compacted root session | SessionStart | Inject each skill in a separate hook payload. |
| Codex and Claude Code | Every subagent | SubagentStart | Apply the same standards in isolated context. |
| Codex and Claude Code | Entering or leaving plan mode | PostToolUse (EnterPlanMode/ExitPlanMode) | Inject planning-discipline on entry, clear its session marker on exit. |
| Pi | Every submitted agent prompt | before_agent_start | Append the three always-active skills plus the planning reminder to the current chained system prompt. |
| OpenCode | Every session using global config | instructions | Load all version-pinned files into context. |
PostCompact is not used for Codex or Claude Code instruction injection. Both hosts provide compact recovery through SessionStart with a compact source.
.
├── .agents/plugins/marketplace.json # Codex repository marketplace
├── .claude-plugin/ # Claude Code manifest and marketplace
├── .codex-plugin/plugin.json # Codex manifest
├── extensions/always-active.js # Native Pi before_agent_start extension
├── extensions/opencode-discipline.js # OpenCode classic all-in-one self-injecting plugin
├── extensions/opencode-planning.js # OpenCode v2 Plan-agent context hook
├── extensions/opencode-planning-classic.js # OpenCode classic reminder transform (superseded)
├── extensions/skill-body.js # Shared skill-body reader for adapters
├── hooks/ # Shared Codex and Claude Code hooks
├── package.json # Native Pi package manifest
├── skills/ # Shared source-of-truth skill bodies
└── test/ # Hook and Pi package behavior tests
| Host | Plugin root | Personal skill ownership |
|---|---|---|
| Codex | PLUGIN_ROOT | ~/.agents/skills/<name>/SKILL.md |
| Claude Code | CLAUDE_PLUGIN_ROOT | ${CLAUDE_CONFIG_DIR:-~/.claude}/skills/<name>/SKILL.md |
Codex also supplies CLAUDE_PLUGIN_ROOT as a compatibility alias. hooks/hooks.json uses that alias so one command works in both hosts; the injector prefers native PLUGIN_ROOT when Codex runs it.
If a matching personal skill exists, the plugin skips its copy. The personal copy owns its activation behavior. Set DISCIPLINE_FORCE_INJECT=1 to force the plugin copy during testing.
Each skill is registered as its own hook command so every payload stays inline instead of spilling to a file-backed preview.
The additionalContext cap is 10,000 characters. Live-session tests delivered 10,000 characters inline; at 10,081 characters, the host substituted a roughly 1.7 KB preview and silently omitted the rest. Injectors strip YAML frontmatter before emitting because it is discovery metadata, not runtime instruction text. test/inject-skills.test.mjs enforces the cap against the real skill files.
If a matching skill exists under your personal skills directory, the plugin skips its own copy, so hand-editing both produces two forks that drift. Author skills in this repo and regenerate the personal copies:
npm run sync # repo -> ~/.claude/skills (only names already present there)
npm run sync:check # exits 1 if a personal copy has drifted from the repo
skills/<name>/SKILL.md with name and description frontmatter.skills/<name>/agents/openai.yaml for Codex presentation and invocation policy.hooks/hooks.json.instructions.planning-discipline covers decomposition, bounded alternative analysis, self-consistency, and read-only ReAct investigation. It applies only while a plan is being produced; it never authorizes execution, workers, or permission changes. Debate stays off until the user opts in once per planning task.
| Host | Full skill | When detection is unavailable |
|---|---|---|
| Codex | SessionStart / UserPromptSubmit / PostToolUse when permission_mode: "plan" | Compact reminder (host omitted permission_mode); nothing for an explicit non-plan mode |
| Claude Code | Same, plus PostToolUse on a successful EnterPlanMode | Compact reminder on absent mode |
| OpenCode v2 | context hook when event.agent === "plan" (extensions/opencode-planning.js) | Not needed; agent identity is available |
| OpenCode classic | extensions/opencode-discipline.js tracks the agent from chat.message, then appends the skill on experimental.chat.system.transform | Compact reminder plus skill path (extensions/opencode-planning-classic.js) |
| Pi | Official planner calls the bridge inside its own active plan branch | Compact reminder in the always-active preamble |
The injector records a per-session marker so the full skill is not re-injected on every prompt. SessionStart with a compact or clear source refreshes it; ExitPlanMode clears it. With no session_id the guard is skipped (fails open to a duplicate rather than dropping discipline).
Pi has no universal cross-extension plan-state API, so the official plan-mode extension calls the bridge from inside the branch where it already knows plan mode is active:
import { getPlanningDisciplineInstructions } from 'discipline/extensions/always-active.js';
// Inside the planner's before_agent_start handler, plan branch already chosen:
const planBody = getPlanningDisciplineInstructions();
return { systemPrompt: event.systemPrompt + '\n\n' + planBody };
The helper returns an empty string when the skill is absent, so the bridge cannot break the planner. Other Pi planners keep explicit skill invocation. This package does not replace Pi's planner or its tool restrictions.
v2: add extensions/opencode-planning.js to the plugin list; it appends the full skill for the plan agent and skips duplicates already in the outgoing context.
Classic (verified against OpenCode 1.18.31): copy extensions/opencode-planning-classic.js and extensions/skill-body.js into <config>/opencode/plugin/. Any .js/.ts file in that directory is auto-loaded — no plugins array entry is needed — and a default or named export that is async () => hooks is accepted. The adapter registers experimental.chat.system.transform and can only add the discovery reminder, because that hook carries no agent identity. The reminder names the resolved skill path only when that path exists, so a relocated adapter degrades to the pathless reminder rather than pointing at a missing file. OpenCode discovers skills from <config>/opencode/skill/<name>/SKILL.md and <config>/opencode/skills/<name>/SKILL.md; opencode debug skill lists them.
Each skill stays under the measured 10,000-character additionalContext cap; test/inject-skills.test.mjs enforces it.
Run all deterministic suites:
node --test
PowerShell smoke test for Codex:
$env:PLUGIN_ROOT = (Get-Location).Path
'{"hook_event_name":"SessionStart","source":"startup"}' |
node hooks/inject-skills.mjs --only response-discipline
POSIX smoke test for Claude Code:
echo '{"hook_event_name":"SessionStart","source":"startup"}' \
| CLAUDE_PLUGIN_ROOT="$PWD" node hooks/inject-skills.mjs --only response-discipline
The hook emits one JSON object whose hookSpecificOutput.additionalContext contains only the requested skill. An unknown --only name or unreadable skills/ directory produces no output and exits zero.
.skill archives are ignored snapshots. skills/ is the source of truth.docs-used.md#D13, not on live host runs: Codex and Claude Code permission_mode, Claude EnterPlanMode, OpenCode v2 event.agent. Codex permission_mode may be absent in older builds or wrappers; those hosts fall back to the compact reminder.DISCIPLINE_STATE_DIR overrides it). Hosts that omit session_id get no dedup.experimental.chat.system.transform fires with output.system as a string array; the transform fires once per system-prompt build, and the adapter's includes() guard prevents a duplicate within one build.skill-body.js with the repo's skills/ sibling, or the reminder drops the path (by design).PATH for Codex and Claude Code lifecycle injection and repository tests.MIT