Custom Script Fields
Custom Script Fields let you create your own computed fields with arbitrary JavaScript logic. Unlike built-in script fields (which offer pre-made templates), custom script fields give you full control over what to calculate and how to display it.
Creating a Custom Script Field
- Go to Apps → ScriptForge → Scripted Fields
- Click Create Custom Field
- Fill in:
- Field Name — shown as the field label on issues
- Field Type — String, Number, or Paragraph
- Script — your computation logic
- Save and add the field to your screens
Field Type Details
String Fields
Return a single string value. Displayed as a text label.
// Show which sprint the issue is overdue in
const issue = await WorkItems.getByKey(context.issueKey);
const dueDate = issue.dueDate ? new Date(issue.dueDate) : null;
if (!dueDate) return 'No due date';
if (dueDate < new Date()) return '⚠️ Overdue';
return 'On track';
Number Fields
Return a numeric value. Can be used in Jira's built-in sum/average gadgets.
// Total story points of all sub-tasks
const issue = await WorkItems.getByKey(context.issueKey);
const subtasks = await issue.getSubTaskObjects();
let total = 0;
for (const task of subtasks) {
const points = task.getCustomFieldValue('customfield_10016') || 0;
total += points;
}
return total;
Paragraph Fields
Return multi-line text. Useful for summaries or formatted data.
// List all comments authors (last 5)
const issue = await WorkItems.getByKey(context.issueKey);
const comments = await issue.getComments();
const recent = comments.slice(-5);
return recent.map(c => `${c.author.displayName} - ${c.created}`).join('\n');
Using HAPI in Script Fields
Script fields have full access to the HAPI library:
// Check if the assignee is in the "developers" group
const issue = await WorkItems.getByKey(context.issueKey);
const assigneeId = issue.assignee;
if (!assigneeId) return 'Unassigned';
const user = await Users.getByAccountId(assigneeId);
const groups = await user.getGroups();
const isDev = groups.some(g => g.name === 'developers');
return isDev ? 'Developer' : 'Non-developer';
Using Entity Properties
For expensive calculations, consider writing the result via a listener and reading it in the scripted field:
// Read a pre-computed value from entity properties
const issue = await WorkItems.getByKey(context.issueKey);
const props = await issue.getEntityProperties();
const score = await props.getInteger('risk-score');
return score || 0;
Tips
- Keep scripts fast — they run on every issue render
- Use entity properties to cache expensive calculations (computed by listeners/jobs)
- Return
nullor an empty string if there's nothing to display - Number fields should always return a numeric value (or 0), not text