@harnessforce/cli 0.2.0 → 0.3.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.
- package/README.md +33 -11
- package/dist/bin.js +618 -443
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -35,6 +35,7 @@ harnessforce init
|
|
|
35
35
|
| `harnessforce tune record` / `harnessforce tune --purge` | Records a proposal from stdin / deletes everything under `~/.harnessforce/tune/` |
|
|
36
36
|
| `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
37
|
| `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 |
|
|
38
|
+
| `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
39
|
| `harnessforce --version` | Prints the version |
|
|
39
40
|
|
|
40
41
|
## Watching your sessions (`harnessforce top`)
|
|
@@ -62,6 +63,20 @@ no context percentage.
|
|
|
62
63
|
- `~/.harnessforce/config.json` may set `{"top": {"ambiguous_width": 2, "braille": true}}`. An unreadable file or a
|
|
63
64
|
value out of range falls back to the defaults and says so; the file is never written.
|
|
64
65
|
|
|
66
|
+
## Codex work location hooks (`harnessforce hook post-tool-use` and `stop`)
|
|
67
|
+
|
|
68
|
+
Codex has no event for a change of the working directory, so these hooks record the repository and branch
|
|
69
|
+
of the working tree of each file named in an `apply_patch` patch (`*** Add File:`, `*** Update File:`,
|
|
70
|
+
`*** Delete File:` and `*** Move to:` lines; relative paths are resolved from `cwd`) and of `cwd` at the end
|
|
71
|
+
of each turn. At `Stop`, when the pairs differ from the pairs sent last, they are sent to
|
|
72
|
+
`/v1/sessions/locations` with the same destination and key as the `SessionStart` hook. Only the agent, the
|
|
73
|
+
session ID and up to 10 pairs of repository and branch are sent; paths, commits, file names and the content
|
|
74
|
+
of patches are not. Codex gives hooks no scratchpad, so the record is kept in
|
|
75
|
+
`<temporary directory>/harnessforce-locations/codex-<session_id>.json`; on macOS and Linux the directory
|
|
76
|
+
must be owned by you with mode `0700`, or nothing is recorded. `stop` always prints `{}`, and both always
|
|
77
|
+
exit 0. A machine set up with an earlier `harnessforce init` gets these hooks when you run it again and
|
|
78
|
+
trust them in `/hooks`.
|
|
79
|
+
|
|
65
80
|
## Codex `SessionStart` hook (`harnessforce hook session-start`)
|
|
66
81
|
|
|
67
82
|
Codex runs this command through the `[[hooks.SessionStart]]` entry that `harnessforce init` writes into Codex's
|
|
@@ -82,10 +97,13 @@ Codex runs this command through the `[[hooks.SessionStart]]` entry that `harness
|
|
|
82
97
|
## What is never sent
|
|
83
98
|
|
|
84
99
|
Harnessforce never turns on prompt or body logging by itself. `harnessforce run` never turns it on, and `harnessforce init`
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
100
|
+
sets `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_ASSISTANT_RESPONSES`, `OTEL_LOG_TOOL_DETAILS` and
|
|
101
|
+
`OTEL_LOG_TOOL_CONTENT` in the Claude Code user settings to `1` only with `--send-content`, and only for
|
|
102
|
+
the categories the Workspace stores (prompts, and model responses with tool input and output). Without that,
|
|
103
|
+
`harnessforce init` writes all four as `0` (and Codex's `log_user_prompt` and `log_agent_responses` as
|
|
104
|
+
`false`), so a value left from an earlier run cannot keep sending. `OTEL_LOG_RAW_API_BODIES` is never written.
|
|
105
|
+
For a Workspace that stores no content, `harnessforce init --send-content` writes `0`, prints the reason, and
|
|
106
|
+
still exits 0. `harnessforce import` never sends content. `harnessforce run`
|
|
89
107
|
never puts the user key or the API token in the agent's environment, arguments or settings. Keys and
|
|
90
108
|
tokens are sent only to the origins pinned by `harnessforce init`.
|
|
91
109
|
|
|
@@ -120,26 +138,30 @@ tokens are sent only to the origins pinned by `harnessforce init`.
|
|
|
120
138
|
5. It updates the Claude Code user settings (`~/.claude/settings.json`, or `$CLAUDE_CONFIG_DIR`),
|
|
121
139
|
changing only these keys:
|
|
122
140
|
- `env`: the OTel exporter variables, `HARNESSFORCE_URL`, `HARNESSFORCE_ENDPOINT` and
|
|
123
|
-
`HARNESSFORCE_WORKSPACE_ID`, but no key
|
|
124
|
-
|
|
141
|
+
`HARNESSFORCE_WORKSPACE_ID`, but no key, and the four `OTEL_LOG_*` content variables: `1` for a category
|
|
142
|
+
you send with `--send-content` and the Workspace stores, `0` otherwise
|
|
125
143
|
- `otelHeadersHelper`: `harnessforce otel-headers`
|
|
126
144
|
- `enabledPlugins["harnessforce@harnessforce-agent"]`
|
|
127
145
|
- `extraKnownMarketplaces["harnessforce-agent"]` (or `additionalMarketplaces` when only that alias is
|
|
128
146
|
present): the GitHub source and `autoUpdate: true`, so Claude Code updates the plugin in the
|
|
129
147
|
background. `--no-plugin-auto-update` writes `false`; a value you set yourself is kept.
|
|
130
148
|
6. It updates the Codex `config.toml` (`$CODEX_HOME` when it is an absolute path, otherwise `~/.codex`),
|
|
131
|
-
changing only these
|
|
149
|
+
changing only these items and keeping every other key and comment:
|
|
132
150
|
- `[otel].exporter`: OTLP/HTTP (`protocol = "binary"`) to the ingest endpoint with
|
|
133
151
|
`Authorization = "Bearer <user ingest key>"`. Codex cannot take the header from a command or expand
|
|
134
152
|
`${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.
|
|
136
|
-
|
|
153
|
+
(never the API token), and you can revoke it on the Workspace's send keys page. `log_user_prompt` and
|
|
154
|
+
`log_agent_responses` are set to `true` for a category you send with `--send-content` and the
|
|
155
|
+
Workspace stores, and `false` otherwise
|
|
137
156
|
- `[[hooks.SessionStart]]`: a handler that runs `harnessforce hook session-start`
|
|
157
|
+
- `[[hooks.PostToolUse]]`: a handler with `matcher = "^apply_patch$"` that runs `harnessforce hook post-tool-use`
|
|
158
|
+
asynchronously
|
|
159
|
+
- `[[hooks.Stop]]`: a handler that runs `harnessforce hook stop` asynchronously
|
|
138
160
|
- `[mcp_servers.harnessforce]`: `url = "<base URL>/mcp"`
|
|
139
161
|
|
|
140
162
|
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
|
|
142
|
-
trust the
|
|
163
|
+
`0600`. Running `harnessforce init` again replaces only these items. Restart Codex afterwards,
|
|
164
|
+
trust the three hooks with `/hooks` (Codex runs an untrusted hook only after you review it), and run
|
|
143
165
|
`codex mcp login harnessforce` to use the MCP server.
|
|
144
166
|
|
|
145
167
|
`harnessforce otel-headers` prints `{"Authorization":"Bearer <key>"}`. The key is `HARNESSFORCE_INGEST_KEY` from
|