Successfully implemented write operations for the HPL CLI to enable creating and updating Lab Notes via the API.
Added two new intent definitions for write operations:
create_lab_note: For creating new Lab Notesupdate_lab_note: For updating existing Lab Notes
Both intents:
- Target scope:
["lab_notes", "remote_api"] - Side effects:
["write_remote"] - Reversible:
false(write operations cannot be automatically undone)
Added two new exit codes:
VALIDATION: 6- For data validation failuresIO: 7- For file I/O errors
Added postJson<T>() function:
- Supports POST requests with JSON payloads
- Handles Bearer token authentication
- Follows existing error handling patterns with
HttpError - Supports unwrapping envelope responses
Implements hpl notes create subcommand:
Features:
- Required options:
--title,--slug - Content input:
--markdown(inline) or--file(from file) - Optional metadata:
--locale,--subtitle,--summary,--tags,--published,--status,--type,--dept - Authentication via
HPL_TOKENenvironment variable or config file - Zod validation of payload before sending
- JSON and human output modes
- Proper error handling with specific exit codes
Example usage:
# Create from file
hpl notes create --title "New Note" --slug "new-note" --file ./note.md
# Create with inline content
hpl notes create --title "Quick Note" --slug "quick-note" --markdown "# Content here"
# With metadata
hpl notes create \
--title "Research Paper" \
--slug "ai-collaboration-patterns" \
--file ./paper.md \
--type paper \
--tags "ai,research,collaboration" \
--status publishedImplements hpl notes update subcommand:
Features:
- Positional argument:
<slug>(note to update) - Optional fields: All create fields (except slug is argument not option)
- Requires at least
--titleand (--markdownor--file) for full updates - Uses same upsert endpoint as create
- Authentication via
HPL_TOKEN - 404 handling for non-existent notes
- JSON and human output modes
Example usage:
# Update from file
hpl notes update my-note --title "Updated Title" --file ./updated.md
# Update specific fields
hpl notes update my-note --status published --tags "updated,reviewed"
# Full update with inline content
hpl notes update my-note \
--title "Revised Note" \
--markdown "# New content" \
--summary "Updated summary"Integrated new commands into the notes command tree:
- Imported
notesCreateSubcommandandnotesUpdateSubcommand - Added both to the command tree (before sync)
Both commands use the existing /lab-notes/upsert endpoint with the LabNoteUpsertPayload schema:
{
slug: string; // required
title: string; // required
markdown: string; // required
locale?: string;
subtitle?: string;
summary?: string;
tags?: string[];
published?: string;
status?: "draft" | "published" | "archived";
type?: "labnote" | "paper" | "memo" | "lore" | "weather";
dept?: string;
}Both commands require authentication via:
HPL_TOKENenvironment variable, OR- Token configured in
~/.humanpatternlab/hpl.json
Returns E_AUTH (exit code 4) if token is missing or invalid.
Both commands support:
- Human mode (default): Readable text output with status messages
- JSON mode (
--json): Structured JSON envelope following the existing contract
Comprehensive error handling for:
- Missing authentication (
E_AUTH, exit 4) - File not found (
E_NOT_FOUND, exit 3) - File I/O errors (
E_IO, exit 7) - Validation errors (
E_VALIDATION, exit 6) - Network errors (
E_NETWORK, exit 10) - Server errors (
E_SERVER, exit 11) - Unknown errors (
E_UNKNOWN, exit 1)
Implementation follows all existing HPL CLI patterns:
- ✅ Core function returns
{ envelope, exitCode } - ✅ Commander adapter handles mode selection and rendering
- ✅ Zod schema validation before API calls
- ✅ Consistent error shapes with codes and messages
- ✅ Proper use of intent descriptors
- ✅ File headers with lab unit attribution
- ✅ Support for both JSON and human output modes
- ✅ Predictable exit codes for automation
Before deployment, test:
-
Create command:
# Test with file hpl notes create --title "Test" --slug "test-note" --file ./test.md # Test with inline content hpl notes create --title "Test" --slug "test-note-2" --markdown "# Test" # Test validation error hpl notes create --title "Test" --slug "test" # Missing content # Test auth error unset HPL_TOKEN hpl notes create --title "Test" --slug "test" --file ./test.md
-
Update command:
# Test successful update hpl notes update test-note --title "Updated" --file ./updated.md # Test 404 hpl notes update nonexistent --title "Test" --markdown "Test" # Test JSON mode hpl notes update test-note --title "Test" --markdown "Test" --json
-
JSON contract verification:
hpl notes create --title "Test" --slug "test" --markdown "Test" --json | \ node -e "JSON.parse(require('fs').readFileSync(0,'utf8'))"
Potential enhancements:
- Add
--partialflag to update command for true partial updates (fetch existing + merge) - Add
hpl notes delete <slug>command using DELETE endpoint - Add batch operations support
- Add interactive mode for creating notes with prompts
- Add validation for slug format (kebab-case, etc.)
- Add dry-run mode like sync has
Modified:
src/contract/intents.ts- Added create/update intentssrc/contract/exitCodes.ts- Added VALIDATION and IO exit codessrc/http/client.ts- Added postJson functionsrc/commands/notes/notes.ts- Wired new commands
Created:
src/commands/notes/create.ts- Create command implementationsrc/commands/notes/update.ts- Update command implementation
Total changes: 4 modified files, 2 new files