Two changes: 1. structured-add-commands: The implicit note shorthand (kb "text") caused accidental note creation from mistyped commands. Replaced with explicit kb addnote <text> command. Root command reverts to standard Cobra behaviour. Updated examples, tests, SKILL.md, and specs. 2. split-readme-developer-docs: Moved build-from-source instructions, release process, API reference, and ROCm migration notes from README.md into a new DEVELOPER.md. README now links to DEVELOPER.md for dev workflows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.0 KiB
Context
The kb client currently overloads the root Cobra command to handle both command dispatch and implicit note ingestion. Any unrecognized multi-word input is silently submitted as a note via POST /api/v1/jobs. This was introduced to reduce friction for note-taking but has proven error-prone — typos in commands create unwanted notes. A single-word guard was added but multi-word typos still slip through.
The root command has: custom ArbitraryArgs validation, a RunE with arg-count branching, a --tags flag for the note shorthand, a custom usage template with isRootCmd template function, and submitNote() living in add.go.
Goals / Non-Goals
Goals:
- Eliminate accidental note creation from mistyped commands
- Provide a clean, explicit
addnotecommand that pairs with existingaddfile - Revert root command to standard Cobra behaviour (no custom args, no custom template)
- Keep the same API contract —
POST /api/v1/jobswithnotefield unchanged
Non-Goals:
- Changing the engine API
- Modifying
addfilebehaviour - Adding new content types (url, bookmark, etc.)
- Backward compatibility shim for
kb "text"syntax
Decisions
1. New addnote command in its own file
Create client/cmd/addnote.go with a cobra.Command that takes ExactArgs(1) — a single quoted string. This mirrors addfile which also takes ExactArgs(1).
Rationale: Keeps each command in its own file (consistent with the existing pattern). ExactArgs(1) means the user must quote multi-word notes, which is unambiguous and avoids the flag-parsing edge cases that plagued the implicit shorthand.
Alternative considered: Joining ArbitraryArgs like the old shorthand. Rejected — this is exactly the ambiguity we're removing.
2. Move submitNote() from add.go to addnote.go
The function is only used by the addnote command, so it belongs in the same file.
Rationale: add.go becomes purely about file operations (it already is, aside from hosting submitNote()). Clean separation.
3. Fully revert root command to Cobra defaults
Remove: ArbitraryArgs, custom RunE (replace with nil — Cobra shows help by default), --tags flag on root, custom usage template, isRootCmd template function.
Rationale: The root command should do one thing — dispatch to subcommands. All the custom logic was there to support the implicit shorthand which is being removed.
4. addnote gets its own --tags flag
The --tags flag moves from the root command to addnote, matching how addfile already has its own --tags flag.
Risks / Trade-offs
- Breaking change for existing users → Mitigated by clear error messaging. If someone types
kb "some text", Cobra will say "unknown command". Theexamplescommand will show the new syntax. - Slightly more typing for notes (
kb addnote "text"vskb "text") → Acceptable trade-off for eliminating accidental ingestion. Tab-completion helps. - Scripts using old syntax will break → This is intentional. The old syntax was a foot-gun.