Skip to content

selectBuiltins

JavaScript · package toolnexus · SPEC §4A · js/src/builtin.ts

function selectBuiltins(cfg?: BuiltinsConfig): Tool[]
type BuiltinsConfig =
| boolean
| { enabled?: boolean; disabled?: boolean; tools?: Record<string, boolean> }

Applies createToolkit’s builtins option — the same value you would pass there — to createBuiltinTools(), without needing a toolkit around it. This is the filtering createToolkit runs internally, exposed directly.

  • You’re assembling a tool list yourself, outside createToolkit, and want the built-ins filtered the same way — same config shape, same semantics, same result.
  • You want to preview what a given builtins config resolves to before wiring it into a toolkit (“if I set { tools: { bash: false } }, what’s actually left?”).
  • You’re testing the filtering logic itself, independent of MCP/skills/toolkit aggregation.

undefined behaves exactly like true — built-ins are on by default, matching the MCP-server and skill enable/disable precedence used everywhere else in toolnexus: disabled: true wins over everything, then enabled: false, otherwise on.

1. The smallest useful call — the default, and the off switch

Section titled “1. The smallest useful call — the default, and the off switch”
import assert from "node:assert"
import { selectBuiltins } from "toolnexus"
// Omitted config ⇒ same as `true` ⇒ all ten built-ins.
assert.equal(selectBuiltins().length, 10)
assert.equal(selectBuiltins(true).length, 10)
// The boolean shorthand for "off" — no built-ins at all.
assert.deepEqual(selectBuiltins(false), [])
console.log("ok:", selectBuiltins().length, "on by default, 0 when false")

2. A per-tool drop-list — the realistic case

Section titled “2. A per-tool drop-list — the realistic case”

The object form’s tools map is a drop-list over an all-on baseline: name a tool false to remove just that one; every unnamed tool (and true-mapped ones) stays on. Unknown names are ignored.

import assert from "node:assert"
import { selectBuiltins } from "toolnexus"
// Turn off just `bash` — everything else stays.
const noBash = selectBuiltins({ tools: { bash: false } })
assert.equal(noBash.length, 9)
assert.ok(!noBash.some((t) => t.name === "bash"))
assert.ok(noBash.some((t) => t.name === "read"))
// A name that isn't a real built-in is silently ignored, not an error.
const withUnknown = selectBuiltins({ tools: { bash: false, not_a_real_tool: false } })
assert.equal(withUnknown.length, 9)
console.log("ok:", noBash.map((t) => t.name).join(", "))

3. The full surface — enabled/disabled precedence, and the object form’s false

Section titled “3. The full surface — enabled/disabled precedence, and the object form’s false”

The object form’s own enabled/disabled fields take precedence over tools — turning the whole source off short-circuits before any per-tool filtering happens.

import assert from "node:assert"
import { selectBuiltins } from "toolnexus"
// disabled:true wins outright — tools is never consulted.
assert.deepEqual(selectBuiltins({ disabled: true, tools: { bash: true } }), [])
// enabled:false is the same as disabled:true when disabled is absent.
assert.deepEqual(selectBuiltins({ enabled: false }), [])
// enabled:true (or omitted) + a tools map ⇒ normal per-tool filtering.
const onlyFileTools = selectBuiltins({ enabled: true, tools: { bash: false, webfetch: false, question: false, apply_patch: false, todowrite: false } })
assert.deepEqual(onlyFileTools.map((t) => t.name).sort(), ["edit", "glob", "grep", "read", "write"])
console.log("ok:", onlyFileTools.map((t) => t.name).join(", "))
Field Type What it does
cfg (bare boolean) boolean true/omitted ⇒ all ten. false ⇒ none.
cfg.enabled boolean false turns every built-in off (unless overridden by disabled).
cfg.disabled boolean true turns every built-in off — takes precedence over enabled.
cfg.tools Record<string, boolean> Drop-list over the all-on default: false removes that tool by name; unknown names are ignored.