@zalom/plastic 1.0.0-alpha.2 → 1.0.0-alpha.21

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.
Files changed (76) hide show
  1. package/PLASTIC.md +128 -473
  2. package/README.md +90 -58
  3. package/agents/future-intent-researcher.md +1 -1
  4. package/agents/intent-curator.md +1 -1
  5. package/bin/plastic.js +57 -0
  6. package/bin/test +28 -0
  7. package/deprecations.yml +7 -6
  8. package/hooks/auto-arm +5 -0
  9. package/hooks/bash-gate +3 -0
  10. package/hooks/check-update +12 -8
  11. package/hooks/code-gate +10 -0
  12. package/hooks/hooks.json +25 -4
  13. package/hooks/statusline +50 -10
  14. package/package.json +2 -2
  15. package/scripts/dashboard.rb +480 -0
  16. package/scripts/doctor.rb +973 -0
  17. package/scripts/hook-auto-arm +52 -0
  18. package/scripts/hook-bash-gate +53 -0
  19. package/scripts/hook-code-gate +39 -0
  20. package/scripts/hook-continue +15 -114
  21. package/scripts/hook-gate-check +19 -4
  22. package/scripts/hook-session-start +76 -31
  23. package/scripts/install.rb +91 -480
  24. package/scripts/lib/bridge.rb +255 -0
  25. package/scripts/lib/installer_core.rb +760 -0
  26. package/scripts/migrate-to-global +1 -1
  27. package/scripts/select-update-target +93 -0
  28. package/scripts/uninstall.rb +53 -0
  29. package/scripts/update.rb +142 -0
  30. package/scripts/versions.rb +141 -0
  31. package/skills/_active-intent-gate.md +26 -0
  32. package/skills/auto/SKILL.md +62 -9
  33. package/skills/auto/evals/evals.json +92 -0
  34. package/skills/auto/references/agent-architecture.md +60 -0
  35. package/skills/brainstorming/SKILL.md +143 -0
  36. package/skills/brainstorming-grill-me/SKILL.md +5 -5
  37. package/skills/continuing/SKILL.md +102 -77
  38. package/skills/continuing/evals/evals.json +136 -0
  39. package/skills/continuing/references/context-management.md +32 -0
  40. package/skills/creating-intent/SKILL.md +16 -1
  41. package/skills/creating-intent/references/lifecycle.md +74 -0
  42. package/skills/creating-intent/references/wikilinks.md +8 -0
  43. package/skills/creating-project/SKILL.md +8 -4
  44. package/skills/creating-project/references/hubs-projects.md +55 -0
  45. package/skills/dashboard/SKILL.md +92 -0
  46. package/skills/doctor/SKILL.md +116 -0
  47. package/skills/doctor/references/gates-stuck-detection.md +38 -0
  48. package/skills/doctor/report.md +96 -0
  49. package/skills/evaluating-skills/SKILL.md +140 -0
  50. package/skills/evaluating-skills/assets/eval-template.json +12 -0
  51. package/skills/evaluating-skills/evals/evals.json +75 -0
  52. package/skills/evaluating-skills/references/convention-checks.md +76 -0
  53. package/skills/evaluating-skills/references/eval-methodology.md +154 -0
  54. package/skills/executing-plan/SKILL.md +3 -3
  55. package/skills/install/SKILL.md +56 -8
  56. package/skills/intent-curator/SKILL.md +3 -3
  57. package/skills/linking-intents/SKILL.md +5 -1
  58. package/skills/linking-intents/references/zettelkasten.md +33 -0
  59. package/skills/managing-index/SKILL.md +5 -1
  60. package/skills/releasing/SKILL.md +119 -18
  61. package/skills/releasing/references/deprecations.md +44 -0
  62. package/skills/research/SKILL.md +114 -0
  63. package/skills/savepoint/SKILL.md +46 -37
  64. package/skills/savepoint/references/context-management.md +32 -0
  65. package/skills/uninstall/SKILL.md +39 -28
  66. package/skills/update/SKILL.md +41 -36
  67. package/skills/versions/SKILL.md +65 -0
  68. package/skills/writing-instructions/SKILL.md +159 -0
  69. package/skills/writing-instructions/references/agentskills-spec.md +135 -0
  70. package/skills/writing-plans/SKILL.md +183 -0
  71. package/templates/agents.md +16 -0
  72. package/templates/outcome.md +13 -0
  73. package/templates/project.yml +5 -0
  74. package/templates/savepoint.md +14 -13
  75. package/templates/spec.md +25 -0
  76. package/bin/install.js +0 -29
package/README.md CHANGED
@@ -1,87 +1,119 @@
1
1
  # Plastic
2
2
 
3
- > Intent-driven state management for AI coding sessions.
4
- > Named after **neuroplasticity** — adaptive, malleable, dynamic, resilient.
3
+ > **Alpha software.** Expect breaking changes between releases.
4
+ > Install: `npx @zalom/plastic@alpha --claude`
5
5
 
6
- ## What Is This?
6
+ Intent-driven idea development system for AI coding agents. Named after
7
+ **neuroplasticity**: adaptive, malleable, dynamic, resilient.
7
8
 
8
- Plastic implements two nested processes: **Build Observe Repeat** (Coordinator's continuous loop) and **What → Why → How → Next** (intent's finite lifecycle). Zettelkasten-inspired linking connects intents. All project state lives in `.plastic/`. Everything is an intent.
9
+ Plastic thinks in **intents**, not tasks. An intent is a desire, something
10
+ you want to accomplish, explore, or understand. Intents are atomic thoughts
11
+ that get developed through two nested processes.
9
12
 
10
- ## Installation
13
+ ## The Two Cycles
11
14
 
12
- ### 1. Register the marketplace
15
+ **Coordinator loop (B→O→R):** Brainstorm → Organize → Review. The human and
16
+ agent explore ideas, structure them into intents, and validate the results.
17
+ This loop runs continuously across sessions.
13
18
 
14
- In Claude Code, run:
15
- ```
16
- /plugin marketplace add zalom/plastic
17
- ```
19
+ **Intent lifecycle (W→W→H→E):** Why → What → How → Execute. Each intent moves
20
+ from motivation through specification, planning, to delivery. Intents produce
21
+ artifacts: `spec.md`, `plan.md`, `checklist.md`, `outcome.md`.
18
22
 
19
- ### 2. Install the plugin
23
+ ## How Plastic Works
20
24
 
21
- In Claude Code, run:
22
- ```
23
- /plugin add plastic@plastic
24
- ```
25
+ Plastic is a **thinking system**, a blueprint for taking a desire from intent to
26
+ delivery. It splits the work in two:
25
27
 
26
- ### 3. Initialize in your project
28
+ - **The blueprint (deterministic).** The conventions, templates, directory structure,
29
+ lifecycle, and linking rules. This is *how to fill in the work*, and it comes out
30
+ identically no matter who or what is working.
31
+ - **The brain (non-deterministic).** The human or LLM that does the actual thinking.
32
+ Plastic never replaces it. It only **steers and validates** it.
27
33
 
28
- In Claude Code, run:
29
- ```
30
- /plastic:install
31
- ```
34
+ Determinism lives in the **form** of the work (section sets, ordering, schemas, naming,
35
+ IDs, file layout), never in the brain's reasoning. The framework stays constant while the
36
+ thinking varies. Run Plastic on Claude Code, Codex, Hermes, OpenClaw, or by hand on paper
37
+ in Obsidian or Word, and the only thing that changes is the *quality of thought*. The
38
+ proof is the paper test: if a person with no tooling and no AI can reproduce a
39
+ correctly-shaped intent, the determinism is in the form, not the agent.
32
40
 
33
- ## Global vs Local
41
+ **Deterministic by design, free by intent.** The rigid part is rigid on purpose. It is
42
+ what makes work portable, reviewable, and resumable across any agent. The free part is
43
+ free on purpose. It is where the brain's creativity lives. Plastic draws the line between
44
+ the two and holds it.
34
45
 
35
- **Global (recommended):** Plastic stores all intents at `~/.plastic/`. Projects spawned by implementation intents get their own `.plastic/store/` for tactical intents.
46
+ **Harnesses are how it holds the line.** Shared harnesses (conventions, templates, and
47
+ directory structure) constrain humans and agents alike. Agent-extra harnesses (evals that
48
+ check a skill's output, plus hooks and instructions that steer reasoning) give an agent
49
+ the instincts a careful person already has: stop and save state, leave a note when the
50
+ context runs out, never plan before specifying.
36
51
 
37
- ```
38
- /plastic:install
39
- ```
52
+ This is **intent-driven delivery**, a new shape for the software lifecycle in the age of
53
+ agentic engineering. The unit of work is an *intent*, not a ticket, and every intent
54
+ carries its own spec, plan, checklist, and outcome as it moves through Why, What, How, and
55
+ Execute. What you get is agent-agnostic, auditable, and additive: a knowledge graph of
56
+ *why* things were built, not just what.
40
57
 
41
- **Local (testing):** Intents stored per-project in `.plastic/`. Useful for trying Plastic in a single project.
58
+ ## Install
42
59
 
43
- ```
44
- /plastic:install --local
60
+ Plastic requires Ruby (pre-installed on macOS/Linux) and Node.js 18+.
61
+
62
+ ```bash
63
+ # Alpha (current, active development)
64
+ npx @zalom/plastic@alpha --claude
65
+
66
+ # Beta (when available, API-stable, bug hunting)
67
+ npx @zalom/plastic@beta --claude
68
+
69
+ # Stable (when available, general use)
70
+ npx @zalom/plastic --claude
45
71
  ```
46
72
 
47
- ## Prerequisites
73
+ Replace `--claude` with `--codex` for Codex CLI, `--hermes` for Hermes, or
74
+ `--all` for all supported agents.
48
75
 
49
- Plastic hooks use Ruby for intent ID generation. Ruby is pre-installed on macOS/Linux. On Windows, use WSL or install Ruby from https://rubyinstaller.org/.
76
+ Bun users can substitute `bunx` for `npx` (e.g. `bunx @zalom/plastic@alpha --claude`).
77
+ Bun is never required.
50
78
 
51
- ## Directory Structure
79
+ Skills install as flat, hyphen-namespaced personal skills (`plastic-doctor`,
80
+ `plastic-auto`, and so on). Invoke them with a hyphen. Plastic is **not** a Claude Code
81
+ plugin; re-running the installer auto-removes any legacy plugin registration.
52
82
 
83
+ ### Updating
84
+
85
+ From within your agent, say "update plastic" or run:
86
+
87
+ ```bash
88
+ npx @zalom/plastic@alpha --claude
53
89
  ```
54
- .plastic/
55
- ├── AGENTS.md # Conventions contract for all agents
56
- ├── config.yml # Plugin configuration
57
- ├── INDEX.md # Brain's entry point
58
- └── store/
59
- └── ID--three-to-five-words/
60
- ├── {ID}--{slug}.md # Always present (e.g., 1a1--design-plastic.md)
61
- ├── spec.md # Optional (brainstorming output)
62
- ├── plan.md # Optional (implementation plan)
63
- ├── checklist.md # Optional (progress tracking)
64
- └── savepoint.md # Optional (session state)
65
- ```
66
90
 
67
- ## Skills
91
+ The `plastic-update` command shows available versions across all channels and
92
+ lets you choose which to install.
93
+
94
+ ## Quick Start
95
+
96
+ After installation, run `/clear` to load Plastic conventions, then:
97
+
98
+ 1. Say "new intent" or run `/plastic-creating-intent` to create your first intent
99
+ 2. Describe what you want to accomplish
100
+ 3. Use `/plastic-brainstorming` to explore the design
101
+ 4. Use `/plastic-writing-plans` to create an implementation plan
102
+ 5. Use `/plastic-executing-plan` to deliver it
103
+
104
+ Or say "auto" to let the agent handle the full lifecycle autonomously.
105
+
106
+ ## Documentation
68
107
 
69
- | Skill | Purpose |
70
- |-------|---------|
71
- | `install` | Initialize `.plastic/` in a new project |
72
- | `creating-intent` | Create a new intent with directory, hash, and INDEX.md entry |
73
- | `savepoint` | Save active intent state before context reset |
74
- | `continuing` | Resume from savepoint after `/clear` |
75
- | `linking-intents` | Connect intents via Zettelkasten links |
76
- | `managing-index` | Curate INDEX.md structure note |
77
- | `executing-plan` | Execute plans via subagent-driven (default) or inline mode |
108
+ - [`docs/architecture.md`](docs/architecture.md): system structure, the two
109
+ processes, the store layout, and the component map.
110
+ - [`docs/internals.md`](docs/internals.md): how Plastic stays deterministic, the
111
+ determinism breakdown, and the harness system.
78
112
 
79
- ## Agents
113
+ ## Conventions
80
114
 
81
- | Agent | Purpose |
82
- |-------|---------|
83
- | `intent-curator` | Maintains INDEX.md health, suggests links |
84
- | `future-intent-researcher` | Researches parked future intents |
115
+ All conventions live in `AGENTS.md`, distributed to `~/.plastic/AGENTS.md`
116
+ during installation. Run `plastic-doctor` to check installation health.
85
117
 
86
118
  ## License
87
119
 
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: plastic:future-intent-researcher
2
+ name: plastic-future-intent-researcher
3
3
  description: |
4
4
  Use this agent to research future intents autonomously. Picks up parked
5
5
  intents from INDEX.md, investigates them via web search and codebase analysis,
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: plastic:intent-curator
2
+ name: plastic-intent-curator
3
3
  description: |
4
4
  Use this agent when completing or reviewing intents, reorganizing the index,
5
5
  or when the intent store needs maintenance. Examples:
package/bin/plastic.js ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Thin shim — npx entry point that dispatches a subcommand to the matching Ruby verb script.
4
+ // All logic lives in scripts/<verb>.rb. JS is only the distribution + dispatch mechanism.
5
+ //
6
+ // npx @zalom/plastic install [flags]
7
+ // npx @zalom/plastic update [flags]
8
+ // npx @zalom/plastic uninstall [flags]
9
+ // npx @zalom/plastic versions [flags]
10
+ //
11
+ // Back-compat: a bare `--uninstall` (no subcommand) routes to uninstall with a deprecation
12
+ // warning; no subcommand at all defaults to install (legacy behaviour, one release).
13
+
14
+ import { execFileSync } from 'node:child_process'
15
+ import { resolve } from 'node:path'
16
+ import { existsSync } from 'node:fs'
17
+
18
+ const VERBS = ['install', 'update', 'uninstall', 'versions']
19
+ const packageRoot = new URL('..', import.meta.url).pathname
20
+ const argv = process.argv.slice(2)
21
+
22
+ let verb
23
+ let rest
24
+
25
+ if (VERBS.includes(argv[0])) {
26
+ verb = argv[0]
27
+ rest = argv.slice(1)
28
+ } else if (argv.includes('--uninstall')) {
29
+ // Deprecated: `--uninstall` as a flag instead of the `uninstall` subcommand.
30
+ console.error('! plastic: `--uninstall` is deprecated — use `npx @zalom/plastic uninstall`. (works for now)')
31
+ verb = 'uninstall'
32
+ rest = argv.filter((a) => a !== '--uninstall')
33
+ } else {
34
+ // No subcommand: legacy default to install (one release of grace).
35
+ verb = 'install'
36
+ rest = argv
37
+ }
38
+
39
+ const script = resolve(packageRoot, 'scripts', `${verb}.rb`)
40
+
41
+ if (!existsSync(script)) {
42
+ console.error(`Error: scripts/${verb}.rb not found in package.`)
43
+ process.exit(1)
44
+ }
45
+
46
+ try {
47
+ execFileSync('ruby', [script, ...rest], {
48
+ stdio: 'inherit',
49
+ env: { ...process.env, PLASTIC_PACKAGE_ROOT: packageRoot },
50
+ })
51
+ } catch (err) {
52
+ if (err.status) process.exit(err.status)
53
+ console.error('Error: Ruby is required to run Plastic.')
54
+ console.error(' macOS: Ruby is pre-installed')
55
+ console.error(' Linux: sudo apt install ruby / dnf install ruby')
56
+ process.exit(1)
57
+ }
package/bin/test ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ # Runs the FULL Minitest suite in a single process.
6
+ #
7
+ # `release.verify` used to be `ruby -Itest test/*_test.rb`, but Ruby runs only
8
+ # the first glob-expanded file as the program — the rest land in ARGV and are
9
+ # never required. The release gate exercised one test file, reported green, and
10
+ # let releases ship over real failures (intent 30). Pointing verify at this
11
+ # script keeps the runner in version control and guarantees every test file is
12
+ # loaded.
13
+
14
+ root = File.expand_path("..", __dir__)
15
+
16
+ files = Dir.glob(File.join(root, "test", "**", "*_test.rb")).sort
17
+ abort "No test files found under #{File.join(root, "test")}" if files.empty?
18
+
19
+ # `bin/test --list` prints the discovered files without running them, so the
20
+ # discovery logic can be tested cheaply (no full-suite execution).
21
+ if ARGV.delete("--list")
22
+ puts files.map { |f| f.sub("#{root}/", "") }
23
+ exit 0
24
+ end
25
+
26
+ $LOAD_PATH.unshift File.join(root, "test")
27
+ require "minitest/autorun"
28
+ files.each { |f| require f }
package/deprecations.yml CHANGED
@@ -12,12 +12,13 @@
12
12
  # link: optional URL to migration guide
13
13
 
14
14
  deprecations:
15
- - id: cc-plugin-to-npx
16
- severity: info
17
- summary: "Plastic distribution is moving from Claude Code plugin to npx install"
15
+ - id: cc-plugin-to-hyphen-skills
16
+ severity: warning
17
+ summary: "Plastic now ships as flat hyphen-named personal skills (plastic-doctor), not a Claude Code plugin. Invocation changed from plastic:<name> to plastic-<name>."
18
18
  migration_steps:
19
- - "Install new distribution: npx @zalom/plastic@latest"
20
- - "Verify: check that ~/.plastic/ is intact and hooks work"
21
- - "Remove old plugin: /plugin remove plastic"
19
+ - "Re-run the installer: npx @zalom/plastic@latest --claude (bunx also works)"
20
+ - "It auto-removes the old plugin/marketplace registration no /plugin step needed"
21
+ - "Invoke skills with a hyphen now: /plastic-doctor, /plastic-auto, etc."
22
+ - "Run /plastic-doctor to verify"
22
23
  introduced: "1.0.0"
23
24
  removal: "2.0.0"
package/hooks/auto-arm ADDED
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+ INPUT=$(cat)
3
+ MESSAGE=$(echo "$INPUT" | ruby -rjson -e 'puts JSON.parse(STDIN.read)["user_prompt"].to_s' 2>/dev/null || echo "")
4
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
+ ruby "$SCRIPT_DIR/../scripts/hook-auto-arm" "$MESSAGE"
@@ -0,0 +1,3 @@
1
+ #!/bin/bash
2
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
3
+ exec ruby "$SCRIPT_DIR/../scripts/hook-bash-gate"
@@ -1,11 +1,15 @@
1
1
  #!/bin/bash
2
- # plastic-hook-version: 1.0.0
3
- # Runs on SessionStart — checks npm for newer version, writes cache
2
+ # plastic-hook-version: 1.1.0
3
+ # Runs on SessionStart — checks npm for a newer version on the installed
4
+ # channel, writes cache. Channel-aware: queries dist-tags and picks the best
5
+ # upgrade target instead of blindly trusting the `latest` tag.
4
6
 
7
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5
8
  PLASTIC_HOME="$HOME/.plastic"
6
9
  CACHE_DIR="$PLASTIC_HOME/.cache"
7
10
  CACHE_FILE="$CACHE_DIR/update-check.json"
8
11
  VERSION_FILE="$PLASTIC_HOME/VERSION"
12
+ SELECTOR="$SCRIPT_DIR/../scripts/select-update-target"
9
13
 
10
14
  mkdir -p "$CACHE_DIR"
11
15
 
@@ -21,21 +25,21 @@ fi
21
25
 
22
26
  # Background check — don't block session start
23
27
  (
24
- RAW=$(npm view @zalom/plastic version 2>/dev/null)
25
- LATEST=$(echo "$RAW" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$')
28
+ TAGS=$(npm view @zalom/plastic dist-tags --json 2>/dev/null)
26
29
 
27
- if [ -z "$LATEST" ]; then
30
+ if [ -z "$TAGS" ]; then
28
31
  exit 0
29
32
  fi
30
33
 
34
+ TARGET=$(printf '%s' "$TAGS" | ruby "$SELECTOR" "$CURRENT" 2>/dev/null)
31
35
  CHECKED=$(date -u +%Y-%m-%dT%H:%M:%SZ)
32
36
 
33
- if [ "$LATEST" != "$CURRENT" ]; then
37
+ if [ -n "$TARGET" ]; then
34
38
  printf '{"current":"%s","latest":"%s","checked":"%s","updateAvailable":true}\n' \
35
- "$CURRENT" "$LATEST" "$CHECKED" > "$CACHE_FILE"
39
+ "$CURRENT" "$TARGET" "$CHECKED" > "$CACHE_FILE"
36
40
  else
37
41
  printf '{"current":"%s","latest":"%s","checked":"%s","updateAvailable":false}\n' \
38
- "$CURRENT" "$LATEST" "$CHECKED" > "$CACHE_FILE"
42
+ "$CURRENT" "$CURRENT" "$CHECKED" > "$CACHE_FILE"
39
43
  fi
40
44
  ) &
41
45
 
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+ INPUT=$(cat)
3
+ FILE_PATH=$(echo "$INPUT" | ruby -rjson -e 'data = JSON.parse(STDIN.read); puts data.dig("tool_params", "file_path") || data.dig("tool_input", "file_path") || ""' 2>/dev/null)
4
+
5
+ if [ -z "$FILE_PATH" ]; then
6
+ exit 0
7
+ fi
8
+
9
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
10
+ ruby "$SCRIPT_DIR/../scripts/hook-code-gate" "$FILE_PATH"
package/hooks/hooks.json CHANGED
@@ -29,6 +29,28 @@
29
29
  ]
30
30
  }
31
31
  ],
32
+ "PreToolUse": [
33
+ {
34
+ "matcher": "Write|Edit|NotebookEdit",
35
+ "hooks": [
36
+ {
37
+ "type": "command",
38
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook\" code-gate",
39
+ "statusMessage": "Checking lifecycle gate..."
40
+ }
41
+ ]
42
+ },
43
+ {
44
+ "matcher": "Bash",
45
+ "hooks": [
46
+ {
47
+ "type": "command",
48
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/run-hook\" bash-gate",
49
+ "statusMessage": "Checking lifecycle gate..."
50
+ }
51
+ ]
52
+ }
53
+ ],
32
54
  "PostToolUse": [
33
55
  {
34
56
  "matcher": "Write|Edit",
@@ -61,15 +83,14 @@
61
83
  "statusMessage": "Checking future intents..."
62
84
  }
63
85
  ]
64
- }
65
- ],
66
- "statusLine": [
86
+ },
67
87
  {
68
88
  "matcher": "",
69
89
  "hooks": [
70
90
  {
71
91
  "type": "command",
72
- "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/statusline\""
92
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/auto-arm\"",
93
+ "statusMessage": "Checking auto mode..."
73
94
  }
74
95
  ]
75
96
  }
package/hooks/statusline CHANGED
@@ -1,16 +1,56 @@
1
1
  #!/bin/bash
2
- # plastic-hook-version: 1.0.0
3
- # StatusLine hook — shows update available warning
2
+ # plastic-hook-version: 2.0.0
3
+ # StatusLine hook — chains user's original statusline, adds Plastic info
4
4
 
5
- CACHE_FILE="$HOME/.plastic/.cache/update-check.json"
5
+ INPUT=$(cat)
6
+
7
+ # --- Chain original statusline ---
8
+ ORIGINAL_CONFIG="$HOME/.plastic/.cache/original-statusline.json"
9
+ ORIGINAL_OUTPUT=""
10
+ if [ -f "$ORIGINAL_CONFIG" ]; then
11
+ ORIGINAL_CMD=$(grep -o '"command":"[^"]*"' "$ORIGINAL_CONFIG" 2>/dev/null | head -1 | cut -d'"' -f4)
12
+ if [ -z "$ORIGINAL_CMD" ]; then
13
+ ORIGINAL_CMD=$(grep -o '"command": "[^"]*"' "$ORIGINAL_CONFIG" 2>/dev/null | head -1 | sed 's/.*"command": "//;s/".*//')
14
+ fi
15
+ if [ -n "$ORIGINAL_CMD" ] && [ -x "$ORIGINAL_CMD" ]; then
16
+ ORIGINAL_OUTPUT=$(echo "$INPUT" | "$ORIGINAL_CMD" 2>/dev/null)
17
+ fi
18
+ fi
19
+
20
+ # --- Plastic status ---
21
+ PLASTIC_PARTS=""
6
22
 
7
- if [ ! -f "$CACHE_FILE" ]; then
8
- exit 0
23
+ # Active intent from INDEX.md
24
+ INDEX="$HOME/.plastic/INDEX.md"
25
+ if [ -f "$INDEX" ]; then
26
+ ACTIVE=$(sed -n '/^## Active$/,/^## /{/^- \[/p;}' "$INDEX" | head -1)
27
+ if [ -n "$ACTIVE" ]; then
28
+ INTENT=$(echo "$ACTIVE" | sed 's/^- \[\([^]]*\)\].*/\1/')
29
+ PLASTIC_PARTS="plastic: ${INTENT}"
30
+ fi
31
+ fi
32
+
33
+ # Update notification
34
+ CACHE_FILE="$HOME/.plastic/.cache/update-check.json"
35
+ if [ -f "$CACHE_FILE" ]; then
36
+ UPDATE_AVAILABLE=$(grep -o '"updateAvailable":true' "$CACHE_FILE" 2>/dev/null)
37
+ if [ -n "$UPDATE_AVAILABLE" ]; then
38
+ LATEST=$(grep -o '"latest":"[^"]*"' "$CACHE_FILE" 2>/dev/null | head -1 | cut -d'"' -f4)
39
+ CURRENT=$(grep -o '"current":"[^"]*"' "$CACHE_FILE" 2>/dev/null | head -1 | cut -d'"' -f4)
40
+ UPDATE_MSG="plastic update: $CURRENT -> $LATEST"
41
+ if [ -n "$PLASTIC_PARTS" ]; then
42
+ PLASTIC_PARTS="$PLASTIC_PARTS | $UPDATE_MSG"
43
+ else
44
+ PLASTIC_PARTS="$UPDATE_MSG"
45
+ fi
46
+ fi
9
47
  fi
10
48
 
11
- UPDATE_AVAILABLE=$(grep -o '"updateAvailable":true' "$CACHE_FILE" 2>/dev/null)
12
- if [ -n "$UPDATE_AVAILABLE" ]; then
13
- LATEST=$(grep -o '"latest":"[^"]*"' "$CACHE_FILE" | cut -d'"' -f4)
14
- CURRENT=$(grep -o '"current":"[^"]*"' "$CACHE_FILE" | cut -d'"' -f4)
15
- echo "Plastic update: $CURRENT → $LATEST — run /plastic:update"
49
+ # --- Combine output ---
50
+ if [ -n "$ORIGINAL_OUTPUT" ] && [ -n "$PLASTIC_PARTS" ]; then
51
+ echo "$ORIGINAL_OUTPUT | $PLASTIC_PARTS"
52
+ elif [ -n "$ORIGINAL_OUTPUT" ]; then
53
+ echo "$ORIGINAL_OUTPUT"
54
+ elif [ -n "$PLASTIC_PARTS" ]; then
55
+ echo "$PLASTIC_PARTS"
16
56
  fi
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@zalom/plastic",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.21",
4
4
  "description": "Intent-driven idea development system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
7
- "plastic": "bin/install.js"
7
+ "plastic": "bin/plastic.js"
8
8
  },
9
9
  "engines": {
10
10
  "node": ">=18.0.0"