Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add skills/jborgia/signaltree/ng-formsnpx skills add JBorgia/signaltree --skill ng-formsgit clone --depth 1 https://github.com/JBorgia/signaltreeWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/jborgia/signaltree/ng-forms)<a href="https://agentmods.dev/skills/jborgia/signaltree/ng-forms"><img src="https://agentmods.dev/badge/skills/jborgia/signaltree/ng-forms.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00113 | $0.02507 |
| Opus 5 | $0.00056 | $0.01254 |
| Sonnet 5 | $0.00023 | $0.00501 |
| Haiku 4.5 | $0.00011 | $0.00251 |
Grade A, and why
signaltree-ng-forms scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 236 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Using @signaltree/ng-forms
Use when an Angular component needs both a SignalTree-backed state slice (reactive in templates/computed/effect) and a native Angular FormGroup/FormControl for ReactiveFormsModule, third-party UI libs, or ControlValueAccessor interop.
Install:
npm install @signaltree/core @signaltree/ng-forms
Peer: @angular/core ^20, @angular/forms ^20, rxjs ^7.
Two patterns — choose one:
- Pattern B:
form()marker +formBridge()— recommended for new code. Form is one slice of a larger tree. - Pattern A:
createFormTree()— when entire component is a form and you want all helpers on one object. Emits dev-only deprecation note; fully functional.
Pattern A — createFormTree (full example with validators, async validation, conditionals, persistence):
import { createFormTree, ngFormValidators } from '@signaltree/ng-forms';
// v12: the bare validator exports were removed — use the ngFormValidators object.
const { required, email, minLength, pattern } = ngFormValidators;
interface ProfileForm extends Record<string, unknown> {
name: string;
email: string;
role: string;
company: { name: string; size: string };
}
class ProfileComponent {
emailAvailabilityValidator: any = null;
readonly profile = createFormTree<ProfileForm>(
{ name: '', email: '', role: 'individual', company: { name: '', size: '1-10' } },
{
persistKey: 'profile-form',
storage: typeof window !== 'undefined' ? window.localStorage : undefined,
validationBatchMs: 120, // coalesce validation results (80–150ms for many async validators)
fieldConfigs: {
name: { validators: [required(), minLength(3)] },
email: {
validators: [required(), email()],
asyncValidators: [this.emailAvailabilityValidator],
debounceMs: 180,
},
'company.name': { validators: [pattern(/^[A-Za-z0-9 .,'&-]{2,}$/)] },
},
conditionals: [{ when: (v) => v.role === 'manager', fields: ['company.name'] }],
}
);
async save() {
try {
await this.profile.submit(async (values) => {
/* typed ProfileForm */
});
} catch {
/* FormValidationError thrown on validation failure */
}
}
}
Bind template: [formGroup]="profile.form". Read signal: profile.$.name(). Read error: profile.getFieldError('email')().
Pattern B — form() marker + formBridge():
import { form, FormSignal, signalTree, validators } from '@signaltree/core';
import { formBridge } from '@signaltree/ng-forms';
const store = signalTree({
contact: form<ContactForm>({
initial: { name: '', email: '', message: '' },
validators: {
name: validators.required('Name is required'),
email: [validators.required(), validators.email()],
message: [validators.required(), validators.minLength(10)],
},
}),
}).with(formBridge());
const bridge = store.getAngularForm('contact');
// bridge?.formGroup → FormGroup; bridge?.formControl('email') → FormControl
formBridge() auto-discovers all form() markers in the tree, including nested paths (tree.getAngularForm('user.profile')).
Pattern C — wizard via form() marker:
import { form, signalTree } from '@signaltree/core';
interface SignupForm extends Record<string, unknown> {
email: string;
password: string;
firstName: string;
lastName: string;
}
const tree = signalTree({
signup: form<SignupForm>({
initial: { email: '', password: '', firstName: '', lastName: '' },
wizard: {
steps: ['credentials', 'profile'],
stepFields: { credentials: ['email', 'password'], profile: ['firstName', 'lastName'] },
},
}),
});
// tree.$.signup.wizard: next(), prev(), goTo(step), currentStep, isLastStep
See WizardConfig and FormWizard in @signaltree/core for full shape.
Pattern D — undo/redo, via core history() (v13+; recommended, works with both form() alone and a bound signalForm()):
import { signalTree, form, history } from '@signaltree/core';
interface ContactForm extends Record<string, unknown> {
name: string;
email: string;
ssn: string;
}
const tree = signalTree({
contact: form<ContactForm>({
initial: { name: '', email: '', ssn: '' },
history: history({ capacity: 20, exclude: ['ssn'] }), // exclude = never snapshotted
}),
});
tree.$.contact.patch({ name: 'Ada' });
tree.$.contact.history?.undo();
tree.$.contact.history?.redo();
tree.$.contact.history?.canUndo(); // Signal<boolean>
tree.$.contact.history?.history(); // Signal<{ past: T[]; present: T; future: T[] }>
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 5d ago First seen · 236 lines · 113 tokens per session scan A 4bf73a5cb5a2
signaltree-ng-forms is a skill published in the GitHub repository JBorgia/signaltree (22 stars, last pushed 14d ago), licensed Apache-2.0. It adds 113 tokens to every session and 2,507 once invoked, about $0.0006 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other skills, from other repositories
systematic-debugging
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes.
local-ai-agents
Build local-first AI agents that run entirely on a developer workstation with Microsoft Foundry Local and Qwen function-calling models. Covers Small Language Models (SLMs), the OpenAI-compatible local endpoint, sandboxed local tools, local RAG with Chroma, local MCP servers, hybrid cloud/local routing, and the…
chronicle
Analyze Copilot session history for standup reports, usage tips, session search, and session reindexing. Use when the user asks for a standup, daily summary, usage tips, workflow recommendations, wants to search or find past sessions by keyword/file/PR, wants to reindex their session store, or asks about deleting…
imagegen
Generate or edit raster images when the task benefits from AI-created bitmap visuals such as photos, illustrations, textures, sprites, mockups, or transparent-background cutouts. Use when Codex should create a brand-new image, transform an existing image, or derive visual variants from references, and the output…
chat-pet-sprite-creation
Use when creating or changing VS Code chat pet sprite art, sprite sheets, state animations, eye treatments, Stable/Insiders variants, or pet transitions under src/vs/workbench/contrib/chat/browser/widget/media/chatPet.
cpu-profile-analysis
Analyze V8/Chrome CPU profiles (.cpuprofile) and DevTools trace files (Trace-.json). Use when: profiling performance, investigating slow functions, comparing code paths, finding bottlenecks, analyzing timeToRequest, understanding call trees from sampling profiler data, analyzing layout/paint/rendering, investigating…