Skip to content

feat(cli): add harper agent — CLI client for the built-in agent (#626)#1553

Open
kriszyp wants to merge 2 commits into
mainfrom
kris/agent-cli
Open

feat(cli): add harper agent — CLI client for the built-in agent (#626)#1553
kriszyp wants to merge 2 commits into
mainfrom
kris/agent-cli

Conversation

@kriszyp

@kriszyp kriszyp commented Jul 1, 2026

Copy link
Copy Markdown
Member

Summary

Adds a harper agent CLI subcommand — a thin client for the built-in agent (#626), so operators can chat with the agent on a local or remote instance without hand-rolling curl against the operations API. This is the transport/UI role #626 anticipated the harper-agent CLI compressing into.

Usage

harper agent "build a Product table exported over REST"   # one-shot: prints the reply, exits
harper agent                                              # interactive REPL
echo "how many tables exist?" | harper agent              # single piped prompt (non-TTY)
harper agent --target https://host:9925 --username admin  # remote instance
harper agent --session <id> "continue where we left off"  # resume a session
harper agent --json "…"                                   # raw session JSON for scripting

Interactive commands: /new (reset session), /exit (quit), /help.

How it works

  • Connection (resolveConnection) mirrors the core of cliOperations without the deploy-specific transport: local unix domain socket by default, or a remote target from --target / HARPER_CLI_TARGET / stored last_target, authenticated with --username/--password (or env), or a stored harper login operation token (Bearer). No changes to the existing deploy/ops CLI path.
  • Turn loop: agent_prompt → poll get_agent_session → render only the transcript items appended since the last poll — assistant text, ▸ tool(args) calls, and results. On awaiting_approval it prints each pending tool call and prompts approve? [y/N]approve_agent_action, then resumes. --session resumes; --json dumps the raw session.
  • Auth: super_user required, same as the underlying agent operations.

Verification

Driven against a live instance:

  • one-shot (harper agent "…") → renders ▸ describe_all({})⤷ {…}agent › The database 'data' contains one table named 'Product'.
  • piped stdin → same one-shot path.
  • --json → raw session with status + messages.

The interactive REPL and the approval prompt reuse the same turn/render/approve logic (validated one-shot); they need a TTY so they aren't exercised in the automated run above.

🤖 Generated with Claude Code

A thin CLI front-end over the agent operations API, so operators can talk to the
built-in agent (#626) locally or on a remote instance without hand-rolling curl.
This is the transport/UI role #626 anticipated for the harper-agent CLI.

- bin/agentCli.ts (new): resolves the ops-API connection the same way the rest of
  the CLI does (local domain socket by default; remote via --target / stored
  `harper login` tokens / env credentials), then:
    * one-shot: `harper agent "build a Product table"` → prints the reply and exits;
      also reads a single piped prompt from stdin when not a TTY.
    * interactive: `harper agent` → a REPL; each line is a turn on one session,
      with /new, /exit, /help.
  Streams a transcript delta after each turn (assistant text, `▸ tool(args)`
  calls, `⤷` results) and, on `awaiting_approval`, prompts to approve/deny each
  pending tool call before resuming. --session resumes an existing session;
  --json prints the raw session for scripting.
- bin/harper.ts + utility/hdbTerms.ts: register the `agent` subcommand and help.

super_user required (same as the underlying ops). Reuses cliCredentials +
httpRequest; no changes to the deploy/ops CLI path.

Verified against a live instance: one-shot, piped stdin, and --json all drive
agent_prompt → get_agent_session and render the tool-calling transcript.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@kriszyp kriszyp requested review from dawsontoth and heskew July 1, 2026 23:48

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new harper agent CLI client (bin/agentCli.ts) that allows users to interact with the built-in Harper agent in either one-shot or interactive REPL modes, integrating it into the main CLI. The review feedback highlights several critical issues in the implementation, including redundant JSON output during polling, potential hangs in non-interactive environments when prompting for approvals, URL parsing errors when ports are already present, credential interpolation bugs, REPL hangs on Ctrl-D exit, and missing null-safety guards when rendering session messages.

Comment thread bin/agentCli.ts
Comment thread bin/agentCli.ts
Comment thread bin/agentCli.ts
Comment thread bin/agentCli.ts Outdated
Comment thread bin/agentCli.ts Outdated
Comment thread bin/agentCli.ts
Comment thread bin/agentCli.ts
@claude

claude Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found. The prior finding (hang in piped stdin when awaiting_approval) is fixed in commit 632dca0ddresolveApprovals now fails loudly instead of hanging when no interactive terminal is available.

@dawsontoth dawsontoth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of AI comments to resolve. We can work through the list of features of harper-agent vs the advantages we are moving toward here to see what gaps that are.

@kriszyp

kriszyp commented Jul 9, 2026

Copy link
Copy Markdown
Member Author

Lots of AI comments to resolve. We can work through the list of features of harper-agent vs the advantages we are moving toward here to see what gaps that are.

One thing I should have made more clear: This is really not intended to replace harper-agent despite having many of the same letters. This really was just thrown together to make it easier for me (or others) to test out the built-in agent. My intention, at least, is that the built-in agent would almost always serve as a subagent, sometimes to harper-agent, claude desktop, or whatever client the user actually prefers. I also could name or alias this as harper chat or something to make the distinction more clear. While it is possible to directly chat with the built-in agent, it doesn't seem all that desirable to leave behind all your memories and favorite UIs.

- pollUntilIdle: emit raw --json session only on pause/terminal, not every poll
- resolveApprovals: fail loudly instead of hanging when no TTY/piped stdin
- resolveConnection: avoid double :port and undefined credential interpolation
- repl: resolve pending prompt on Ctrl-D/EOF so the loop unwinds
- renderDelta/resolveApprovals: guard null session messages/approvals

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@heskew

heskew commented Jul 11, 2026

Copy link
Copy Markdown
Member

CI triage on the two red checks — neither looks caused by this PR:

  • Unit Test (Node 24) (run 29056777030): getRecordCount › returns the exact count when the loop completes within the time budget failed 29 == 30. The same head passed the Node 22 and Node 26 legs. The test seeds 30 rows but awaits only the last put(), so it can race write visibility — and recent main runs show the unit suite failing one arbitrary test per run (a different one each time), i.e. a background flake rate, not this change.
  • Integration 1/6 (Node 24) (run 29056777016): bulk conditional mutation [rocksdb] died to HarperStartupError: Harper produced no startup output for 60000ms — one hung instance out of ~30 that started fine in the same job. The same shard passed on Node 22/26/Bun/Windows for this head, and the identical startup hang appears on a main run (29152500778, 2026-07-11) killing a different suite.

The PR's only reachable runtime change is the harper agent dispatch case, which neither suite invokes. A re-run of the two failed jobs should go green.

🤖 Posted by Claude on behalf of @heskew

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants