Skip to main content
A domain decides when. A rule is what gets said. They are separate commands because they are separate things, and they live in separate places: triggers in domains.toml, rule text in the graph.

Creating a domain

Why it works. A domain has three kinds of trigger. prompt_keywords match against what you type. file_keywords match against the content of a file being worked on. paths match against recently-active file paths pulled from the graph. Any one of them firing is enough. The gotcha. Creating a domain gives you a bucket with no rules in it. A match with nothing attached injects nothing, silently, which is the single most common reason people conclude base is not working. Add a rule next, not later.

Adding a rule

Why it works. Rules are graph nodes attached to the domain, so they can be added, listed and removed without touching config, and the same rule can be reasoned about alongside the decisions and notes filed under the same domain. The gotcha. Write the --rationale. It is injected with the rule as “rule, because rationale”, and a rule with a reason attached survives being argued with in a way that a bare imperative does not. Next rung. base rule remove --domain billing --index 2 removes one by the index shown in rule list. Indexes shift after a removal, so list again between removals rather than working down a list you printed earlier.

The global tier

-g goes on rule itself, before the verb. After the verb is invalid. The gotcha. Six commands carry -g: rule, decision, handoff, fork, learn and changes. Everything else decides its tier from where you are standing, and outside a registered workspace base refuses the write rather than picking one for you. Check base help <command> instead of assuming.

Checking a domain fires

base context runs the real matcher against text you supply, without sending anything anywhere. This is the fastest possible answer to “would this have worked”.

When nothing gets injected

Work down this ladder in order. It is ordered by how often each cause is the real one.
1

Did you type a star command in that prompt?

A matched *command short-circuits domain matching for that turn. Your rules do not arrive, and nothing says so. This is the most common cause by a distance, especially if you have settled into a mode you type by habit.
2

Does the domain have any rules?

An empty list means the trigger fires and there is nothing behind it. domains.toml holds triggers only, so a domain can look perfectly configured and be empty.
3

Does the trigger actually match?

Matching is plain substring and path comparison. A domain triggered on invoice does not fire on billing, and nothing is doing anything clever on your behalf.
4

Are you inside a registered workspace?

Outside one there is no workspace graph to match against. base scaffold fixes it.
5

Is the hook itself running?

This runs the hook by hand and prints what it would have injected. Read stderr as well as stdout.

Watching it work while you tune

With devmode on, hook output carries a diagnostic block showing which domains matched, why, and what was deduplicated or suppressed. It is the fastest way to tune a trigger, because you can see the match rather than infer it. The gotcha. Turn it back off when you are done. It adds output to every hook event, and the noise stops being informative quickly.

Removing triggers and domains

base domain remove is a triggers-level delete: the rules you added still exist in the graph, they simply have nothing left to fire them. If you want a domain quiet but recoverable, remove its triggers instead.
The domain write commands do not all use the same tier. create, remove-trigger and remove only touch the global ~/.base-gbl/domains.toml. add-trigger writes the workspace file.Two consequences. A domain you create and then add a trigger to is split across two files. And a trigger added inside a workspace cannot be removed from the command line: remove-trigger will not find it, and base domain remove reports “Domain not found” for a workspace domain that base domain list is showing you, because list merges both tiers and the write commands do not.Established from source at 4866996, the commit the shipped 0.13.2 binary was built from. Until it changes, edit the workspace .base/domains.toml by hand for anything the CLI will not reach.

Pushing config into the graph

This reads domains.toml into the graph so domains and their bootstrap rules exist as entities. It also runs on its own at session start, gated by a timestamp so it is a no-op when nothing has changed.

Next

Debugging injection

The rest of the story: brackets, suppression, and where the audit trail is.

Context reference

Every domain and rule command, with its flags.