@procrastivity/clast 0.0.3 → 0.0.5
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 +41 -38
- package/bin/clast +31 -122
- package/bin/clast-plumbing +180 -0
- package/examples/cron/clast-snapshot.service +2 -2
- package/examples/cron/clast-snapshot.timer +1 -1
- package/examples/cron/crontab.sample +4 -4
- package/examples/workflows/morning-briefing.md +17 -17
- package/hooks/snapshot.sh +5 -5
- package/lib/clast/clast-classify-lib.bash +68 -0
- package/lib/clast/clast-dismissed-lib.bash +76 -5
- package/lib/clast/clast-lib.bash +93 -8
- package/lib/clast/clast-manifest-lib.bash +58 -5
- package/lib/clast/clast-porcelain-lib.bash +230 -0
- package/lib/clast/clast-porcelain-subcommands/brief.bash +236 -0
- package/lib/clast/clast-porcelain-subcommands/retro.bash +236 -0
- package/lib/clast/clast-porcelain-subcommands/undismiss.bash +27 -0
- package/lib/clast/clast-porcelain-subcommands/wake.bash +514 -0
- package/lib/clast/clast-registry-lib.bash +164 -41
- package/lib/clast/clast-retro-lib.bash +397 -0
- package/lib/clast/clast-subcommands/doctor.bash +29 -13
- package/lib/clast/clast-subcommands/entries.bash +40 -50
- package/lib/clast/clast-subcommands/projects.bash +16 -20
- package/lib/clast/clast-subcommands/registry.bash +26 -11
- package/lib/clast/clast-subcommands/retro.bash +217 -0
- package/lib/clast/clast-subcommands/sessions.bash +193 -48
- package/lib/clast/clast-subcommands/show.bash +69 -12
- package/lib/clast/clast-subcommands/snapshot.bash +29 -11
- package/lib/clast/clast-subcommands/stats.bash +7 -2
- package/lib/clast/prompts/brief-system.md +11 -5
- package/lib/clast/prompts/brief-user.md +4 -1
- package/lib/clast/prompts/retro-summary-system.md +14 -0
- package/lib/clast/prompts/retro-summary-user.md +7 -0
- package/lib/clast/prompts/{day-wakeup-draft-system.md → wake-draft-system.md} +1 -1
- package/package.json +3 -3
- package/{.claude-plugin/skills/wakeup → skills/brief}/SKILL.md +22 -20
- package/{.claude-plugin/skills/day-wakeup → skills/wake}/SKILL.md +54 -29
- package/bin/clast-brief +0 -305
- package/bin/clast-wake +0 -579
- /package/lib/clast/prompts/{day-wakeup-draft-user.md → wake-draft-user.md} +0 -0
package/README.md
CHANGED
|
@@ -6,27 +6,30 @@ Capture, curate, and surface Claude Code session history across all your project
|
|
|
6
6
|
|
|
7
7
|
## What it does
|
|
8
8
|
|
|
9
|
-
- **CLI**
|
|
10
|
-
-
|
|
9
|
+
- **CLI** — two binaries, porcelain over plumbing:
|
|
10
|
+
- `clast` — porcelain (LLM-aware): `clast wake`, `clast brief`. See [run without Claude Code](./docs/guides/run-without-claude-code.md).
|
|
11
|
+
- `clast-plumbing` — deterministic core: snapshot, browse, and query your Claude Code session JSONL history.
|
|
12
|
+
- **Plugin** — installs skills (`/wake`, `/brief`) that surface recent session context.
|
|
11
13
|
- **SessionStart hook** — quietly snapshots active sessions in the background each time Claude Code starts.
|
|
12
14
|
|
|
13
15
|
## Capture your sessions
|
|
14
16
|
|
|
15
17
|
```sh
|
|
16
|
-
clast snapshot # copy any new sessions into the journal
|
|
17
|
-
clast snapshot --dry-run --json | jq # preview what would be captured
|
|
18
|
+
clast-plumbing snapshot # copy any new sessions into the journal
|
|
19
|
+
clast-plumbing snapshot --dry-run --json | jq # preview what would be captured
|
|
18
20
|
```
|
|
19
21
|
|
|
20
|
-
`clast snapshot` is idempotent and silent on no-op, safe to run from
|
|
21
|
-
a SessionStart hook. See
|
|
22
|
+
`clast-plumbing snapshot` is idempotent and silent on no-op, safe to run from
|
|
23
|
+
cron or a SessionStart hook. See
|
|
24
|
+
[`docs/reference/cli.md#clast-snapshot`](./docs/reference/cli.md#clast-snapshot)
|
|
22
25
|
for the full flag reference.
|
|
23
26
|
|
|
24
27
|
## Read your sessions
|
|
25
28
|
|
|
26
29
|
```sh
|
|
27
|
-
clast projects # which projects had activity today
|
|
28
|
-
clast sessions --since -7d # sessions captured in the last week
|
|
29
|
-
clast show <session-uuid> --full # metadata + first/last turns
|
|
30
|
+
clast-plumbing projects # which projects had activity today
|
|
31
|
+
clast-plumbing sessions --since -7d # sessions captured in the last week
|
|
32
|
+
clast-plumbing show <session-uuid> --full # metadata + first/last turns
|
|
30
33
|
```
|
|
31
34
|
|
|
32
35
|
Window flags (`--day`, `--since`, `--until`) accept ISO dates and
|
|
@@ -39,14 +42,14 @@ for the full flag and output schemas.
|
|
|
39
42
|
## Curate an entry
|
|
40
43
|
|
|
41
44
|
```sh
|
|
42
|
-
clast entries # list curated entries
|
|
43
|
-
clast entries read 2026-05-30-1430-xesapps-foo.md # cat a single entry
|
|
44
|
-
printf 'Notes...\n' | clast entries write \
|
|
45
|
-
--session <session-uuid> --slug short-slug --body-stdin
|
|
45
|
+
clast-plumbing entries # list curated entries
|
|
46
|
+
clast-plumbing entries read 2026-05-30-1430-xesapps-foo.md # cat a single entry
|
|
47
|
+
printf 'Notes...\n' | clast-plumbing entries write \
|
|
48
|
+
--session <session-uuid> --slug short-slug --body-stdin # write a new entry
|
|
46
49
|
```
|
|
47
50
|
|
|
48
|
-
`clast entries write` looks up the session in the manifest, composes
|
|
49
|
-
documented frontmatter from the captured snapshot + registry, and writes
|
|
51
|
+
`clast-plumbing entries write` looks up the session in the manifest, composes
|
|
52
|
+
the documented frontmatter from the captured snapshot + registry, and writes
|
|
50
53
|
`entries/YYYY-MM-DD-HHMM-<project-slug>-<session-slug>.md` atomically. See
|
|
51
54
|
[`docs/reference/cli.md#entry-frontmatter`](./docs/reference/cli.md#entry-frontmatter)
|
|
52
55
|
for the full frontmatter schema and
|
|
@@ -56,31 +59,31 @@ for the flag reference.
|
|
|
56
59
|
## Leave a breadcrumb
|
|
57
60
|
|
|
58
61
|
```sh
|
|
59
|
-
clast breadcrumb --project xesapps 'check migration before deploy'
|
|
60
|
-
clast breadcrumb --global 'remember to bump the cache version'
|
|
62
|
+
clast-plumbing breadcrumb --project xesapps 'check migration before deploy'
|
|
63
|
+
clast-plumbing breadcrumb --global 'remember to bump the cache version'
|
|
61
64
|
|
|
62
|
-
clast breadcrumb --read --project xesapps
|
|
63
|
-
clast breadcrumb --read --global
|
|
65
|
+
clast-plumbing breadcrumb --read --project xesapps
|
|
66
|
+
clast-plumbing breadcrumb --read --global
|
|
64
67
|
```
|
|
65
68
|
|
|
66
|
-
Breadcrumbs are append-only one-line notes for `/
|
|
69
|
+
Breadcrumbs are append-only one-line notes for `/brief` and `/wake`.
|
|
67
70
|
See [`docs/reference/cli.md#clast-breadcrumb`](./docs/reference/cli.md#clast-breadcrumb)
|
|
68
71
|
for the full command contract.
|
|
69
72
|
|
|
70
73
|
## Inspect and audit the journal
|
|
71
74
|
|
|
72
75
|
```sh
|
|
73
|
-
clast stats # one-line activity summary for today
|
|
74
|
-
clast stats --since -7d # rollup over the last week
|
|
76
|
+
clast-plumbing stats # one-line activity summary for today
|
|
77
|
+
clast-plumbing stats --since -7d # rollup over the last week
|
|
75
78
|
|
|
76
|
-
clast doctor # check manifest, registry, snapshots
|
|
77
|
-
clast doctor --fix # rebuild a broken manifest, prune orphans
|
|
79
|
+
clast-plumbing doctor # check manifest, registry, snapshots
|
|
80
|
+
clast-plumbing doctor --fix # rebuild a broken manifest, prune orphans
|
|
78
81
|
```
|
|
79
82
|
|
|
80
83
|
See [`docs/reference/cli.md#clast-stats`](./docs/reference/cli.md#clast-stats)
|
|
81
84
|
and [`docs/reference/cli.md#clast-doctor`](./docs/reference/cli.md#clast-doctor)
|
|
82
|
-
for the contract reference, and `clast stats --help` /
|
|
83
|
-
for the current set of flags.
|
|
85
|
+
for the contract reference, and `clast-plumbing stats --help` /
|
|
86
|
+
`clast-plumbing doctor --help` for the current set of flags.
|
|
84
87
|
|
|
85
88
|
## Install to a prefix
|
|
86
89
|
|
|
@@ -102,9 +105,9 @@ for the rationale.
|
|
|
102
105
|
With Nix flakes enabled, you can use `clast` directly from the public flake:
|
|
103
106
|
|
|
104
107
|
```sh
|
|
105
|
-
nix run github:procrastivity/clast -- whereami
|
|
106
108
|
nix profile install github:procrastivity/clast
|
|
107
|
-
nix build .#default && ./result/bin/clast --version
|
|
109
|
+
nix build .#default && ./result/bin/clast --version # porcelain
|
|
110
|
+
nix build .#default && ./result/bin/clast-plumbing --help # plumbing
|
|
108
111
|
```
|
|
109
112
|
|
|
110
113
|
For Home Manager or nix-darwin users, `overlays.default` exposes `pkgs.clast`.
|
|
@@ -135,27 +138,27 @@ The plugin can be installed from any local checkout, or via `npm install -g`
|
|
|
135
138
|
(which puts `.claude-plugin/` under `npm root -g`); a centralized marketplace
|
|
136
139
|
listing is a separate distribution channel deliberately not pursued for v1.
|
|
137
140
|
Today the plugin ships a single `SessionStart` hook: every time a Claude Code
|
|
138
|
-
session starts it backgrounds `clast snapshot`, so your journal stays
|
|
139
|
-
with zero manual effort. The hook is best-effort and silent: if the
|
|
140
|
-
isn't on your `PATH` yet, sessions still start cleanly. See
|
|
141
|
+
session starts it backgrounds `clast-plumbing snapshot`, so your journal stays
|
|
142
|
+
current with zero manual effort. The hook is best-effort and silent: if the
|
|
143
|
+
`clast-plumbing` CLI isn't on your `PATH` yet, sessions still start cleanly. See
|
|
141
144
|
[`docs/reference/plugin.md#hook-sessionstart`](./docs/reference/plugin.md#hook-sessionstart)
|
|
142
145
|
for the hook's design rationale.
|
|
143
146
|
|
|
144
|
-
### `/
|
|
147
|
+
### `/wake`
|
|
145
148
|
|
|
146
|
-
At the start of each day, run `/
|
|
149
|
+
At the start of each day, run `/wake` inside any Claude Code session after
|
|
147
150
|
the plugin is installed. It performs once-per-day cross-project curation of
|
|
148
151
|
yesterday's sessions into durable journal entries, walking each uncurated session
|
|
149
152
|
through a draft you can accept, edit, skip, or mark for in-entry promotion. See
|
|
150
|
-
[`docs/reference/plugin.md#skill-1-
|
|
153
|
+
[`docs/reference/plugin.md#skill-1-wake`](./docs/reference/plugin.md#skill-1-wake).
|
|
151
154
|
|
|
152
|
-
### `/
|
|
155
|
+
### `/brief`
|
|
153
156
|
|
|
154
|
-
When starting work on a specific project, run `/
|
|
157
|
+
When starting work on a specific project, run `/brief` (or `/brief <slug>` from
|
|
155
158
|
anywhere) to get a per-project read-only briefing synthesized from recent curated entries,
|
|
156
|
-
today's breadcrumbs, and any sessions already started today. `/
|
|
159
|
+
today's breadcrumbs, and any sessions already started today. `/brief` never writes — it
|
|
157
160
|
only reads. See
|
|
158
|
-
[`docs/reference/plugin.md#skill-2-
|
|
161
|
+
[`docs/reference/plugin.md#skill-2-brief`](./docs/reference/plugin.md#skill-2-brief).
|
|
159
162
|
|
|
160
163
|
## Development
|
|
161
164
|
|
package/bin/clast
CHANGED
|
@@ -1,93 +1,42 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# clast —
|
|
2
|
+
# clast — porcelain over clast-plumbing, with an OpenAI-compatible LLM
|
|
3
|
+
# provider. Owns the `wake` and `brief` subcommands, plus `undismiss` as a
|
|
4
|
+
# convenience passthrough to plumbing (recovers an accidental [d] in wake).
|
|
5
|
+
# Every other verb is a clean error — the porcelain does not broadly proxy.
|
|
3
6
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# each defines a single function `clast_cmd_<name>`.
|
|
7
|
+
# Subcommand files live in $CLAST_LIB/clast-porcelain-subcommands/<name>.bash
|
|
8
|
+
# and each defines a single function `clast_cmd_<name>`.
|
|
7
9
|
set -euo pipefail
|
|
8
10
|
|
|
9
11
|
CLAST_LIB="${CLAST_LIB:-$(dirname "$(realpath "$0")")/../lib/clast}"
|
|
10
12
|
export CLAST_LIB
|
|
11
13
|
|
|
12
|
-
# shellcheck source=lib/clast/clast-lib.bash
|
|
13
|
-
source "$CLAST_LIB/clast-lib.bash"
|
|
14
|
-
# shellcheck source=lib/clast/clast-decode-lib.bash
|
|
15
|
-
source "$CLAST_LIB/clast-decode-lib.bash"
|
|
16
|
-
# shellcheck source=lib/clast/clast-registry-lib.bash
|
|
17
|
-
source "$CLAST_LIB/clast-registry-lib.bash"
|
|
18
|
-
# shellcheck source=lib/clast/clast-manifest-lib.bash
|
|
19
|
-
source "$CLAST_LIB/clast-manifest-lib.bash"
|
|
20
|
-
|
|
21
|
-
# --- Global flag parsing -------------------------------------------------
|
|
22
|
-
#
|
|
23
|
-
# Walk argv before the subcommand name, peeling off any recognized global
|
|
24
|
-
# flag and setting the corresponding env var. Stop at the first non-flag
|
|
25
|
-
# arg (the subcommand) or at `--`. Remaining argv is passed to the
|
|
26
|
-
# subcommand untouched.
|
|
27
|
-
#
|
|
28
|
-
# `--json` and `--journal-dir`/`--projects-dir` are forwarded to the lib
|
|
29
|
-
# via env so subcommands can also accept them locally without re-parsing.
|
|
14
|
+
# shellcheck source=lib/clast/clast-porcelain-lib.bash
|
|
15
|
+
source "$CLAST_LIB/clast-porcelain-lib.bash"
|
|
30
16
|
|
|
31
17
|
declare -a _CLAST_REMAINING=()
|
|
32
18
|
|
|
33
19
|
while [[ $# -gt 0 ]]; do
|
|
34
20
|
case "$1" in
|
|
35
21
|
-h|--help|help)
|
|
36
|
-
|
|
22
|
+
clast_porcelain_usage
|
|
37
23
|
exit 0
|
|
38
24
|
;;
|
|
39
25
|
--version)
|
|
40
|
-
echo "clast $(
|
|
26
|
+
echo "clast $(clast_porcelain_version)"
|
|
41
27
|
exit 0
|
|
42
28
|
;;
|
|
43
|
-
--json)
|
|
44
|
-
export CLAST_JSON=1
|
|
45
|
-
shift
|
|
46
|
-
;;
|
|
47
|
-
-v|--verbose)
|
|
48
|
-
export CLAST_VERBOSE=1
|
|
49
|
-
shift
|
|
50
|
-
;;
|
|
51
|
-
-q|--quiet)
|
|
52
|
-
export CLAST_QUIET=1
|
|
53
|
-
shift
|
|
54
|
-
;;
|
|
55
|
-
--journal-dir)
|
|
56
|
-
if [[ $# -lt 2 ]]; then
|
|
57
|
-
clast_log_error "--journal-dir requires a value"
|
|
58
|
-
exit 2
|
|
59
|
-
fi
|
|
60
|
-
export CLAST_JOURNAL_DIR="$2"
|
|
61
|
-
shift 2
|
|
62
|
-
;;
|
|
63
|
-
--journal-dir=*)
|
|
64
|
-
export CLAST_JOURNAL_DIR="${1#*=}"
|
|
65
|
-
shift
|
|
66
|
-
;;
|
|
67
|
-
--projects-dir)
|
|
68
|
-
if [[ $# -lt 2 ]]; then
|
|
69
|
-
clast_log_error "--projects-dir requires a value"
|
|
70
|
-
exit 2
|
|
71
|
-
fi
|
|
72
|
-
export CLAST_PROJECTS_DIR="$2"
|
|
73
|
-
shift 2
|
|
74
|
-
;;
|
|
75
|
-
--projects-dir=*)
|
|
76
|
-
export CLAST_PROJECTS_DIR="${1#*=}"
|
|
77
|
-
shift
|
|
78
|
-
;;
|
|
79
29
|
--)
|
|
80
30
|
shift
|
|
81
31
|
_CLAST_REMAINING+=("$@")
|
|
82
32
|
break
|
|
83
33
|
;;
|
|
84
34
|
-*)
|
|
85
|
-
|
|
86
|
-
|
|
35
|
+
clast_porcelain_log_error "unknown global flag: $1"
|
|
36
|
+
clast_porcelain_usage >&2
|
|
87
37
|
exit 2
|
|
88
38
|
;;
|
|
89
39
|
*)
|
|
90
|
-
# First non-flag arg is the subcommand; stop parsing.
|
|
91
40
|
_CLAST_REMAINING+=("$@")
|
|
92
41
|
break
|
|
93
42
|
;;
|
|
@@ -95,7 +44,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
95
44
|
done
|
|
96
45
|
|
|
97
46
|
if [[ ${#_CLAST_REMAINING[@]} -eq 0 ]]; then
|
|
98
|
-
|
|
47
|
+
clast_porcelain_usage
|
|
99
48
|
exit 0
|
|
100
49
|
fi
|
|
101
50
|
|
|
@@ -103,70 +52,30 @@ set -- "${_CLAST_REMAINING[@]}"
|
|
|
103
52
|
|
|
104
53
|
cmd="$1"; shift
|
|
105
54
|
|
|
106
|
-
# --- Subcommand dispatch -------------------------------------------------
|
|
107
|
-
|
|
108
|
-
# Map of stubbed subcommands → step number that will implement them.
|
|
109
|
-
# Future steps replace each stub with a real `source` + dispatch below.
|
|
110
|
-
_clast_stub() {
|
|
111
|
-
local name="$1" step="$2"
|
|
112
|
-
clast_log_error "$name is not yet implemented (planned for step $step)"
|
|
113
|
-
exit 2
|
|
114
|
-
}
|
|
115
|
-
|
|
116
55
|
case "$cmd" in
|
|
117
|
-
|
|
118
|
-
# shellcheck source=lib/clast/clast-subcommands/
|
|
119
|
-
source "$CLAST_LIB/clast-subcommands/
|
|
120
|
-
|
|
121
|
-
;;
|
|
122
|
-
snapshot)
|
|
123
|
-
# shellcheck source=lib/clast/clast-subcommands/snapshot.bash
|
|
124
|
-
source "$CLAST_LIB/clast-subcommands/snapshot.bash"
|
|
125
|
-
clast_cmd_snapshot "$@"
|
|
126
|
-
;;
|
|
127
|
-
projects)
|
|
128
|
-
# shellcheck source=lib/clast/clast-subcommands/projects.bash
|
|
129
|
-
source "$CLAST_LIB/clast-subcommands/projects.bash"
|
|
130
|
-
clast_cmd_projects "$@"
|
|
131
|
-
;;
|
|
132
|
-
sessions)
|
|
133
|
-
# shellcheck source=lib/clast/clast-subcommands/sessions.bash
|
|
134
|
-
source "$CLAST_LIB/clast-subcommands/sessions.bash"
|
|
135
|
-
clast_cmd_sessions "$@"
|
|
136
|
-
;;
|
|
137
|
-
show)
|
|
138
|
-
# shellcheck source=lib/clast/clast-subcommands/show.bash
|
|
139
|
-
source "$CLAST_LIB/clast-subcommands/show.bash"
|
|
140
|
-
clast_cmd_show "$@"
|
|
141
|
-
;;
|
|
142
|
-
entries)
|
|
143
|
-
# shellcheck source=lib/clast/clast-subcommands/entries.bash
|
|
144
|
-
source "$CLAST_LIB/clast-subcommands/entries.bash"
|
|
145
|
-
clast_cmd_entries "$@"
|
|
146
|
-
;;
|
|
147
|
-
breadcrumb)
|
|
148
|
-
# shellcheck source=lib/clast/clast-subcommands/breadcrumb.bash
|
|
149
|
-
source "$CLAST_LIB/clast-subcommands/breadcrumb.bash"
|
|
150
|
-
clast_cmd_breadcrumb "$@"
|
|
56
|
+
wake)
|
|
57
|
+
# shellcheck source=lib/clast/clast-porcelain-subcommands/wake.bash
|
|
58
|
+
source "$CLAST_LIB/clast-porcelain-subcommands/wake.bash"
|
|
59
|
+
clast_cmd_wake "$@"
|
|
151
60
|
;;
|
|
152
|
-
|
|
153
|
-
# shellcheck source=lib/clast/clast-subcommands/
|
|
154
|
-
source "$CLAST_LIB/clast-subcommands/
|
|
155
|
-
|
|
61
|
+
brief)
|
|
62
|
+
# shellcheck source=lib/clast/clast-porcelain-subcommands/brief.bash
|
|
63
|
+
source "$CLAST_LIB/clast-porcelain-subcommands/brief.bash"
|
|
64
|
+
clast_cmd_brief "$@"
|
|
156
65
|
;;
|
|
157
|
-
|
|
158
|
-
# shellcheck source=lib/clast/clast-subcommands/
|
|
159
|
-
source "$CLAST_LIB/clast-subcommands/
|
|
160
|
-
|
|
66
|
+
retro)
|
|
67
|
+
# shellcheck source=lib/clast/clast-porcelain-subcommands/retro.bash
|
|
68
|
+
source "$CLAST_LIB/clast-porcelain-subcommands/retro.bash"
|
|
69
|
+
clast_cmd_retro "$@"
|
|
161
70
|
;;
|
|
162
|
-
|
|
163
|
-
# shellcheck source=lib/clast/clast-subcommands/
|
|
164
|
-
source "$CLAST_LIB/clast-subcommands/
|
|
165
|
-
|
|
71
|
+
undismiss)
|
|
72
|
+
# shellcheck source=lib/clast/clast-porcelain-subcommands/undismiss.bash
|
|
73
|
+
source "$CLAST_LIB/clast-porcelain-subcommands/undismiss.bash"
|
|
74
|
+
clast_cmd_undismiss "$@"
|
|
166
75
|
;;
|
|
167
76
|
*)
|
|
168
|
-
|
|
169
|
-
|
|
77
|
+
clast_porcelain_log_error "unknown subcommand '$cmd'"
|
|
78
|
+
clast_porcelain_usage >&2
|
|
170
79
|
exit 2
|
|
171
80
|
;;
|
|
172
81
|
esac
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# clast-plumbing — main dispatcher (the deterministic, LLM-free core).
|
|
3
|
+
#
|
|
4
|
+
# Parses global flags, sources libs, dispatches to a subcommand.
|
|
5
|
+
# Subcommand files live in $CLAST_LIB/clast-subcommands/<name>.bash and
|
|
6
|
+
# each defines a single function `clast_cmd_<name>`. The user-facing
|
|
7
|
+
# porcelain is `bin/clast` (see `clast --help` for that surface).
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
CLAST_LIB="${CLAST_LIB:-$(dirname "$(realpath "$0")")/../lib/clast}"
|
|
11
|
+
export CLAST_LIB
|
|
12
|
+
|
|
13
|
+
# shellcheck source=lib/clast/clast-lib.bash
|
|
14
|
+
source "$CLAST_LIB/clast-lib.bash"
|
|
15
|
+
# shellcheck source=lib/clast/clast-decode-lib.bash
|
|
16
|
+
source "$CLAST_LIB/clast-decode-lib.bash"
|
|
17
|
+
# shellcheck source=lib/clast/clast-registry-lib.bash
|
|
18
|
+
source "$CLAST_LIB/clast-registry-lib.bash"
|
|
19
|
+
# shellcheck source=lib/clast/clast-manifest-lib.bash
|
|
20
|
+
source "$CLAST_LIB/clast-manifest-lib.bash"
|
|
21
|
+
# shellcheck source=lib/clast/clast-classify-lib.bash
|
|
22
|
+
source "$CLAST_LIB/clast-classify-lib.bash"
|
|
23
|
+
|
|
24
|
+
# --- Global flag parsing -------------------------------------------------
|
|
25
|
+
#
|
|
26
|
+
# Walk argv before the subcommand name, peeling off any recognized global
|
|
27
|
+
# flag and setting the corresponding env var. Stop at the first non-flag
|
|
28
|
+
# arg (the subcommand) or at `--`. Remaining argv is passed to the
|
|
29
|
+
# subcommand untouched.
|
|
30
|
+
#
|
|
31
|
+
# `--json` and `--journal-dir`/`--projects-dir` are forwarded to the lib
|
|
32
|
+
# via env so subcommands can also accept them locally without re-parsing.
|
|
33
|
+
|
|
34
|
+
declare -a _CLAST_REMAINING=()
|
|
35
|
+
|
|
36
|
+
while [[ $# -gt 0 ]]; do
|
|
37
|
+
case "$1" in
|
|
38
|
+
-h|--help|help)
|
|
39
|
+
clast_usage
|
|
40
|
+
exit 0
|
|
41
|
+
;;
|
|
42
|
+
--version)
|
|
43
|
+
echo "clast-plumbing $(clast_version)"
|
|
44
|
+
exit 0
|
|
45
|
+
;;
|
|
46
|
+
--json)
|
|
47
|
+
export CLAST_JSON=1
|
|
48
|
+
shift
|
|
49
|
+
;;
|
|
50
|
+
-v|--verbose)
|
|
51
|
+
export CLAST_VERBOSE=1
|
|
52
|
+
shift
|
|
53
|
+
;;
|
|
54
|
+
-q|--quiet)
|
|
55
|
+
export CLAST_QUIET=1
|
|
56
|
+
shift
|
|
57
|
+
;;
|
|
58
|
+
--journal-dir)
|
|
59
|
+
if [[ $# -lt 2 ]]; then
|
|
60
|
+
clast_log_error "--journal-dir requires a value"
|
|
61
|
+
exit 2
|
|
62
|
+
fi
|
|
63
|
+
export CLAST_JOURNAL_DIR="$2"
|
|
64
|
+
shift 2
|
|
65
|
+
;;
|
|
66
|
+
--journal-dir=*)
|
|
67
|
+
export CLAST_JOURNAL_DIR="${1#*=}"
|
|
68
|
+
shift
|
|
69
|
+
;;
|
|
70
|
+
--projects-dir)
|
|
71
|
+
if [[ $# -lt 2 ]]; then
|
|
72
|
+
clast_log_error "--projects-dir requires a value"
|
|
73
|
+
exit 2
|
|
74
|
+
fi
|
|
75
|
+
export CLAST_PROJECTS_DIR="$2"
|
|
76
|
+
shift 2
|
|
77
|
+
;;
|
|
78
|
+
--projects-dir=*)
|
|
79
|
+
export CLAST_PROJECTS_DIR="${1#*=}"
|
|
80
|
+
shift
|
|
81
|
+
;;
|
|
82
|
+
--)
|
|
83
|
+
shift
|
|
84
|
+
_CLAST_REMAINING+=("$@")
|
|
85
|
+
break
|
|
86
|
+
;;
|
|
87
|
+
-*)
|
|
88
|
+
clast_log_error "unknown global flag: $1"
|
|
89
|
+
clast_usage >&2
|
|
90
|
+
exit 2
|
|
91
|
+
;;
|
|
92
|
+
*)
|
|
93
|
+
# First non-flag arg is the subcommand; stop parsing.
|
|
94
|
+
_CLAST_REMAINING+=("$@")
|
|
95
|
+
break
|
|
96
|
+
;;
|
|
97
|
+
esac
|
|
98
|
+
done
|
|
99
|
+
|
|
100
|
+
if [[ ${#_CLAST_REMAINING[@]} -eq 0 ]]; then
|
|
101
|
+
clast_usage
|
|
102
|
+
exit 0
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
set -- "${_CLAST_REMAINING[@]}"
|
|
106
|
+
|
|
107
|
+
cmd="$1"; shift
|
|
108
|
+
|
|
109
|
+
# --- Subcommand dispatch -------------------------------------------------
|
|
110
|
+
|
|
111
|
+
# Map of stubbed subcommands → step number that will implement them.
|
|
112
|
+
# Future steps replace each stub with a real `source` + dispatch below.
|
|
113
|
+
_clast_stub() {
|
|
114
|
+
local name="$1" step="$2"
|
|
115
|
+
clast_log_error "$name is not yet implemented (planned for step $step)"
|
|
116
|
+
exit 2
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
case "$cmd" in
|
|
120
|
+
whereami)
|
|
121
|
+
# shellcheck source=lib/clast/clast-subcommands/whereami.bash
|
|
122
|
+
source "$CLAST_LIB/clast-subcommands/whereami.bash"
|
|
123
|
+
clast_cmd_whereami "$@"
|
|
124
|
+
;;
|
|
125
|
+
snapshot)
|
|
126
|
+
# shellcheck source=lib/clast/clast-subcommands/snapshot.bash
|
|
127
|
+
source "$CLAST_LIB/clast-subcommands/snapshot.bash"
|
|
128
|
+
clast_cmd_snapshot "$@"
|
|
129
|
+
;;
|
|
130
|
+
projects)
|
|
131
|
+
# shellcheck source=lib/clast/clast-subcommands/projects.bash
|
|
132
|
+
source "$CLAST_LIB/clast-subcommands/projects.bash"
|
|
133
|
+
clast_cmd_projects "$@"
|
|
134
|
+
;;
|
|
135
|
+
sessions)
|
|
136
|
+
# shellcheck source=lib/clast/clast-subcommands/sessions.bash
|
|
137
|
+
source "$CLAST_LIB/clast-subcommands/sessions.bash"
|
|
138
|
+
clast_cmd_sessions "$@"
|
|
139
|
+
;;
|
|
140
|
+
show)
|
|
141
|
+
# shellcheck source=lib/clast/clast-subcommands/show.bash
|
|
142
|
+
source "$CLAST_LIB/clast-subcommands/show.bash"
|
|
143
|
+
clast_cmd_show "$@"
|
|
144
|
+
;;
|
|
145
|
+
entries)
|
|
146
|
+
# shellcheck source=lib/clast/clast-subcommands/entries.bash
|
|
147
|
+
source "$CLAST_LIB/clast-subcommands/entries.bash"
|
|
148
|
+
clast_cmd_entries "$@"
|
|
149
|
+
;;
|
|
150
|
+
breadcrumb)
|
|
151
|
+
# shellcheck source=lib/clast/clast-subcommands/breadcrumb.bash
|
|
152
|
+
source "$CLAST_LIB/clast-subcommands/breadcrumb.bash"
|
|
153
|
+
clast_cmd_breadcrumb "$@"
|
|
154
|
+
;;
|
|
155
|
+
registry)
|
|
156
|
+
# shellcheck source=lib/clast/clast-subcommands/registry.bash
|
|
157
|
+
source "$CLAST_LIB/clast-subcommands/registry.bash"
|
|
158
|
+
clast_cmd_registry "$@"
|
|
159
|
+
;;
|
|
160
|
+
stats)
|
|
161
|
+
# shellcheck source=lib/clast/clast-subcommands/stats.bash
|
|
162
|
+
source "$CLAST_LIB/clast-subcommands/stats.bash"
|
|
163
|
+
clast_cmd_stats "$@"
|
|
164
|
+
;;
|
|
165
|
+
doctor)
|
|
166
|
+
# shellcheck source=lib/clast/clast-subcommands/doctor.bash
|
|
167
|
+
source "$CLAST_LIB/clast-subcommands/doctor.bash"
|
|
168
|
+
clast_cmd_doctor "$@"
|
|
169
|
+
;;
|
|
170
|
+
retro)
|
|
171
|
+
# shellcheck source=lib/clast/clast-subcommands/retro.bash
|
|
172
|
+
source "$CLAST_LIB/clast-subcommands/retro.bash"
|
|
173
|
+
clast_cmd_retro "$@"
|
|
174
|
+
;;
|
|
175
|
+
*)
|
|
176
|
+
clast_log_error "unknown subcommand '$cmd'"
|
|
177
|
+
clast_usage >&2
|
|
178
|
+
exit 2
|
|
179
|
+
;;
|
|
180
|
+
esac
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# then enable the timer with: systemctl --user enable --now clast-snapshot.timer
|
|
4
4
|
|
|
5
5
|
[Unit]
|
|
6
|
-
Description=Capture Claude Code transcripts with clast
|
|
6
|
+
Description=Capture Claude Code transcripts with clast-plumbing
|
|
7
7
|
|
|
8
8
|
[Service]
|
|
9
9
|
Type=oneshot
|
|
10
|
-
ExecStart=/usr/local/bin/clast snapshot
|
|
10
|
+
ExecStart=/usr/local/bin/clast-plumbing snapshot
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# clast cron sample for unattended transcript capture.
|
|
2
2
|
# Install with: crontab -l | { cat; cat examples/cron/crontab.sample; } | crontab -
|
|
3
|
-
# Edit the clast path if you installed somewhere other than /usr/local/bin.
|
|
3
|
+
# Edit the clast-plumbing path if you installed somewhere other than /usr/local/bin.
|
|
4
4
|
|
|
5
5
|
# Every hour at :05, capture any new transcripts.
|
|
6
6
|
# Idempotent and silent on no-op, so safe to run frequently.
|
|
7
|
-
5 * * * * /usr/local/bin/clast snapshot >/dev/null 2>&1
|
|
7
|
+
5 * * * * /usr/local/bin/clast-plumbing snapshot >/dev/null 2>&1
|
|
8
8
|
|
|
9
9
|
# Alternative: every 15 minutes for active users moving between many sessions.
|
|
10
|
-
# */15 * * * * /usr/local/bin/clast snapshot >/dev/null 2>&1
|
|
10
|
+
# */15 * * * * /usr/local/bin/clast-plumbing snapshot >/dev/null 2>&1
|
|
11
11
|
|
|
12
12
|
# Alternative: once daily for hands-off archival.
|
|
13
|
-
# 10 4 * * * /usr/local/bin/clast snapshot >/dev/null 2>&1
|
|
13
|
+
# 10 4 * * * /usr/local/bin/clast-plumbing snapshot >/dev/null 2>&1
|
|
14
14
|
|
|
15
15
|
# Alternative: no cron. Rely on the SessionStart hook installed with the plugin.
|
|
16
16
|
# The hook covers most use cases already; cron is only useful when you want capture without ever opening Claude.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Morning Briefing Example
|
|
2
2
|
|
|
3
|
-
This is a realistic walkthrough of one `/
|
|
3
|
+
This is a realistic walkthrough of one `/wake` run. Yesterday, `xesapps`
|
|
4
4
|
finished a field-normalization fix, `notes` explored a journal template update,
|
|
5
5
|
and `infra-tools` checked a flaky shell lint issue.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
# User: /
|
|
9
|
-
clast snapshot
|
|
10
|
-
clast --json sessions --day yesterday
|
|
8
|
+
# User: /wake
|
|
9
|
+
clast-plumbing snapshot
|
|
10
|
+
clast-plumbing --json sessions --day yesterday
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
It filters to `curated: false`, groups by project, and shows:
|
|
@@ -23,8 +23,8 @@ xesapps 09:12 feature/field-normalize 58 messages
|
|
|
23
23
|
The skill reads session details and breadcrumbs:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
clast --json show 33333333-3333-4333-8333-333333333333 --full --turns 8
|
|
27
|
-
clast breadcrumb --read --project infra-tools --day yesterday
|
|
26
|
+
clast-plumbing --json show 33333333-3333-4333-8333-333333333333 --full --turns 8
|
|
27
|
+
clast-plumbing breadcrumb --read --project infra-tools --day yesterday
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
It drafts a short entry:
|
|
@@ -43,15 +43,15 @@ AskUserQuestion presents `Accept`, `Accept + promote decision`, `Accept + promot
|
|
|
43
43
|
common-issue`, `Accept + promote workflow`, `Edit`, `Skip`, and `Stop here`.
|
|
44
44
|
|
|
45
45
|
The user chooses `Skip`. The skill writes nothing; the session remains
|
|
46
|
-
uncurated and can be revisited in a later `/
|
|
46
|
+
uncurated and can be revisited in a later `/wake`.
|
|
47
47
|
|
|
48
48
|
## Session 2: notes
|
|
49
49
|
|
|
50
50
|
The skill reads the next transcript:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
clast --json show 22222222-2222-4222-8222-222222222222 --full --turns 8
|
|
54
|
-
clast breadcrumb --read --project notes --day yesterday
|
|
53
|
+
clast-plumbing --json show 22222222-2222-4222-8222-222222222222 --full --turns 8
|
|
54
|
+
clast-plumbing breadcrumb --read --project notes --day yesterday
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
The user asks for a revision:
|
|
@@ -76,7 +76,7 @@ Tighten the note-entry template before using it for project briefings.
|
|
|
76
76
|
The skill writes through stdin:
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
|
-
clast entries write \
|
|
79
|
+
clast-plumbing entries write \
|
|
80
80
|
--session 22222222-2222-4222-8222-222222222222 \
|
|
81
81
|
--slug entry-template-cleanup \
|
|
82
82
|
--tags notes,template \
|
|
@@ -89,8 +89,8 @@ clast entries write \
|
|
|
89
89
|
The skill reads the session and breadcrumbs:
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
|
-
clast --json show 11111111-1111-4111-8111-111111111111 --full --turns 8
|
|
93
|
-
clast breadcrumb --read --project xesapps --day yesterday
|
|
92
|
+
clast-plumbing --json show 11111111-1111-4111-8111-111111111111 --full --turns 8
|
|
93
|
+
clast-plumbing breadcrumb --read --project xesapps --day yesterday
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
The user chooses `Accept + promote decision` for this draft:
|
|
@@ -112,7 +112,7 @@ items are folded into the entry body rather than written to separate decision,
|
|
|
112
112
|
common-issue, or workflow files.
|
|
113
113
|
|
|
114
114
|
```bash
|
|
115
|
-
clast entries write \
|
|
115
|
+
clast-plumbing entries write \
|
|
116
116
|
--session 11111111-1111-4111-8111-111111111111 \
|
|
117
117
|
--slug field-normalization-fix \
|
|
118
118
|
--tags xesapps,fields,regression \
|
|
@@ -123,15 +123,15 @@ clast entries write \
|
|
|
123
123
|
Final summary:
|
|
124
124
|
|
|
125
125
|
```text
|
|
126
|
-
|
|
126
|
+
Wake complete.
|
|
127
127
|
Curated: 2 sessions across 2 projects.
|
|
128
128
|
Skipped: 1 session.
|
|
129
129
|
Remaining uncurated: 1.
|
|
130
130
|
Promoted: 1 decision (folded into the accepted entry for v1.0).
|
|
131
|
-
Run `/
|
|
131
|
+
Run `/brief <project>` to start working on a specific project today.
|
|
132
132
|
```
|
|
133
133
|
|
|
134
134
|
What this changes on disk:
|
|
135
135
|
`entries/2026-05-31-1340-notes-entry-template-cleanup.md` and `entries/2026-05-31-0912-xesapps-field-normalization-fix.md` were written.
|
|
136
|
-
`.manifest.jsonl` was already current from `clast snapshot`; curation does not append to it.
|
|
137
|
-
The skipped `infra-tools` session stays uncurated and remains eligible for a later `/
|
|
136
|
+
`.manifest.jsonl` was already current from `clast-plumbing snapshot`; curation does not append to it.
|
|
137
|
+
The skipped `infra-tools` session stays uncurated and remains eligible for a later `/wake`.
|