kankaku-claude 0.12.0 → 1.0.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/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +15 -0
- package/README.md +7 -7
- package/dist/auto-sync.js +1 -1
- package/dist/cli-core.js +1 -1
- package/dist/cost-store.js +3 -2
- package/dist/doctor.js +1 -1
- package/dist/handle-hook.js +4 -4
- package/dist/paths.js +1 -1
- package/dist/record.js +1 -1
- package/dist/replay.js +3 -3
- package/dist/report.js +1 -1
- package/dist/sync-cli.js +2 -2
- package/dist/task-cli.js +1 -1
- package/dist/task-select.js +1 -1
- package/dist/work-target.js +2 -2
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kankaku",
|
|
3
3
|
"description": "Records how long Claude Code works on each of your prompts: wall time, waiting time, work time and cost, per prompt, in kankaku's worklog format.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "soyunninja"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,21 @@ All notable changes to this project are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
6
|
|
|
7
|
+
## 1.0.0 — 2026-09-29
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- The library dependency is renamed from `kankaku` to `kankaku-pi`, and
|
|
12
|
+
its entry points are imported as `kankaku-pi/domain`, `kankaku-pi/ports`
|
|
13
|
+
and `kankaku-pi/hub`. The package keeps its own name, `kankaku-claude`
|
|
14
|
+
(directory unchanged). No behaviour change.
|
|
15
|
+
- `kankaku-claude sync` usage text names `dist/cli.js`, and comments no
|
|
16
|
+
longer point at files that are not in the repository.
|
|
17
|
+
|
|
18
|
+
## 0.12.1 — 2026-09-29
|
|
19
|
+
|
|
20
|
+
No changes in this package; released in lockstep with kankaku 0.12.1.
|
|
21
|
+
|
|
7
22
|
## 0.12.0 — 2026-09-29
|
|
8
23
|
|
|
9
24
|
### Added
|
package/README.md
CHANGED
|
@@ -40,27 +40,27 @@ no identity and are labelled by whichever tool syncs them first.
|
|
|
40
40
|
a `.ts` file once it sits under a `node_modules` directory
|
|
41
41
|
(`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`), so every published
|
|
42
42
|
hook/statusline/CLI command runs the built `dist/*.js` file, never the
|
|
43
|
-
`.ts` source. Installed via `kankaku
|
|
43
|
+
`.ts` source. Installed via `kankaku` (below) this needs no action
|
|
44
44
|
from you; a manual `--plugin-dir` checkout must run `npm install && npm
|
|
45
45
|
run build` once before Claude Code can load it (see "Manual/dev"
|
|
46
46
|
below).
|
|
47
47
|
|
|
48
48
|
## Install
|
|
49
49
|
|
|
50
|
-
**Recommended: `kankaku
|
|
51
|
-
`kankaku
|
|
50
|
+
**Recommended: `kankaku`'s setup wizard.** This package lives inside
|
|
51
|
+
`kankaku`'s own dependency tree, so installing and running its setup
|
|
52
52
|
wizard configures Claude Code for you — statusline and hooks together, in
|
|
53
53
|
one step, with no checkout and no `--plugin-dir`:
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
npm i -g kankaku
|
|
56
|
+
npm i -g kankaku
|
|
57
57
|
kankaku setup
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
Checking Claude Code in the wizard (or confirming it in `kankaku setup
|
|
61
61
|
--yes`) writes `statusLine` and `hooks` into `~/.claude/settings.json`,
|
|
62
62
|
resolved from this package's own bundled files, merged with — never
|
|
63
|
-
clobbering — whatever else is already there. See `kankaku
|
|
63
|
+
clobbering — whatever else is already there. See `kankaku`'s own
|
|
64
64
|
README ("Claude Code") for the full behaviour, the
|
|
65
65
|
`--claude-plugin-dir`/`KANKAKU_CLAUDE_PLUGIN_DIR` override, and why you
|
|
66
66
|
should drop `--plugin-dir` (below) once this has run.
|
|
@@ -72,7 +72,7 @@ at it directly:
|
|
|
72
72
|
git clone https://github.com/soyunninja/kankaku.git
|
|
73
73
|
cd kankaku/packages/claude
|
|
74
74
|
npm install && npm run build
|
|
75
|
-
claude --plugin-dir
|
|
75
|
+
claude --plugin-dir "$PWD"
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
`npm run build` compiles `src/` into `dist/`; the hooks, statusline and
|
|
@@ -113,7 +113,7 @@ Claude Code plugins cannot set `statusLine` for themselves — there is no
|
|
|
113
113
|
programmatic way for a plugin to add a `statusLine` entry to your settings.
|
|
114
114
|
The statusline is also the *only* documented source of per-prompt cost
|
|
115
115
|
(`cost.total_cost_usd`); hooks never receive it. `kankaku setup` (above)
|
|
116
|
-
writes it for you automatically; without `kankaku
|
|
116
|
+
writes it for you automatically; without `kankaku`, run:
|
|
117
117
|
|
|
118
118
|
```
|
|
119
119
|
/kankaku:setup
|
package/dist/auto-sync.js
CHANGED
|
@@ -3,7 +3,7 @@ export async function autoSync(trigger, deps) {
|
|
|
3
3
|
if (deps.env.KANKAKU_SYNC_AUTO === "0")
|
|
4
4
|
return;
|
|
5
5
|
try {
|
|
6
|
-
const { resolveHubCredentials } = await import("kankaku/hub");
|
|
6
|
+
const { resolveHubCredentials } = await import("kankaku-pi/hub");
|
|
7
7
|
const { homedir } = await import("node:os");
|
|
8
8
|
const hub = resolveHubCredentials({ env: deps.env, homeDir: deps.homeDir ?? (() => deps.env.HOME || homedir()) });
|
|
9
9
|
if (!hub.credentials || hub.invalidReason)
|
package/dist/cli-core.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { basename, join } from "node:path";
|
|
2
|
-
import { JsonlWorkLog } from "kankaku/hub";
|
|
2
|
+
import { JsonlWorkLog } from "kankaku-pi/hub";
|
|
3
3
|
import { listStateFiles, resolveKankakuDir } from "./paths.js";
|
|
4
4
|
import { readState } from "./session-state.js";
|
|
5
5
|
import { readCost } from "./cost-store.js";
|
package/dist/cost-store.js
CHANGED
|
@@ -6,9 +6,10 @@ const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
|
6
6
|
* Cost lives under the HOME directory, never a project: the statusline
|
|
7
7
|
* command is wired globally and runs in every session on the machine, so a
|
|
8
8
|
* project-relative path would litter whatever project happens to be open
|
|
9
|
-
* (the defect this module fixes
|
|
9
|
+
* (the defect this module fixes: cost files were written into whichever
|
|
10
|
+
* project happened to be open).
|
|
10
11
|
* Imports only node builtins so light hooks that read/write cost stay off
|
|
11
|
-
* the `kankaku` import path.
|
|
12
|
+
* the `kankaku-pi` import path.
|
|
12
13
|
*/
|
|
13
14
|
export function costDir(env) {
|
|
14
15
|
const home = env.HOME || homedir();
|
package/dist/doctor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import { JsonlWorkLog, SyncStateStore, computeSyncStatus, resolveHubCredentials } from "kankaku/hub";
|
|
4
|
+
import { JsonlWorkLog, SyncStateStore, computeSyncStatus, resolveHubCredentials } from "kankaku-pi/hub";
|
|
5
5
|
import { costDir } from "./cost-store.js";
|
|
6
6
|
import { listStateFiles, resolveKankakuDir } from "./paths.js";
|
|
7
7
|
import { readState } from "./session-state.js";
|
package/dist/handle-hook.js
CHANGED
|
@@ -10,7 +10,7 @@ const STOP_COST_WAIT_MAX_MS = 1500;
|
|
|
10
10
|
/**
|
|
11
11
|
* Dispatches one Claude Code hook invocation. Light events (everything but
|
|
12
12
|
* Stop/SessionStart/SessionEnd) only append one event line plus a tiny
|
|
13
|
-
* state update, and never import `kankaku` at runtime — the heavier replay/
|
|
13
|
+
* state update, and never import `kankaku-pi` at runtime — the heavier replay/
|
|
14
14
|
* storage layer is loaded with dynamic `import()` only inside the three
|
|
15
15
|
* branches that actually settle or recover a record.
|
|
16
16
|
*/
|
|
@@ -111,7 +111,7 @@ export async function handleHook(input, deps) {
|
|
|
111
111
|
async function handleStop(paths, sessionId, deps) {
|
|
112
112
|
const { replayPrompt } = await import("./replay.js");
|
|
113
113
|
const { buildClaudeRecord } = await import("./record.js");
|
|
114
|
-
const { JsonlWorkLog } = await import("kankaku/hub");
|
|
114
|
+
const { JsonlWorkLog } = await import("kankaku-pi/hub");
|
|
115
115
|
const events = readEventLog(paths.eventsFile);
|
|
116
116
|
const beforeStopTs = events.length >= 2 ? events[events.length - 2].ts : events[events.length - 1]?.ts ?? deps.now();
|
|
117
117
|
const deadline = deps.now() + STOP_COST_WAIT_MAX_MS;
|
|
@@ -149,7 +149,7 @@ async function handleStop(paths, sessionId, deps) {
|
|
|
149
149
|
async function handleSessionStart(paths, sessionId, cwd, source, ts, deps) {
|
|
150
150
|
if (source !== "compact") {
|
|
151
151
|
const { recoverStaleSessions } = await import("./inflight-recovery.js");
|
|
152
|
-
const { JsonlWorkLog } = await import("kankaku/hub");
|
|
152
|
+
const { JsonlWorkLog } = await import("kankaku-pi/hub");
|
|
153
153
|
const recovered = recoverStaleSessions({
|
|
154
154
|
claudeDir: paths.claudeDir,
|
|
155
155
|
currentSessionId: sessionId,
|
|
@@ -189,7 +189,7 @@ async function handleSessionEnd(paths, sessionId, cwd, ts, deps) {
|
|
|
189
189
|
if (state?.promptOpen) {
|
|
190
190
|
const { replayPrompt } = await import("./replay.js");
|
|
191
191
|
const { buildClaudeRecord } = await import("./record.js");
|
|
192
|
-
const { JsonlWorkLog } = await import("kankaku/hub");
|
|
192
|
+
const { JsonlWorkLog } = await import("kankaku-pi/hub");
|
|
193
193
|
const events = readEventLog(paths.eventsFile);
|
|
194
194
|
const prompts = splitPrompts(events);
|
|
195
195
|
const last = prompts[prompts.length - 1];
|
package/dist/paths.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readdirSync } from "node:fs";
|
|
2
2
|
import { isAbsolute, join } from "node:path";
|
|
3
3
|
/**
|
|
4
|
-
* Same rule as
|
|
4
|
+
* Same rule as `resolveKankakuDir` in the `kankaku-pi` hub barrel (`kankaku-pi/hub`): an absolute
|
|
5
5
|
* `KANKAKU_DIR` is used as-is, a relative one is joined against the session's
|
|
6
6
|
* cwd. Inlined rather than imported so the light hooks (one per tool call)
|
|
7
7
|
* never load the hub barrel for a two-line helper.
|
package/dist/record.js
CHANGED
|
@@ -24,7 +24,7 @@ const PLUGIN_VERSION = readPackageVersion(join(dirname(dirname(fileURLToPath(imp
|
|
|
24
24
|
* caller decides which cost snapshot's model applies.
|
|
25
25
|
*
|
|
26
26
|
* Also stamps who MEASURED the record (`agent`, `plugin`, `pluginVersion`),
|
|
27
|
-
* so a worklog later synced by another tool (the kankaku
|
|
27
|
+
* so a worklog later synced by another tool (the `kankaku` CLI) keeps the
|
|
28
28
|
* right identity. `agentVersion` is omitted: Claude Code passes its version
|
|
29
29
|
* to no hook payload, and spawning `claude --version` from a hook is not
|
|
30
30
|
* acceptable.
|
package/dist/replay.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { WorkTracker } from "kankaku/domain";
|
|
1
|
+
import { WorkTracker } from "kankaku-pi/domain";
|
|
2
2
|
/** Tool names whose span counts as waiting rather than working. */
|
|
3
3
|
const INTERACTIVE_TOOLS = ["AskUserQuestion"];
|
|
4
4
|
/**
|
|
5
5
|
* The plugin's own subagent profile: Claude Code's `Agent`/`Task` tool
|
|
6
6
|
* calls open a subagent span, read from `subagent_type`. No join key is
|
|
7
|
-
* offered (`SubagentStart`/`SubagentStop` are recorded but not linked
|
|
8
|
-
*
|
|
7
|
+
* offered (`SubagentStart`/`SubagentStop` are recorded but not linked, so a
|
|
8
|
+
* subagent span is closed by the replay itself).
|
|
9
9
|
*/
|
|
10
10
|
const CLAUDE_CODE_SUBAGENT_PROFILE = {
|
|
11
11
|
id: "claude-code",
|
package/dist/report.js
CHANGED
package/dist/sync-cli.js
CHANGED
|
@@ -2,9 +2,9 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import { homedir, hostname, tmpdir } from "node:os";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { CachedCatalog, JsonlWorkLog, PocketBaseClient, PocketBaseSink, SyncStateStore, computeSyncStatus, createPocketBaseCatalogFetcher, resolveHubCredentials, runSync, safeHomeDir, } from "kankaku/hub";
|
|
5
|
+
import { CachedCatalog, JsonlWorkLog, PocketBaseClient, PocketBaseSink, SyncStateStore, computeSyncStatus, createPocketBaseCatalogFetcher, resolveHubCredentials, runSync, safeHomeDir, } from "kankaku-pi/hub";
|
|
6
6
|
import { resolveKankakuDir } from "./paths.js";
|
|
7
|
-
const usage = "usage: node
|
|
7
|
+
const usage = "usage: node dist/cli.js sync [all|status]\n";
|
|
8
8
|
function windowHours(env) {
|
|
9
9
|
const value = Number(env.KANKAKU_SYNC_WINDOW_HOURS);
|
|
10
10
|
return env.KANKAKU_SYNC_WINDOW_HOURS && Number.isFinite(value) && value > 0 ? value : 24;
|
package/dist/task-cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { CachedCatalog, PocketBaseClient, createPocketBaseCatalogFetcher, resolveHubCredentials } from "kankaku/hub";
|
|
3
|
+
import { CachedCatalog, PocketBaseClient, createPocketBaseCatalogFetcher, resolveHubCredentials } from "kankaku-pi/hub";
|
|
4
4
|
import { findSession } from "./find-session.js";
|
|
5
5
|
import { resolveKankakuDir, resolveTargetFile } from "./paths.js";
|
|
6
6
|
import { readSessionTarget, writeSessionTarget } from "./session-target-store.js";
|
package/dist/task-select.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Pure task selection for `/kankaku:task`. Mirrors pi's picker
|
|
3
3
|
* (`adapters/target-picker.ts#pickHubTask`): a task is pickable when its
|
|
4
4
|
* status is not `done` (the hub's statuses are `open | doing | done`, see
|
|
5
|
-
* `HubTask` in `kankaku/domain`) and it belongs to the resolved project.
|
|
5
|
+
* `HubTask` in `kankaku-pi/domain`) and it belongs to the resolved project.
|
|
6
6
|
*/
|
|
7
7
|
export function isOpenTask(task) {
|
|
8
8
|
return task.status !== "done";
|
package/dist/work-target.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import { CachedCatalog, readProjectClient, readProjectTargetIds, resolveHubCredentials, } from "kankaku/hub";
|
|
4
|
-
import { formatWorkTargetLabel, isValidClient, resolveClient, resolveWorkTarget, resolveWorkTargetSource, } from "kankaku/domain";
|
|
3
|
+
import { CachedCatalog, readProjectClient, readProjectTargetIds, resolveHubCredentials, } from "kankaku-pi/hub";
|
|
4
|
+
import { formatWorkTargetLabel, isValidClient, resolveClient, resolveWorkTarget, resolveWorkTargetSource, } from "kankaku-pi/domain";
|
|
5
5
|
import { findSession } from "./find-session.js";
|
|
6
6
|
import { resolveKankakuDir, resolveTargetFile } from "./paths.js";
|
|
7
7
|
import { readSessionTarget } from "./session-target-store.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kankaku-claude",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Claude Code plugin that records how long the agent works on each user prompt, in kankaku's worklog format.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"prepublishOnly": "npm run check"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"kankaku": "^0.
|
|
30
|
+
"kankaku-pi": "^1.0.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^24.13.4",
|