@procrastivity/clast 0.0.2 → 0.0.4

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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: day-wakeup
3
- description: 'Generate curated journal entries from yesterday''s Claude Code sessions across all projects. Use when the user says "/day-wakeup", "day wakeup", "morning briefing", "catch me up on yesterday", "what did I work on yesterday", "review my day", "process yesterday''s sessions", or otherwise signals they want to curate prior work across projects at the start of a new day. Runs `clast snapshot` to ensure fresh data, then walks through each uncurated session from yesterday and proposes a draft entry the user can accept, edit, or skip. Prompts for promotion of decisions, common-issues, and workflows per accepted session. This is the once-per-day curation flow; for per-project briefings use /wakeup; for mid-session pivots use session-brief.'
3
+ description: 'Generate curated journal entries from yesterday''s Claude Code sessions across all projects. Use when the user says "/day-wakeup", "day wakeup", "morning briefing", "catch me up on yesterday", "what did I work on yesterday", "review my day", "process yesterday''s sessions", or otherwise signals they want to curate prior work across projects at the start of a new day. Runs `clast-plumbing snapshot` to ensure fresh data, then walks through each uncurated session from yesterday and proposes a draft entry the user can accept, edit, or skip. Prompts for promotion of decisions, common-issues, and workflows per accepted session. This is the once-per-day curation flow; for per-project briefings use /wakeup; for mid-session pivots use session-brief.'
4
4
  ---
5
5
 
6
6
  # Day Wakeup
@@ -13,28 +13,30 @@ Curation at end-of-session has high friction (the user wants to stop, not summar
13
13
 
14
14
  The transcripts themselves are captured automatically by the SessionStart hook + cron — the user never has to remember to log anything. What `/day-wakeup` does is **curate the captured transcripts into durable entries the user controls**, and prompt for promotion of decisions, common-issues, and workflows along the way.
15
15
 
16
- ## Step 0: Resolve the clast binary
16
+ ## Step 0: Resolve the clast-plumbing binary
17
17
 
18
- Before running any `clast` command, determine which binary to use. Run this
19
- once at the start and reuse the result for all commands in this skill:
18
+ This skill calls the deterministic core (`clast-plumbing`), not the
19
+ LLM-aware porcelain (`clast`). Determine the binary to use once at the
20
+ start and reuse the result for all commands in this skill:
20
21
 
21
22
  ```bash
22
- if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" && -x "$CLAUDE_PLUGIN_ROOT/bin/clast" ]]; then
23
- CLAST_BIN="$CLAUDE_PLUGIN_ROOT/bin/clast"
24
- elif command -v clast >/dev/null 2>&1; then
25
- CLAST_BIN="clast"
23
+ if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" && -x "$CLAUDE_PLUGIN_ROOT/bin/clast-plumbing" ]]; then
24
+ CLAST_BIN="$CLAUDE_PLUGIN_ROOT/bin/clast-plumbing"
25
+ elif command -v clast-plumbing >/dev/null 2>&1; then
26
+ CLAST_BIN="clast-plumbing"
26
27
  else
27
28
  _pdir="$(find ~/.claude -maxdepth 5 -name plugin.json -path '*/clast/.claude-plugin/*' -print -quit 2>/dev/null)"
28
29
  if [[ -n "$_pdir" ]]; then
29
- CLAST_BIN="$(cd "$(dirname "$_pdir")/../.." && pwd)/bin/clast"
30
+ CLAST_BIN="$(cd "$(dirname "$_pdir")/../.." && pwd)/bin/clast-plumbing"
30
31
  fi
31
32
  fi
32
33
  ```
33
34
 
34
- If `CLAST_BIN` is still empty, tell the user: "clast CLI not found. Install it
35
- with `npm i -g @procrastivity/clast` or see the README for other options."
35
+ If `CLAST_BIN` is still empty, tell the user: "clast-plumbing CLI not found.
36
+ Install it with `npm i -g @procrastivity/clast` or see the README for other
37
+ options."
36
38
 
37
- Use `$CLAST_BIN` in place of bare `clast` for all commands in this skill.
39
+ Use `$CLAST_BIN` in place of bare `clast-plumbing` for all commands in this skill.
38
40
 
39
41
  ## Step 1: Ensure fresh data
40
42
 
@@ -108,7 +110,7 @@ For each session in the list:
108
110
  5. Present the **promotion question** (see below) via AskUserQuestion.
109
111
 
110
112
  6. Handle the response:
111
- - **Accept** (any combination of accept-flavored options): pipe the draft to `clast entries write` via stdin.
113
+ - **Accept** (any combination of accept-flavored options): pipe the draft to `clast-plumbing entries write` via stdin.
112
114
  - **Edit**: prompt the user for what to change, regenerate the draft incorporating their feedback, loop.
113
115
  - **Skip**: do not write.
114
116
  - **Stop here**: end the entire `/day-wakeup` flow, leaving remaining sessions uncurated (user can resume tomorrow).
@@ -133,7 +135,7 @@ Run `/wakeup <project>` to start working on a specific project today.
133
135
 
134
136
  ## Draft generation prompt
135
137
 
136
- The prompt templates live in `lib/clast/prompts/` so they are shared with the standalone `clast-wake` script:
138
+ The prompt templates live in `lib/clast/prompts/` so they are shared with the porcelain `clast wake` subcommand:
137
139
 
138
140
  - **System prompt:** `lib/clast/prompts/day-wakeup-draft-system.md`
139
141
  - **User prompt template:** `lib/clast/prompts/day-wakeup-draft-user.md` (uses `{{placeholder}}` syntax)
@@ -175,7 +177,7 @@ If the user selects `Edit`:
175
177
  When the user accepts:
176
178
 
177
179
  1. Extract the suggested tags from the draft (the user may have edited them).
178
- 2. Pipe the entry body (without the suggested-tags trailer) to `clast entries write`:
180
+ 2. Pipe the entry body (without the suggested-tags trailer) to `clast-plumbing entries write`:
179
181
 
180
182
  ```bash
181
183
  $CLAST_BIN entries write \
@@ -190,14 +192,14 @@ $CLAST_BIN entries write \
190
192
 
191
193
  3. If the write succeeds, append a one-line confirmation to the running summary.
192
194
 
193
- For promoted items (decisions, common-issues, workflows): currently these are tracked inside the entry's body for v1. **TODO for v1.1: separate `clast decisions write` / `clast common-issues write` / `clast workflows write` subcommands and a directory structure to match.** Note this in the user-facing summary so the user knows they're folded into the entry for now.
195
+ For promoted items (decisions, common-issues, workflows): currently these are tracked inside the entry's body for v1. **TODO for v1.1: separate `clast-plumbing decisions write` / `clast-plumbing common-issues write` / `clast-plumbing workflows write` subcommands and a directory structure to match.** Note this in the user-facing summary so the user knows they're folded into the entry for now.
194
196
 
195
- <!-- step-12 addition: v1 promotion section convention --> When folding promoted items into the accepted entry body, append `## Decision`, `## Common issue`, or `## Workflow` (h2, singular, capitalized), each followed by the prompted-for title (h3) and body before invoking `clast entries write`.
197
+ <!-- step-12 addition: v1 promotion section convention --> When folding promoted items into the accepted entry body, append `## Decision`, `## Common issue`, or `## Workflow` (h2, singular, capitalized), each followed by the prompted-for title (h3) and body before invoking `clast-plumbing entries write`.
196
198
 
197
199
  ## Edge cases
198
200
 
199
201
  - **No uncurated sessions**: print "Nothing to curate — all sessions are curated or dismissed." and stop.
200
202
  - **Multi-day backlog**: present the triage step (Step 2) so the user can choose scope before processing.
201
- - **`clast snapshot` fails**: warn the user, then attempt to proceed with whatever's already in the manifest.
202
- - **`clast show` fails for a specific session**: skip that session, note it in the final summary, continue with the rest.
203
+ - **`clast-plumbing snapshot` fails**: warn the user, then attempt to proceed with whatever's already in the manifest.
204
+ - **`clast-plumbing show` fails for a specific session**: skip that session, note it in the final summary, continue with the rest.
203
205
  - **User says "do them all without prompting"**: not a v1 feature. Each session gets its own AskUserQuestion. The friction is intentional — it's where curation happens.
@@ -12,28 +12,30 @@ Synthesize a briefing for the current (or named) project so the user can resume
12
12
 
13
13
  `/day-wakeup` curates yesterday's work into entries. `/wakeup` reads those entries back when starting work in a specific repo. The two are complementary: one writes, one reads.
14
14
 
15
- ## Step 0: Resolve the clast binary
15
+ ## Step 0: Resolve the clast-plumbing binary
16
16
 
17
- Before running any `clast` command, determine which binary to use. Run this
18
- once at the start and reuse the result for all commands in this skill:
17
+ This skill calls the deterministic core (`clast-plumbing`), not the
18
+ LLM-aware porcelain (`clast`). Determine the binary to use once at the
19
+ start and reuse the result for all commands in this skill:
19
20
 
20
21
  ```bash
21
- if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" && -x "$CLAUDE_PLUGIN_ROOT/bin/clast" ]]; then
22
- CLAST_BIN="$CLAUDE_PLUGIN_ROOT/bin/clast"
23
- elif command -v clast >/dev/null 2>&1; then
24
- CLAST_BIN="clast"
22
+ if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" && -x "$CLAUDE_PLUGIN_ROOT/bin/clast-plumbing" ]]; then
23
+ CLAST_BIN="$CLAUDE_PLUGIN_ROOT/bin/clast-plumbing"
24
+ elif command -v clast-plumbing >/dev/null 2>&1; then
25
+ CLAST_BIN="clast-plumbing"
25
26
  else
26
27
  _pdir="$(find ~/.claude -maxdepth 5 -name plugin.json -path '*/clast/.claude-plugin/*' -print -quit 2>/dev/null)"
27
28
  if [[ -n "$_pdir" ]]; then
28
- CLAST_BIN="$(cd "$(dirname "$_pdir")/../.." && pwd)/bin/clast"
29
+ CLAST_BIN="$(cd "$(dirname "$_pdir")/../.." && pwd)/bin/clast-plumbing"
29
30
  fi
30
31
  fi
31
32
  ```
32
33
 
33
- If `CLAST_BIN` is still empty, tell the user: "clast CLI not found. Install it
34
- with `npm i -g @procrastivity/clast` or see the README for other options."
34
+ If `CLAST_BIN` is still empty, tell the user: "clast-plumbing CLI not found.
35
+ Install it with `npm i -g @procrastivity/clast` or see the README for other
36
+ options."
35
37
 
36
- Use `$CLAST_BIN` in place of bare `clast` for all commands in this skill.
38
+ Use `$CLAST_BIN` in place of bare `clast-plumbing` for all commands in this skill.
37
39
 
38
40
  ## Step 1: Resolve the project
39
41
 
@@ -43,7 +45,7 @@ If the user passed a slug as an argument (`/wakeup xesapps`), use it directly. O
43
45
  $CLAST_BIN registry resolve "$(pwd)"
44
46
  ```
45
47
 
46
- If `pwd` doesn't resolve and no slug was given: print "Not in a registered project. Run `clast registry add .` first, or invoke as `/wakeup <slug>`." and stop.
48
+ If `pwd` doesn't resolve and no slug was given: print "Not in a registered project. Run `clast-plumbing registry add .` first, or invoke as `/wakeup <slug>`." and stop.
47
49
 
48
50
  ## Step 2: Gather data
49
51
 
@@ -103,7 +105,7 @@ Wakeup is read-only. Never invoke write-form subcommands (`entries write`, `brea
103
105
 
104
106
  ## Edge cases
105
107
 
106
- - **No entries for project**: print "No curated entries for `<slug>` yet. Run `/day-wakeup` to process recent sessions, or run `clast sessions --project <slug>` to see what's available." and stop.
108
+ - **No entries for project**: print "No curated entries for `<slug>` yet. Run `/day-wakeup` to process recent sessions, or run `clast-plumbing sessions --project <slug>` to see what's available." and stop.
107
109
  - **Slug resolves but no entries and no sessions**: print "Project `<slug>` registered but has no journal activity yet."
108
110
  - **Today's session count > 5**: summarize ("worked 12 sessions today, most recent 16:22 on branch `loop-guard-ngram`") rather than listing all.
109
111
 
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** (`clast`) snapshot, browse, and query your Claude Code session JSONL history.
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.
10
12
  - **Plugin** — installs skills (`/day-wakeup`, `/wakeup`) 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 cron or
21
- a SessionStart hook. See [`docs/reference/cli.md#clast-snapshot`](./docs/reference/cli.md#clast-snapshot)
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 # write a new entry
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 the
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,11 +59,11 @@ 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
69
  Breadcrumbs are append-only one-line notes for `/wakeup` and `/day-wakeup`.
@@ -70,17 +73,17 @@ for the full command contract.
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` / `clast doctor --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
 
@@ -90,8 +93,10 @@ for the current set of flags.
90
93
  ./install.sh ~/.local
91
94
  ```
92
95
 
93
- `make install` wraps the same script. Use `./uninstall.sh ~/.local` (or
94
- `make uninstall` for the default prefix) to remove the installed files. See
96
+ `make install` wraps the same script; `make install-local` installs the working
97
+ tree to `~/.local` with no sudo (and `make uninstall-local` removes it). Use
98
+ `./uninstall.sh ~/.local` (or `make uninstall` for the default prefix) to remove
99
+ the installed files. See
95
100
  [`docs/reference/repo-bootstrap.md#installsh--uninstallsh`](./docs/reference/repo-bootstrap.md#installsh--uninstallsh)
96
101
  for the rationale.
97
102
 
@@ -100,9 +105,9 @@ for the rationale.
100
105
  With Nix flakes enabled, you can use `clast` directly from the public flake:
101
106
 
102
107
  ```sh
103
- nix run github:procrastivity/clast -- whereami
104
108
  nix profile install github:procrastivity/clast
105
- 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
106
111
  ```
107
112
 
108
113
  For Home Manager or nix-darwin users, `overlays.default` exposes `pkgs.clast`.
@@ -133,9 +138,9 @@ The plugin can be installed from any local checkout, or via `npm install -g`
133
138
  (which puts `.claude-plugin/` under `npm root -g`); a centralized marketplace
134
139
  listing is a separate distribution channel deliberately not pursued for v1.
135
140
  Today the plugin ships a single `SessionStart` hook: every time a Claude Code
136
- session starts it backgrounds `clast snapshot`, so your journal stays current
137
- with zero manual effort. The hook is best-effort and silent: if the `clast` CLI
138
- 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
139
144
  [`docs/reference/plugin.md#hook-sessionstart`](./docs/reference/plugin.md#hook-sessionstart)
140
145
  for the hook's design rationale.
141
146
 
package/bin/clast CHANGED
@@ -1,93 +1,41 @@
1
1
  #!/usr/bin/env bash
2
- # clast — main dispatcher.
2
+ # clast — porcelain over clast-plumbing, with an OpenAI-compatible LLM
3
+ # provider. Owns the `wake` and `brief` subcommands. Every other verb is a
4
+ # clean error — the porcelain does not proxy to plumbing.
3
5
  #
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>`.
6
+ # Subcommand files live in $CLAST_LIB/clast-porcelain-subcommands/<name>.bash
7
+ # and each defines a single function `clast_cmd_<name>`.
7
8
  set -euo pipefail
8
9
 
9
10
  CLAST_LIB="${CLAST_LIB:-$(dirname "$(realpath "$0")")/../lib/clast}"
10
11
  export CLAST_LIB
11
12
 
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.
13
+ # shellcheck source=lib/clast/clast-porcelain-lib.bash
14
+ source "$CLAST_LIB/clast-porcelain-lib.bash"
30
15
 
31
16
  declare -a _CLAST_REMAINING=()
32
17
 
33
18
  while [[ $# -gt 0 ]]; do
34
19
  case "$1" in
35
20
  -h|--help|help)
36
- clast_usage
21
+ clast_porcelain_usage
37
22
  exit 0
38
23
  ;;
39
24
  --version)
40
- echo "clast $(clast_version)"
25
+ echo "clast $(clast_porcelain_version)"
41
26
  exit 0
42
27
  ;;
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
28
  --)
80
29
  shift
81
30
  _CLAST_REMAINING+=("$@")
82
31
  break
83
32
  ;;
84
33
  -*)
85
- clast_log_error "unknown global flag: $1"
86
- clast_usage >&2
34
+ clast_porcelain_log_error "unknown global flag: $1"
35
+ clast_porcelain_usage >&2
87
36
  exit 2
88
37
  ;;
89
38
  *)
90
- # First non-flag arg is the subcommand; stop parsing.
91
39
  _CLAST_REMAINING+=("$@")
92
40
  break
93
41
  ;;
@@ -95,7 +43,7 @@ while [[ $# -gt 0 ]]; do
95
43
  done
96
44
 
97
45
  if [[ ${#_CLAST_REMAINING[@]} -eq 0 ]]; then
98
- clast_usage
46
+ clast_porcelain_usage
99
47
  exit 0
100
48
  fi
101
49
 
@@ -103,70 +51,20 @@ set -- "${_CLAST_REMAINING[@]}"
103
51
 
104
52
  cmd="$1"; shift
105
53
 
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
54
  case "$cmd" in
117
- whereami)
118
- # shellcheck source=lib/clast/clast-subcommands/whereami.bash
119
- source "$CLAST_LIB/clast-subcommands/whereami.bash"
120
- clast_cmd_whereami "$@"
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 "$@"
151
- ;;
152
- registry)
153
- # shellcheck source=lib/clast/clast-subcommands/registry.bash
154
- source "$CLAST_LIB/clast-subcommands/registry.bash"
155
- clast_cmd_registry "$@"
156
- ;;
157
- stats)
158
- # shellcheck source=lib/clast/clast-subcommands/stats.bash
159
- source "$CLAST_LIB/clast-subcommands/stats.bash"
160
- clast_cmd_stats "$@"
55
+ wake)
56
+ # shellcheck source=lib/clast/clast-porcelain-subcommands/wake.bash
57
+ source "$CLAST_LIB/clast-porcelain-subcommands/wake.bash"
58
+ clast_cmd_wake "$@"
161
59
  ;;
162
- doctor)
163
- # shellcheck source=lib/clast/clast-subcommands/doctor.bash
164
- source "$CLAST_LIB/clast-subcommands/doctor.bash"
165
- clast_cmd_doctor "$@"
60
+ brief)
61
+ # shellcheck source=lib/clast/clast-porcelain-subcommands/brief.bash
62
+ source "$CLAST_LIB/clast-porcelain-subcommands/brief.bash"
63
+ clast_cmd_brief "$@"
166
64
  ;;
167
65
  *)
168
- clast_log_error "unknown subcommand '$cmd'"
169
- clast_usage >&2
66
+ clast_porcelain_log_error "unknown subcommand '$cmd'"
67
+ clast_porcelain_usage >&2
170
68
  exit 2
171
69
  ;;
172
70
  esac
@@ -0,0 +1,173 @@
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
+
22
+ # --- Global flag parsing -------------------------------------------------
23
+ #
24
+ # Walk argv before the subcommand name, peeling off any recognized global
25
+ # flag and setting the corresponding env var. Stop at the first non-flag
26
+ # arg (the subcommand) or at `--`. Remaining argv is passed to the
27
+ # subcommand untouched.
28
+ #
29
+ # `--json` and `--journal-dir`/`--projects-dir` are forwarded to the lib
30
+ # via env so subcommands can also accept them locally without re-parsing.
31
+
32
+ declare -a _CLAST_REMAINING=()
33
+
34
+ while [[ $# -gt 0 ]]; do
35
+ case "$1" in
36
+ -h|--help|help)
37
+ clast_usage
38
+ exit 0
39
+ ;;
40
+ --version)
41
+ echo "clast-plumbing $(clast_version)"
42
+ exit 0
43
+ ;;
44
+ --json)
45
+ export CLAST_JSON=1
46
+ shift
47
+ ;;
48
+ -v|--verbose)
49
+ export CLAST_VERBOSE=1
50
+ shift
51
+ ;;
52
+ -q|--quiet)
53
+ export CLAST_QUIET=1
54
+ shift
55
+ ;;
56
+ --journal-dir)
57
+ if [[ $# -lt 2 ]]; then
58
+ clast_log_error "--journal-dir requires a value"
59
+ exit 2
60
+ fi
61
+ export CLAST_JOURNAL_DIR="$2"
62
+ shift 2
63
+ ;;
64
+ --journal-dir=*)
65
+ export CLAST_JOURNAL_DIR="${1#*=}"
66
+ shift
67
+ ;;
68
+ --projects-dir)
69
+ if [[ $# -lt 2 ]]; then
70
+ clast_log_error "--projects-dir requires a value"
71
+ exit 2
72
+ fi
73
+ export CLAST_PROJECTS_DIR="$2"
74
+ shift 2
75
+ ;;
76
+ --projects-dir=*)
77
+ export CLAST_PROJECTS_DIR="${1#*=}"
78
+ shift
79
+ ;;
80
+ --)
81
+ shift
82
+ _CLAST_REMAINING+=("$@")
83
+ break
84
+ ;;
85
+ -*)
86
+ clast_log_error "unknown global flag: $1"
87
+ clast_usage >&2
88
+ exit 2
89
+ ;;
90
+ *)
91
+ # First non-flag arg is the subcommand; stop parsing.
92
+ _CLAST_REMAINING+=("$@")
93
+ break
94
+ ;;
95
+ esac
96
+ done
97
+
98
+ if [[ ${#_CLAST_REMAINING[@]} -eq 0 ]]; then
99
+ clast_usage
100
+ exit 0
101
+ fi
102
+
103
+ set -- "${_CLAST_REMAINING[@]}"
104
+
105
+ cmd="$1"; shift
106
+
107
+ # --- Subcommand dispatch -------------------------------------------------
108
+
109
+ # Map of stubbed subcommands → step number that will implement them.
110
+ # Future steps replace each stub with a real `source` + dispatch below.
111
+ _clast_stub() {
112
+ local name="$1" step="$2"
113
+ clast_log_error "$name is not yet implemented (planned for step $step)"
114
+ exit 2
115
+ }
116
+
117
+ case "$cmd" in
118
+ whereami)
119
+ # shellcheck source=lib/clast/clast-subcommands/whereami.bash
120
+ source "$CLAST_LIB/clast-subcommands/whereami.bash"
121
+ clast_cmd_whereami "$@"
122
+ ;;
123
+ snapshot)
124
+ # shellcheck source=lib/clast/clast-subcommands/snapshot.bash
125
+ source "$CLAST_LIB/clast-subcommands/snapshot.bash"
126
+ clast_cmd_snapshot "$@"
127
+ ;;
128
+ projects)
129
+ # shellcheck source=lib/clast/clast-subcommands/projects.bash
130
+ source "$CLAST_LIB/clast-subcommands/projects.bash"
131
+ clast_cmd_projects "$@"
132
+ ;;
133
+ sessions)
134
+ # shellcheck source=lib/clast/clast-subcommands/sessions.bash
135
+ source "$CLAST_LIB/clast-subcommands/sessions.bash"
136
+ clast_cmd_sessions "$@"
137
+ ;;
138
+ show)
139
+ # shellcheck source=lib/clast/clast-subcommands/show.bash
140
+ source "$CLAST_LIB/clast-subcommands/show.bash"
141
+ clast_cmd_show "$@"
142
+ ;;
143
+ entries)
144
+ # shellcheck source=lib/clast/clast-subcommands/entries.bash
145
+ source "$CLAST_LIB/clast-subcommands/entries.bash"
146
+ clast_cmd_entries "$@"
147
+ ;;
148
+ breadcrumb)
149
+ # shellcheck source=lib/clast/clast-subcommands/breadcrumb.bash
150
+ source "$CLAST_LIB/clast-subcommands/breadcrumb.bash"
151
+ clast_cmd_breadcrumb "$@"
152
+ ;;
153
+ registry)
154
+ # shellcheck source=lib/clast/clast-subcommands/registry.bash
155
+ source "$CLAST_LIB/clast-subcommands/registry.bash"
156
+ clast_cmd_registry "$@"
157
+ ;;
158
+ stats)
159
+ # shellcheck source=lib/clast/clast-subcommands/stats.bash
160
+ source "$CLAST_LIB/clast-subcommands/stats.bash"
161
+ clast_cmd_stats "$@"
162
+ ;;
163
+ doctor)
164
+ # shellcheck source=lib/clast/clast-subcommands/doctor.bash
165
+ source "$CLAST_LIB/clast-subcommands/doctor.bash"
166
+ clast_cmd_doctor "$@"
167
+ ;;
168
+ *)
169
+ clast_log_error "unknown subcommand '$cmd'"
170
+ clast_usage >&2
171
+ exit 2
172
+ ;;
173
+ esac