@harnessforce/cli 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +39 -11
  2. package/dist/bin.js +824 -465
  3. package/package.json +5 -5
package/README.md CHANGED
@@ -31,10 +31,14 @@ harnessforce init
31
31
  | `harnessforce otel-headers` | Prints the `Authorization` header for Claude Code's `otelHeadersHelper`. Exits 3 when there is no key, 4 when the destination differs from the pinned origin, 5 while the CLI version is unsupported, and 1 on other failures. On Linux, after printing a key read from the kernel keyring, it moves that Workspace's items to an unlocked Secret Service (not when the hook starts it), so a reboot does not lose them |
32
32
  | `harnessforce run --issue <identifier> -- <agent> [args]` | Launches an agent with its session linked to an Issue |
33
33
  | `harnessforce import` | Sends the metadata of past Claude Code sessions in connected repositories |
34
+ | `harnessforce status [--json]` | Shows the connected Workspace, your role, the setup steps that remain with their URLs, and whether the `origin` repository of the current directory is connected to the GitHub App. Reads only; the remote URL is compared on this machine and never sent. Exits 0 whenever the status was read |
34
35
  | `harnessforce tune [--all] [--no-send] [--show-report] [--json]` | Analyzes past sessions on this machine by public rules and sends the counts (analysis reports) |
36
+ | `harnessforce tune --report-only [--all]` | Analyzes and sends like `harnessforce tune`, but writes nothing to stdout. Meant for your OS scheduler |
37
+ | `harnessforce tune --print-schedule` | Prints one cron line that runs `harnessforce tune --report-only` every Monday at 9:00 local time. Changes nothing and makes no network request |
35
38
  | `harnessforce tune record` / `harnessforce tune --purge` | Records a proposal from stdin / deletes everything under `~/.harnessforce/tune/` |
36
39
  | `harnessforce top [--once] [--json] [--ascii] [--theme <auto\|light\|dark\|ansi>]` | Shows the Claude Code and Codex sessions on this machine in the terminal: state, tokens, context and tool failures. Reads only local files and never connects to Harnessforce |
37
40
  | `harnessforce hook session-start` | The entry of Codex's `SessionStart` hook: reads `session_id`, `cwd` and `source` from stdin, registers the session, and prints the session ID for the agent's context. Always exits 0 |
41
+ | `harnessforce hook post-tool-use` / `stop` | The entries of Codex's `PostToolUse` (`apply_patch`) and `Stop` hooks: record the repository and branch of the working trees the session works in, and send them at the end of a turn in which they changed. Always exit 0 |
38
42
  | `harnessforce --version` | Prints the version |
39
43
 
40
44
  ## Watching your sessions (`harnessforce top`)
@@ -62,6 +66,20 @@ no context percentage.
62
66
  - `~/.harnessforce/config.json` may set `{"top": {"ambiguous_width": 2, "braille": true}}`. An unreadable file or a
63
67
  value out of range falls back to the defaults and says so; the file is never written.
64
68
 
69
+ ## Codex work location hooks (`harnessforce hook post-tool-use` and `stop`)
70
+
71
+ Codex has no event for a change of the working directory, so these hooks record the repository and branch
72
+ of the working tree of each file named in an `apply_patch` patch (`*** Add File:`, `*** Update File:`,
73
+ `*** Delete File:` and `*** Move to:` lines; relative paths are resolved from `cwd`) and of `cwd` at the end
74
+ of each turn. At `Stop`, when the pairs differ from the pairs sent last, they are sent to
75
+ `/v1/sessions/locations` with the same destination and key as the `SessionStart` hook. Only the agent, the
76
+ session ID and up to 10 pairs of repository and branch are sent; paths, commits, file names and the content
77
+ of patches are not. Codex gives hooks no scratchpad, so the record is kept in
78
+ `<temporary directory>/harnessforce-locations/codex-<session_id>.json`; on macOS and Linux the directory
79
+ must be owned by you with mode `0700`, or nothing is recorded. `stop` always prints `{}`, and both always
80
+ exit 0. A machine set up with an earlier `harnessforce init` gets these hooks when you run it again and
81
+ trust them in `/hooks`.
82
+
65
83
  ## Codex `SessionStart` hook (`harnessforce hook session-start`)
66
84
 
67
85
  Codex runs this command through the `[[hooks.SessionStart]]` entry that `harnessforce init` writes into Codex's
@@ -82,10 +100,13 @@ Codex runs this command through the `[[hooks.SessionStart]]` entry that `harness
82
100
  ## What is never sent
83
101
 
84
102
  Harnessforce never turns on prompt or body logging by itself. `harnessforce run` never turns it on, and `harnessforce init`
85
- adds `OTEL_LOG_USER_PROMPTS=1` to the Claude Code user settings only with `--send-content`, and only
86
- when the credentials response says the Workspace has opted in to content. Without that, prompts,
87
- responses, tool inputs and outputs, and file contents are not sent. For a Workspace that has not opted
88
- in, `harnessforce init --send-content` leaves the setting alone, prints the reason, and still exits 0. `harnessforce run`
103
+ sets `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_ASSISTANT_RESPONSES`, `OTEL_LOG_TOOL_DETAILS` and
104
+ `OTEL_LOG_TOOL_CONTENT` in the Claude Code user settings to `1` only with `--send-content`, and only for
105
+ the categories the Workspace stores (prompts, and model responses with tool input and output). Without that,
106
+ `harnessforce init` writes all four as `0` (and Codex's `log_user_prompt` and `log_agent_responses` as
107
+ `false`), so a value left from an earlier run cannot keep sending. `OTEL_LOG_RAW_API_BODIES` is never written.
108
+ For a Workspace that stores no content, `harnessforce init --send-content` writes `0`, prints the reason, and
109
+ still exits 0. `harnessforce import` never sends content. `harnessforce run`
89
110
  never puts the user key or the API token in the agent's environment, arguments or settings. Keys and
90
111
  tokens are sent only to the origins pinned by `harnessforce init`.
91
112
 
@@ -120,26 +141,30 @@ tokens are sent only to the origins pinned by `harnessforce init`.
120
141
  5. It updates the Claude Code user settings (`~/.claude/settings.json`, or `$CLAUDE_CONFIG_DIR`),
121
142
  changing only these keys:
122
143
  - `env`: the OTel exporter variables, `HARNESSFORCE_URL`, `HARNESSFORCE_ENDPOINT` and
123
- `HARNESSFORCE_WORKSPACE_ID`, but no key. With `--send-content` and a Workspace that has opted in
124
- to content it also adds `OTEL_LOG_USER_PROMPTS=1`
144
+ `HARNESSFORCE_WORKSPACE_ID`, but no key, and the four `OTEL_LOG_*` content variables: `1` for a category
145
+ you send with `--send-content` and the Workspace stores, `0` otherwise
125
146
  - `otelHeadersHelper`: `harnessforce otel-headers`
126
147
  - `enabledPlugins["harnessforce@harnessforce-agent"]`
127
148
  - `extraKnownMarketplaces["harnessforce-agent"]` (or `additionalMarketplaces` when only that alias is
128
149
  present): the GitHub source and `autoUpdate: true`, so Claude Code updates the plugin in the
129
150
  background. `--no-plugin-auto-update` writes `false`; a value you set yourself is kept.
130
151
  6. It updates the Codex `config.toml` (`$CODEX_HOME` when it is an absolute path, otherwise `~/.codex`),
131
- changing only these three items and keeping every other key and comment:
152
+ changing only these items and keeping every other key and comment:
132
153
  - `[otel].exporter`: OTLP/HTTP (`protocol = "binary"`) to the ingest endpoint with
133
154
  `Authorization = "Bearer <user ingest key>"`. Codex cannot take the header from a command or expand
134
155
  `${VAR}`, so this is the one place a key is written to a plain file. It is the user ingest key only
135
- (never the API token), and you can revoke it on the Workspace's send keys page. With `--send-content`
136
- and a Workspace that has opted in to content it also sets `log_user_prompt = true`
156
+ (never the API token), and you can revoke it on the Workspace's send keys page. `log_user_prompt` and
157
+ `log_agent_responses` are set to `true` for a category you send with `--send-content` and the
158
+ Workspace stores, and `false` otherwise
137
159
  - `[[hooks.SessionStart]]`: a handler that runs `harnessforce hook session-start`
160
+ - `[[hooks.PostToolUse]]`: a handler with `matcher = "^apply_patch$"` that runs `harnessforce hook post-tool-use`
161
+ asynchronously
162
+ - `[[hooks.Stop]]`: a handler that runs `harnessforce hook stop` asynchronously
138
163
  - `[mcp_servers.harnessforce]`: `url = "<base URL>/mcp"`
139
164
 
140
165
  The file is written through a temporary file in the same directory and renamed into place, with mode
141
- `0600`. Running `harnessforce init` again replaces only these three items. Restart Codex afterwards,
142
- trust the hook with `/hooks` (Codex runs an untrusted hook only after you review it), and run
166
+ `0600`. Running `harnessforce init` again replaces only these items. Restart Codex afterwards,
167
+ trust the three hooks with `/hooks` (Codex runs an untrusted hook only after you review it), and run
143
168
  `codex mcp login harnessforce` to use the MCP server.
144
169
 
145
170
  `harnessforce otel-headers` prints `{"Authorization":"Bearer <key>"}`. The key is `HARNESSFORCE_INGEST_KEY` from
@@ -273,6 +298,9 @@ role cannot use it.
273
298
  - `--json` also lists, for each recorded proposal whose application was detected, the value of its
274
299
  category in the 14 days before and after the detection time (`followups`). The difference is not
275
300
  a cause. Once a `--json` run outputs a follow-up whose after period has ended, later runs omit it.
301
+ - To send weekly without opening Claude Code, add the line that `harnessforce tune --print-schedule`
302
+ prints to your crontab yourself. Harnessforce never registers it. To stop, remove the line or set
303
+ `send_report` to `false`.
276
304
  - Everything it keeps is under `~/.harnessforce/tune/`; `harnessforce tune --purge` deletes it.
277
305
 
278
306
  ## License