@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.
- package/README.md +39 -11
- package/dist/bin.js +824 -465
- 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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
124
|
-
|
|
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
|
|
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.
|
|
136
|
-
|
|
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
|
|
142
|
-
trust the
|
|
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
|