From powerbuilder-dev
Use when modifying PowerBuilder source code (.srw, .srd, .sru, .srm files). Guides the complete workflow from reading to compilation. MUST be used for any PB code change.
How this skill is triggered — by the user, by Claude, or both
Slash command
/powerbuilder-dev:pb-modifyThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
These rules exist because Claude has caused real compilation failures by hallucinating variable names, control names, and function signatures. Every rule below comes from a real incident.
These rules exist because Claude has caused real compilation failures by hallucinating variable names, control names, and function signatures. Every rule below comes from a real incident.
NEVER invent a variable, control, or function name. If you haven't seen it in the source code via pb_read_object, it does not exist. The incident with dw_purline_quickfeed (correct name: dw_purlinelimite_quickfeed) cost 3 hours of debugging.
NEVER use Edit or Write on .sr files.* These tools corrupt PB encoding (BOM, CRLF, tabs). A PreToolUse hook will block you. Always use pb_modify_script.
NEVER declare a variable without checking existing declarations. The ld_qtyold duplicate declaration incident caused a compilation failure that was invisible in Deploy mode.
NEVER skip the verification step (Step 5). You MUST re-read the modified file to confirm your change is correct before compiling.
NEVER modify forward, on create, or on destroy sections. These are generated by the PB IDE and will break the object if altered.
NEVER guess a DataWindow column name. Use pb_dw_get_columns or read the .srd file to get the actual column names.
NEVER copy code between windows without checking control names. Each window has its own controls with specific names. What works in w_quickpurchase may reference controls that don't exist in w_quickpurchaselimite.
Before changing any PowerBuilder file, you MUST gather complete context:
pb_read_object to get the FULL source + parsed metadatapb_get_inheritance — what does this inherit from? What inherits from it?pb_get_dependencies — who references this object? What could break?pb_get_object_summary for a quick structural overviewNEVER modify a PB file without completing all 4 reads above.
Before writing any code, build an explicit inventory of names that exist in the target scope. This prevents hallucination of non-existent identifiers.
From the pb_read_object output, list ALL variables declared in the function/event you're modifying:
type variables ... end variables)type varname at the top of the function/event)CHECK: Is the variable you want to use already declared? If yes, DO NOT re-declare it. CHECK: Does the variable name you're about to use match an existing one EXACTLY? (case-insensitive in PB, but names must match)
If your code references any UI control (DataWindow, button, text field, etc.), verify it exists:
pb_read_object output for the control's type declarationdw_purline vs dw_purlinelimite — these are DIFFERENT controls)pb_search_code to find the control name in the sourceIf your code accesses DataWindow columns (via GetItemString, SetItem, GetItemNumber, etc.):
pb_dw_get_columns or pb_get_datawindow_sql to get the actual column list.srd file directlyIf calling a function on an object:
pb_read_object or pb_search_codeBefore writing code, state explicitly:
If you cannot confirm a name from Step 2, STOP and ask the user or search for it.
Use pb_modify_script for targeted find-and-replace:
.bak backups.pbl/ subfolder for compilationFor new functions/events, insert at the correct location in the file:
type variables ... end variables sectionforward prototypes ... end prototypesend type declarationIMPORTANT: When modifying similar code in multiple files (e.g., w_quickpurchase AND w_quickpurchaselimite):
pb_read_object firstThis step is MANDATORY. Do NOT skip it.
After each pb_modify_script call:
pb_read_object (or the specific section with pb_read_object + section parameter).pbl/ sync: pb_modify_script reports pbl_synced in its output — confirm it's not nullOnly proceed to Step 6 if the re-read confirms the modification is correct.
pb_validate_syntax for quick structural checkpb_compile for full compilation (uses Full Build by default — gives detailed errors like C0081, C0015)C0081: Duplicate variable → you declared a variable that already existed (Step 2 failure)C0015: Undefined variable → you used a name that doesn't exist (hallucination)C0114: Error scanning object source entry → encoding corruption (should not happen with pb_modify_script)C0248: Missing definition of top-level type → $PBExportHeader$ or forward section damagedcopy_pbds: trueIf compilation fails:
.bak backup file exists — restore with pb_modify_script if neededis_ = instance string, il_ = instance long, ib_ = instance booleanid_ = instance decimal/date, ii_ = instance integerls_ = local string, ll_ = local long, lb_ = local boolean, ld_ = local decimalas_ = argument string, al_ = argument long, etc.of_ = object function (public method)wf_ = window function (private to window)gf_ = global functionue_ prefix = user-defined events (custom)w_ = window, nvo_ = non-visual object, uo_ = user object (visual)d_ = datawindow, m_ = menust_ = static text, sle_ = single line edit, mle_ = multi-line editcb_ = command button, dw_ = datawindow controlddlb_ = dropdown list box, rb_ = radio button, cbx_ = checkbox$PBExportHeader$objectname.srw
forward ← DO NOT MODIFY
global type ... from ...
end type
end forward
shared variables ← shared across instances
end variables
type variables ← instance variables
end variables
forward prototypes ← function declarations
end prototypes
type prototypes ← more declarations
end prototypes
event open;...end event ← events
public function ...end function ← functions
on objectname.create ← lifecycle — DO NOT MODIFY
on objectname.destroy ← lifecycle — DO NOT MODIFY
SQLCA = default transaction object (database connection)SQLCA.SQLCode (1 = success, -1 = error)this. = current object, parent. = parent windowdestroy = free memory for dynamic objects (MUST be called or memory leaks)trigger event = fire event now, post event = queue for laterBefore submitting your modification, verify:
[ ] Step 1: Read object, inheritance, dependencies, summary — ALL DONE
[ ] Step 2: All variable names confirmed from source (not invented)
[ ] Step 2: All control names confirmed from source (not invented)
[ ] Step 2: All DW column names confirmed (not guessed)
[ ] Step 2: All function names/signatures confirmed
[ ] Step 3: Plan stated with explicit name list
[ ] Step 4: Used pb_modify_script (NOT Edit/Write)
[ ] Step 5: Re-read modified file — change is correct
[ ] Step 5: No duplicate declarations introduced
[ ] Step 5: pbl_synced confirmed
[ ] Step 6: pb_compile succeeded (Full Build)
[ ] Step 7: No errors left — codebase compiles clean
npx claudepluginhub juliendetilleux/powerbuilder-toolkit --plugin powerbuilder-devProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.