Skip to content

feat(cli): add happy droid command (ACP alias)#835

Open
apoorvgarg31 wants to merge 2 commits intoslopus:mainfrom
apoorvgarg31:feat/add-droid-command
Open

feat(cli): add happy droid command (ACP alias)#835
apoorvgarg31 wants to merge 2 commits intoslopus:mainfrom
apoorvgarg31:feat/add-droid-command

Conversation

@apoorvgarg31
Copy link

@apoorvgarg31 apoorvgarg31 commented Mar 9, 2026

Summary

  • add top-level happy droid subcommand
  • wire it as an ACP alias (equivalent to happy acp droid)
  • auto-start daemon/auth flow same as other agent commands
  • update CLI help text and README command lists

Why

Users expect symmetry with happy, happy codex, and happy gemini. This adds first-class command ergonomics for Droid without changing ACP internals.

Notes

  • This assumes droid is available in PATH and ACP-compatible.
  • Could not run local typecheck/tests in this environment because repo toolchain binaries (yarn, tsc) are unavailable.

Validation

  • ✅ corepack yarn install
  • ✅ cd packages/happy-cli && corepack yarn build
  • ✅ cd packages/happy-cli && corepack yarn typecheck
  • ✅ cd packages/happy-cli && corepack yarn vitest run src/agent/acp/acpAgentConfig.test.ts
  • ⚠️ cd packages/happy-cli && corepack yarn test → 1 unrelated failing test in this environment: src/agent/acp/runAcp.test.ts (verbose logging line formatting expectation)

@apoorvgarg31 apoorvgarg31 changed the title feat(cli): add command (ACP alias) feat(cli): add happy droid command (ACP alias) Mar 9, 2026
@apoorvgarg31
Copy link
Author

Ran contributing-guidelines checks in this branch:\n\n- ✅ yarn install v1.22.22
[1/4] Resolving packages...
success Already up-to-date.
$ node ./scripts/postinstall.cjs
yarn workspace v1.22.22
yarn run v1.22.22
$ shx rm -rf dist && npx tsc --noEmit && pkgroll
Done in 3.05s.
Done in 3.20s.
Done in 3.66s.\n- ✅ yarn run v1.22.22
$ shx rm -rf dist && npx tsc --noEmit && pkgroll
Done in 6.71s.\n- ✅ yarn run v1.22.22
$ tsc --noEmit
Done in 4.42s.\n- ✅ yarn run v1.22.22
$ /tmp/happy/node_modules/.bin/vitest run src/agent/acp/acpAgentConfig.test.ts

RUN v3.2.4 /tmp/happy/packages/happy-cli

Build stdout: $ shx rm -rf dist && npx tsc --noEmit && pkgroll

✓ src/agent/acp/acpAgentConfig.test.ts (8 tests) 5ms

Test Files 1 passed (1)
Tests 8 passed (8)
Start at 18:46:01
Duration 9.17s (transform 43ms, setup 0ms, collect 28ms, tests 5ms, environment 0ms, prepare 110ms)

Done in 9.57s.\n- ⚠️ yarn run v1.22.22
$ $npm_execpath run build && vitest run
$ shx rm -rf dist && npx tsc --noEmit && pkgroll

RUN v3.2.4 /tmp/happy/packages/happy-cli

Build stdout: $ shx rm -rf dist && npx tsc --noEmit && pkgroll

stdout | src/claude/utils/claudeCheckSession.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

stdout | src/utils/MessageQueue2.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

stdout | src/claude/utils/claudeFindLastSession.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

stdout | src/claude/utils/claudeSettings.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

✓ src/claude/claudeLocal.test.ts (10 tests) 64ms
✓ src/modules/difftastic/index.test.ts (5 tests) 96ms
stdout | src/claude/utils/sessionScanner.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

✓ src/claude/utils/claudeSettings.test.ts (7 tests) 85ms
✓ src/claude/utils/claudeCheckSession.test.ts (17 tests) 130ms
✓ src/modules/ripgrep/index.test.ts (5 tests) 335ms
✓ src/claude/utils/claudeFindLastSession.test.ts (14 tests) 302ms
✓ src/api/apiSession.test.ts (22 tests) 157ms
✓ src/utils/deterministicJson.test.ts (16 tests) 69ms
✓ src/agent/acp/AcpSessionManager.test.ts (27 tests) 105ms
✓ src/utils/MessageQueue2.test.ts (18 tests) 660ms
✓ src/sessionProtocol/types.test.ts (9 tests) 36ms
✓ src/claude/utils/sessionProtocolMapper.test.ts (10 tests) 48ms
✓ src/codex/tests/sessionProtocolMapper.test.ts (9 tests) 45ms
✓ src/utils/PushableAsyncIterable.test.ts (8 tests) 46ms
❯ src/agent/acp/runAcp.test.ts (9 tests | 1 failed) 770ms
✓ runAcp > wires backend messages through mapper into session envelopes 120ms
✓ runAcp > registers abort handler that cancels the ACP backend session 54ms
✓ runAcp > emits thinking messages in default mode 116ms
✓ runAcp > emits raw backend and envelope logs when verbose is enabled 107ms
× runAcp > logs slash commands, modes, and models line by line when verbose is enabled 90ms
→ expected [ Array(18) ] to deeply equal ArrayContaining{…}
✓ runAcp > exits when backend reports terminal startup status 3ms
✓ runAcp > updates session metadata with ACP config options (models and operating modes) 58ms
✓ runAcp > switches ACP model and permission mode when requested values match config options 108ms
✓ runAcp > ignores ACP model and permission mode requests when values do not match advertised options 110ms
stdout | src/commands/sandbox.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

stdout | src/commands/sandbox.test.ts > handleSandboxCommand > routes configure subcommand

Sandbox configuration summary:
{
"enabled": true,
"workspaceRoot": "/Developer",
"sessionIsolation": "workspace",
"customWritePaths": [],
"denyReadPaths": [
"
/.ssh",
"/.aws",
"
/.gnupg"
],
"extraWritePaths": [
"/tmp"
],
"denyWritePaths": [
".env"
],
"networkMode": "allowed",
"allowedDomains": [],
"deniedDomains": [],
"allowLocalBinding": true
}

stdout | src/commands/sandbox.test.ts > handleSandboxCommand > routes configure subcommand
Sandbox configuration cancelled.

✓ src/commands/sandbox.test.ts (8 tests) 30ms
stdout | src/utils/tmux.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

✓ src/utils/expandEnvVars.test.ts (17 tests) 23ms
✓ src/claude/utils/sessionScanner.test.ts (2 tests) 1296ms
✓ sessionScanner > should process initial session and resumed session correctly 1286ms
✓ src/utils/tmux.test.ts (51 tests) 40ms
✓ src/utils/hmac_sha512.test.ts (1 test) 15ms
stdout | src/ui/qrcode.test.ts > QR Code Utility > should render a small QR code without throwing

📱 To authenticate, scan this QR code with your mobile device:

      ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
      █ ▄▄▄▄▄ █▀▄█▀▄█ ▄▄▄▄▄ █
      █ █   █ █▀▄█▀██ █   █ █
      █ █▄▄▄█ █▀▀ ▄ █ █▄▄▄█ █
      █▄▄▄▄▄▄▄█▄█ ▀ █▄▄▄▄▄▄▄█
      █ ▄▄▄ ▀▄ ▄▄▀█  ▀ ▀▄▀▄▀█
      █▀ ▀█▄ ▄▄▄▀▀▄█ ▄▄▀  ▄██
      █▄█▄█▄▄▄▄ ▀▄▄▀ ▄▀ ▀██ █
      █ ▄▄▄▄▄ █▄  █ ▀█ ▀▀▀▄██
      █ █   █ █  █ ▄▀▄▄ ▀▀▄▄█
      █ █▄▄▄█ █ ▄▀ ▄ █▄█▀ ███
      █▄▄▄▄▄▄▄█▄▄▄█▄▄▄▄▄▄█▄██

================================================================================

✓ src/ui/qrcode.test.ts (1 test) 44ms
✓ src/claude/utils/permissionMode.test.ts (17 tests) 35ms
✓ src/codex/tests/codexMcpClient.test.ts (4 tests) 36ms
✓ src/claude/utils/path.test.ts (19 tests) 31ms
✓ src/api/api.test.ts (9 tests) 39ms
✓ src/sandbox/config.test.ts (7 tests) 8ms
✓ src/utils/createSessionMetadata.test.ts (5 tests) 6ms
✓ src/agent/acp/sessionConfigMetadata.test.ts (4 tests) 16ms
✓ src/utils/tests/runtimeIntegration.test.ts (4 tests) 30ms
✓ src/codex/tests/executionPolicy.test.ts (3 tests) 6ms
✓ src/modules/common/pathSecurity.test.ts (4 tests) 8ms
stdout | src/persistence.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

✓ src/parsers/specialCommands.test.ts (12 tests) 13ms
✓ src/persistence.test.ts (4 tests) 19ms
✓ src/claude/utils/sdkToLogConverter.test.ts (16 tests) 32ms
✓ src/utils/tests/runtime.test.ts (6 tests) 13ms
✓ src/utils/sandboxFlags.test.ts (2 tests) 12ms
✓ src/sandbox/manager.test.ts (4 tests) 17ms
✓ src/agent/acp/acpAgentConfig.test.ts (8 tests) 17ms
stdout | src/daemon/daemon.integration.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

stdout | src/daemon/daemon.integration.test.ts
[TEST] Server not reachable: TypeError: fetch failed
�[90m at node:internal/deps/undici/undici:14902:13�[39m
�[90m at processTicksAndRejections (node:internal/process/task_queues:105:5)�[39m
at isServerHealthy �[90m(/tmp/happy/packages/happy-cli/�[39msrc/daemon/daemon.integration.test.ts:53:22�[90m)�[39m
at �[90m/tmp/happy/packages/happy-cli/�[39msrc/daemon/daemon.integration.test.ts:76:18
at VitestExecutor.runModule (file:///tmp/happy/node_modules/�[4mvite-node�[24m/dist/client.mjs:397:4)
at VitestExecutor.directRequest (file:///tmp/happy/node_modules/�[4mvite-node�[24m/dist/client.mjs:375:3)
at VitestExecutor.cachedRequest (file:///tmp/happy/node_modules/�[4mvite-node�[24m/dist/client.mjs:189:11)
at VitestExecutor.executeId (file:///tmp/happy/node_modules/�[4mvite-node�[24m/dist/client.mjs:166:10)
at collectTests (file:///tmp/happy/node_modules/�[4m@vitest/runner�[24m/dist/chunk-hooks.js:1174:4)
at startTests (file:///tmp/happy/node_modules/�[4m@vitest/runner�[24m/dist/chunk-hooks.js:1817:17) {
[cause]: Error: connect ECONNREFUSED 127.0.0.1:3005
�[90m at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1637:16)�[39m {
errno: �[33m-111�[39m,
code: �[32m'ECONNREFUSED'�[39m,
syscall: �[32m'connect'�[39m,
address: �[32m'127.0.0.1'�[39m,
port: �[33m3005�[39m
}
}

↓ src/daemon/daemon.integration.test.ts (12 tests | 12 skipped)
↓ src/sandbox/network.integration.test.ts (1 test | 1 skipped)
stdout | src/codex/tests/emitReadyIfIdle.test.ts
[REMOTE LOGGING] Sending logs to server for AI debugging

✓ src/codex/tests/emitReadyIfIdle.test.ts (4 tests) 3ms
✓ src/utils/serverConnectionErrors.test.ts (28 tests) 64700ms
✓ startOfflineReconnection > successful reconnection > should only reconnect once (idempotent) 305ms
✓ startOfflineReconnection > retry behavior > should retry when health check fails then succeeds 4520ms
✓ startOfflineReconnection > retry behavior > should retry when onReconnected throws 6832ms
✓ startOfflineReconnection > retry behavior > should increment failure count on each retry 11758ms
✓ startOfflineReconnection > cancellation > should prevent reconnection if cancelled before first attempt 602ms
✓ startOfflineReconnection > error handling > should stop retrying on 401 authentication error 302ms
✓ startOfflineReconnection > error handling > should retry on 500 server error 9648ms
✓ startOfflineReconnection > error handling > should retry on 503 service unavailable 7829ms
✓ startOfflineReconnection > error handling > should retry on non-axios network errors 2614ms
✓ startOfflineReconnection > error handling > should retry on ETIMEDOUT errors 9651ms
✓ startOfflineReconnection > error handling > should NOT stop retrying on 403 forbidden (not auth failure) 9550ms

Test Files 1 failed | 39 passed | 2 skipped (42)
Tests 1 failed | 425 passed | 13 skipped (439)
Start at 18:46:20
Duration 74.77s (transform 3.80s, setup 0ms, collect 11.18s, tests 69.44s, environment 19ms, prepare 9.06s)

info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command. currently has 1 unrelated failing test in this environment: \n\nAlso added follow-up commit to register in + updated unit expectation for that map.

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.

1 participant