Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .clinerules/memory-bank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Cline's Memory Bank

I am Cline, an expert software engineer with a unique characteristic: my memory resets completely between sessions. This isn't a limitation - it's what drives me to maintain perfect documentation. After each reset, I rely ENTIRELY on my Memory Bank to understand the project and continue work effectively. I MUST read ALL memory bank files at the start of EVERY task - this is not optional.

## Memory Bank Structure

The Memory Bank consists of core files and optional context files, all in Markdown format. Files build upon each other in a clear hierarchy:

### Core Files (Required)

1. `projectbrief.md` - Foundation document that shapes all other files
- Created at project start if it doesn't exist
- Defines core requirements and goals
- Source of truth for project scope
2. `productContext.md` - Why this project exists
- Problems it solves
- How it should work
- User experience goals
3. `activeContext.md` - Current work focus
- Recent changes
- Next steps
- Active decisions and considerations
- Important patterns and preferences
- Learnings and project insights
4. `systemPatterns.md` - System architecture
- Key technical decisions
- Design patterns in use
- Component relationships
- Critical implementation paths
5. `techContext.md` - Technologies used
- Development setup
- Technical constraints
- Dependencies
- Tool usage patterns
6. `progress.md` - What works
- What's left to build
- Current status
- Known issues
- Evolution of project decisions

### Additional Context

Create additional files/folders within memory-bank/ when they help organize:

- Complex feature documentation
- Integration specifications
- API documentation
- Testing strategies
- Deployment procedures

## Documentation Updates

Memory Bank updates occur when:

1. Discovering new project patterns
2. After implementing significant changes
3. When user requests with **update memory bank** (MUST review ALL files)
4. When context needs clarification

REMEMBER: After every memory reset, I begin completely fresh. The Memory Bank is my only link to previous work. It must be maintained with precision and clarity, as my effectiveness depends entirely on its accuracy.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# Ignore local Claude Code state, but track the shared, committed settings.
.claude/*
!.claude/settings.json
# Cline plugin install artifacts (e.g. from `cline plugin install ./ --cwd .`).
.cline/plugins/
.DS_Store
node_modules/
.eval-magic
14 changes: 13 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ Slow-powers is a set of software development methodology skills and meta skill-w

## What lives here

This repo ships Slow-powers across three harnesses:
This repo ships Slow-powers across four harnesses:

- `skills/` — Skills, assets, and cross-cutting tests
- `.claude-plugin/` — Claude Code plugin
- `.codex-plugin/` — OpenAI Codex plugin
- `opencode/` — OpenCode plugin (`@slowdini/slow-powers-opencode`)
- `cline/` — Cline plugin (CLI/SDK/Kanban only; declared via the `cline`
field in `package.json`, with `skills/` auto-discovered from the package
root)

Cline-specific setup for working on this repo also lives at root:

- `.clinerules/` — Cline rules (the Memory Bank custom instructions)
- `memory-bank/` — Cline Memory Bank files recording ongoing work

## Editing the right files

Expand Down Expand Up @@ -69,3 +77,7 @@ bun run check
(pre-commit runs typecheck + lint-staged; pre-push runs the test suite).

`bun scripts/bump-version.ts <version>` updates every manifest in lockstep.

To test the Cline integration live: `cline plugin install ./ --cwd <scratch-dir>`,
run a Cline session in the scratch dir, then
`cline plugin uninstall slow-powers --cwd <scratch-dir>` when done.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Slow-powers is a fork of [obra/superpowers](https://github.com/obra/superpowers)

## Quickstart

[Claude Code](#claude-code) · [Codex CLI](#codex-cli) · [OpenCode](#opencode)
[Claude Code](#claude-code) · [Codex CLI](#codex-cli) · [OpenCode](#opencode) · [Cline](#cline)

## How it works

Expand Down Expand Up @@ -99,6 +99,17 @@ You can also browse and install it interactively: run `codex`, open
opencode plugin @slowdini/slow-powers-opencode -g
```

### Cline

```bash
cline plugin install https://github.com/slowdini/slow-powers.git
```

Cline plugins load in the Cline CLI, SDK, and Kanban — **not** the VSCode or
JetBrains extensions. On those, you can still use the skills by copying or
symlinking `skills/` into `.cline/skills/` (project) or `~/.cline/skills/`
(global); the bootstrap injection and plan gate are CLI/SDK/Kanban-only.

## The skills

Slow-powers provides a set of highly focused skills that ensure your agent operates with maximum discipline:
Expand Down Expand Up @@ -151,8 +162,9 @@ Flat layout — skills and assets live at root, harness-specific integration liv
- `.claude-plugin/` — Claude Code plugin manifest and hooks
- `.codex-plugin/` — OpenAI Codex plugin manifest
- `opencode/` — OpenCode plugin
- `cline/` — Cline plugin entry point
- `.claude-plugin/marketplace.json` — Claude Code marketplace registry
- `package.json` — OpenCode plugin manifest + dev tooling
- `package.json` — OpenCode + Cline plugin manifests + dev tooling

## Releasing

Expand Down
127 changes: 127 additions & 0 deletions cline/plugins/slow-powers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* Slow-powers plugin for Cline (CLI / SDK / Kanban).
*
* Two jobs, mirroring what the bash hooks do on Claude Code and Codex:
*
* 1. BOOTSTRAP INJECTION — registers the contents of bootstrap.md as a session
* rule, so the skill-enforcement block is part of every session's system
* prompt. This replaces the SessionStart-hook injection used on Claude/Codex
* and the system-prompt transform used on OpenCode.
*
* 2. PLAN GATE — the FIRST switch_to_act_mode call of a conversation is skipped
* with an instruction to run the hardening-plans skill on the plan first.
* switch_to_act_mode is how Cline presents a finished plan and leaves plan
* mode; skipping it keeps the session in plan mode, so the agent can load
* the skill, fix findings inline, and re-submit a hardened plan. The
* re-submission finds the per-conversation marker and is allowed through.
*
* WHY DENY-ONCE (and not deny-until-proven-hardened): keying the marker per
* conversation and allowing the second attempt guarantees we can never
* hard-lock a user inside plan mode. Worst case (agent re-submits without
* hardening) degrades to no-gate behavior — never worse. Same argument as
* hooks/exit-plan-mode.
*
* Skills need no wiring here: when this package is installed as a Cline
* plugin, the top-level skills/ directory is discovered automatically.
*
* Single-file plugin constraint: only Node builtins may be imported at
* runtime; @cline/* packages are host-provided and referenced in JSDoc only.
*/

import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";

const PLUGIN_DIR = path.dirname(fileURLToPath(import.meta.url));
const BOOTSTRAP_PATH = path.resolve(PLUGIN_DIR, "../../bootstrap.md");

// Module-level cache: bootstrap.md does not change during a session, so read
// it once. undefined = not yet loaded, null = missing/unreadable.
let _bootstrapCache;

function getBootstrapContent() {
if (_bootstrapCache !== undefined) return _bootstrapCache;
try {
_bootstrapCache = fs.readFileSync(BOOTSTRAP_PATH, "utf8");
} catch {
_bootstrapCache = null;
}
return _bootstrapCache;
}

// Pick a key that is stable across the skip and the re-submit. conversationId
// is the natural choice; fall back to agentId, then a fixed key. Any
// consistent key preserves deny-once safety.
function conversationKey(context) {
const snapshot = context?.snapshot;
const raw = snapshot?.conversationId ?? snapshot?.agentId ?? "fallback";
// Sanitize to a safe, bounded filename component (mirrors the bash hooks).
return String(raw)
.replace(/[^A-Za-z0-9._-]/g, "_")
.slice(0, 128);
}

function markerPath(context) {
return path.join(
process.env.SLOW_POWERS_PLAN_GATE_DIR ?? os.tmpdir(),
`slow-powers-plan-gate-${conversationKey(context)}`,
);
}

const SKIP_REASON =
"A plan is about to be presented. Before it leaves your hands, use the " +
"hardening-plans skill to review the plan file as a skeptical executor, " +
"then call switch_to_act_mode again to present the hardened plan.";

/** @type {import("@cline/sdk").AgentPlugin} */
const SlowPowersPlugin = {
name: "slow-powers",
manifest: {
capabilities: ["hooks", "rules"],
},

setup(api) {
const bootstrap = getBootstrapContent();
if (!bootstrap) return;
api.registerRule({
id: "slow-powers/bootstrap",
source: "slow-powers",
content: bootstrap,
});
},

hooks: {
beforeTool(context) {
try {
// The runtime passes both `tool` (the AgentTool definition) and
// `toolCall` (the pending call). First-party guards read `tool.name`;
// the plugin docs read `toolCall.name`. Accept either shape.
const toolName = context?.tool?.name ?? context?.toolCall?.name;
if (toolName !== "switch_to_act_mode") return undefined;

const marker = markerPath(context);
if (fs.existsSync(marker)) {
// Re-submission after hardening — let the plan be presented.
return undefined;
}

// First switch_to_act_mode this conversation: record it, then skip
// once to insert the hardening-plans beat. Best-effort marker write —
// a failed write must not break the gate (fail-open below covers it).
try {
fs.writeFileSync(marker, "");
} catch {
// Ignore: worst case the gate fires again on the next attempt.
}

return { skip: true, reason: SKIP_REASON };
} catch {
// Fail open: a plugin error must never block the user's workflow.
return undefined;
}
},
},
};

export default SlowPowersPlugin;
77 changes: 77 additions & 0 deletions memory-bank/activeContext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Active Context

## Current focus

Cline support was just added (August 2026). Two halves:

1. **Cline plugin** (`cline/plugins/slow-powers.js`, declared via the `cline`
field in `package.json`): registers `bootstrap.md` as a session rule and
gates the first `switch_to_act_mode` of each conversation on
hardening-plans (skip-once + tmp marker, mirroring `hooks/exit-plan-mode`).
Skills are auto-discovered from the package root — no wiring needed.
2. **Repo-local Cline setup**: `.clinerules/memory-bank.md` (canonical Memory
Bank instructions) and this `memory-bank/` directory, both committed.

## Recent changes

- `cline/plugins/slow-powers.js` (new), `package.json` `cline` field + `files`
- `tests/harness/spec.ts` Cline entry; Cline assertions in `manifests.test.ts`;
new `tests/harness/cline-plugin.test.ts`
- README Cline install section; AGENTS.md four-harness update;
`.gitignore` covers `.cline/plugins/` install artifacts

## Verification results (Cline CLI 3.0.51, headless)

- `cline plugin install <repo> --cwd <scratch>` works; installer copies the
repo and registers the plugin entry.
- Live session: all 8 skills discovered; `<EXTREMELY-IMPORTANT>` bootstrap
block present in instructions; bootstrap behavior observed (agent invoked a
skill on a ~1% match, per the bootstrap rule).
- Plan gate: unit-tested against the documented `AgentBeforeToolResult`
contract. The runtime's `skip` handling (tool doesn't run, `reason` goes to
the model) and the hook context shape were confirmed in the shipped CLI
source — the first-party `core.plan-mode-command-guard` extension uses the
same pattern. `switch_to_act_mode` is NOT exposed in headless one-shot
sessions, so an interactive (TUI) confirmation of the gate firing is the one
remaining manual check.

## Next steps

- PR opened: https://github.com/slowdini/slow-powers/pull/266 (base `dev`).
- Manually confirm the plan gate in an interactive `cline -i` plan-mode
session (present plan → approve → first `switch_to_act_mode` gets skipped
with the hardening instruction) — easiest via a test release, per the
maintainer.
- After merge to `dev`: trigger the Release PR workflow with the next version
to ship the Cline plugin (that release doubles as the test release).

## Active decisions

- Distribution reuses the root `package.json` (git install); no separate npm
package or release-workflow change.
- The Cline gate is skip-once only. The already-hardened short-circuit
(upstream #153 refinement) is deferred — it needs reliable detection that
hardening-plans already ran (the skill-invocation tool is `skills` in the
Cline runtime).
- No `.cline/skills/` dogfooding symlinks: Cline's skill registry is
last-wins with plugin dirs scanned *after* workspace dirs, so an installed
slow-powers plugin would silently shadow the repo's skills. The
installed-vs-repo precedence question is deferred to a separate
cross-harness exploration (it affects all harnesses).

## Learnings

- Cline plugins load only in CLI/SDK/Kanban — not VSCode/JetBrains. IDE users
get skills via manual copy into `.cline/skills/` or `~/.cline/skills/`.
- Cline reads `AGENTS.md` natively; no memory-file symlink needed for it.
- Cline's plan-exit tool is `switch_to_act_mode`; `AgentBeforeToolResult.skip`
+ `reason` is the deny mechanism; `registerRule` puts content in the system
prompt every session.
- Hook contexts pass the tool name on BOTH `tool.name` (first-party shape) and
`toolCall.name` (docs shape) — read `tool?.name ?? toolCall?.name`.
- Headless one-shot sessions (`cline -p "..."`) don't expose
`switch_to_act_mode` and can't drive TTY-only commands (`cline config`); use
interactive sessions for plan-gate verification.
- Cline's local plugin install copies dotfile-free repo content — everything
the plugin needs (`cline/`, `skills/`, `bootstrap.md`) is a normal path, so
this is fine.
26 changes: 26 additions & 0 deletions memory-bank/productContext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Product Context

## Why this exists

Coding agents under pressure skip discipline: they present unreviewed plans,
claim success without running tests, thrash on bugs with guess-and-check, and
let new work collide with in-progress branches. Slow-powers exists to put that
discipline back — not by replacing harness features, but by hardening them
(plan-mode gates, skill-enforcement bootstrap, verification loops).

## How it should work

- A bootstrap block (`bootstrap.md`) is injected into every session, making
skill use non-negotiable when a skill applies.
- Skills declare prerequisite / next-step gates so the agent follows an
intended sequence (plan → harden → isolate → TDD → verify).
- Harness hooks/plugins supply the deterministic beats a skill can't enforce
on its own (e.g. gating plan presentation on hardening-plans).

## User experience goals

- Install once per harness, then forget it — the value shows up as plans that
don't hallucinate files, tests that exist before code, and success claims
backed by command output.
- "The plugin for people who don't install plugins": minimal surface, no
config, no lock-in; users can extend with their own evaluated skills.
Loading
Loading