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
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: pip
directory: /docs
schedule:
interval: weekly
129 changes: 77 additions & 52 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,68 +12,93 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Check shell scripts parse correctly
- name: Shell lint
run: |
scripts="setup.sh install.sh verify.sh uninstall.sh update.sh bin/ccs skills/planning-with-files/scripts/check-complete.sh skills/planning-with-files/scripts/init-session.sh"
for f in $scripts; do bash -n "$f"; done
# shellcheck disable=SC2086
shellcheck -S style $scripts

- name: Scripts are executable
run: |
echo "Checking shell scripts..."
for f in setup.sh install.sh verify.sh uninstall.sh update.sh bin/ccs; do
echo " $f"
bash -n "$f"
[ -x "$f" ] || { echo "FAIL: $f is not executable"; exit 1; }
done
echo "All scripts parse OK"

- name: Check markdown internal links
- name: Python compiles
run: python3 -m py_compile docs/generate-pdf.py docs/generate-demo.py scripts/check_readme_anchors.py skills/planning-with-files/scripts/session-catchup.py

- name: README anchors resolve
run: python3 scripts/check_readme_anchors.py

- name: Command and skill headers
run: |
echo "Checking README.md internal links..."
# Extract anchor links from TOC and verify headings exist
grep -oP '\(#[a-z0-9-]+\)' README.md | tr -d '()' | while read -r anchor; do
heading="${anchor#\#}"
# GitHub converts headings: lowercase, spaces to -, strip special chars
if ! grep -iqP "^#{1,6}\s+.*$(echo "$heading" | sed 's/-/[- ]/g')" README.md; then
echo " WARNING: anchor $anchor may be broken"
fi
set -e
for f in commands/*.md; do
name="$(basename "${f%.md}")"
head -1 "$f" | grep -q "^## /$name " || { echo "$f: first line must be '## /$name - ...'"; exit 1; }
done
echo "Link check done"
f=skills/planning-with-files/SKILL.md
head -1 "$f" | grep -qx -- '---' || { echo "$f: missing frontmatter"; exit 1; }
grep -q '^name: planning-with-files$' "$f"
grep -q '^description: ' "$f"
echo "headers ok"

- name: Verify repo structure
- name: Required files present
run: |
echo "Checking required files exist..."
files=(
"setup.sh"
"install.sh"
"verify.sh"
"uninstall.sh"
"update.sh"
"bin/ccs"
"commands/rename-session.md"
"commands/standup.md"
"rules/session-naming.md"
"skills/planning-with-files/SKILL.md"
"templates/claude-md-snippet.md"
"completions/_ccs"
"completions/ccs.bash"
"docs/cheatsheet.md"
"docs/cheatsheet.pdf"
"LICENSE"
)
missing=0
for f in "${files[@]}"; do
if [ ! -f "$f" ]; then
echo " MISSING: $f"
missing=$((missing + 1))
fi
for f in setup.sh install.sh verify.sh uninstall.sh update.sh bin/ccs \
commands/rename-session.md commands/standup.md commands/wrapup.md \
commands/team-log.md commands/team-standup.md rules/session-naming.md \
skills/planning-with-files/SKILL.md templates/claude-md-snippet.md \
completions/_ccs completions/ccs.bash docs/cheatsheet.md docs/cheatsheet.pdf \
docs/requirements.txt LICENSE; do
[ -f "$f" ] || { echo "MISSING: $f"; missing=$((missing + 1)); }
done
if [ "$missing" -gt 0 ]; then
echo "$missing files missing!"
exit 1
[ "$missing" -eq 0 ]

- name: Local-only install, verify and uninstall against a temp CLAUDE_DIR
run: |
set -e
export CLAUDE_DIR="$RUNNER_TEMP/claude"
bash install.sh --local-only
for c in commands/*.md; do test -f "$CLAUDE_DIR/commands/$(basename "$c")"; done
test -f "$CLAUDE_DIR/skills/planning-with-files/SKILL.md"
test -f "$CLAUDE_DIR/rules/common/session-naming.md"
bash install.sh --local-only
test "$(grep -c 'Memory & Context System' "$CLAUDE_DIR/CLAUDE.md")" = 1
bash verify.sh --local-only
bash uninstall.sh --yes --local-only
for c in commands/*.md; do test ! -e "$CLAUDE_DIR/commands/$(basename "$c")"; done
test ! -e "$CLAUDE_DIR/rules/common/session-naming.md"
echo "install/verify/uninstall ok"

- name: ccs runs without its optional dependencies
run: |
bash bin/ccs --version
bash bin/ccs help > /dev/null

- name: No em or en dashes
run: |
if grep -rnP '[\x{2013}\x{2014}]' --include='*.md' --include='*.sh' --include='*.py' --include='*.yml' --include='ccs' . ; then
echo "dash characters found"; exit 1
fi
echo "All required files present"

- name: Check scripts are executable
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: System libraries for WeasyPrint
run: sudo apt-get update -q && sudo apt-get install -y -q libpango-1.0-0 libpangoft2-1.0-0 libharfbuzz-subset0
- name: Build the cheatsheet PDF
run: |
for f in setup.sh install.sh verify.sh uninstall.sh update.sh bin/ccs; do
if [ ! -x "$f" ]; then
echo "FAIL: $f is not executable"
exit 1
fi
done
echo "All scripts are executable"
pip install -r docs/requirements.txt
cd docs && python3 generate-pdf.py
test -s cheatsheet.pdf
- uses: actions/upload-artifact@v4
with:
name: cheatsheet
path: docs/cheatsheet.pdf
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ PRs welcome. Here's what's most useful:

## Before submitting

1. Run `bash -n` on any shell scripts you changed to check syntax
1. Run `shellcheck -S style` and `bash -n` on any shell scripts you changed (CI runs both)
2. If you changed `ccs`, test the affected subcommands
3. If you changed the cheatsheet, regenerate the PDF: `cd docs && python3 generate-pdf.py`
4. Keep the README concise - new sections should use `<details>` blocks when possible
. If you add a README section link, run `python3 scripts/check_readme_anchors.py`; CI fails on a dangling `(#anchor)`
6. CI also runs `install.sh --local-only`, `verify.sh --local-only` and `uninstall.sh --yes --local-only` against a temporary `CLAUDE_DIR`; keep those paths working

## What doesn't fit

Expand Down
30 changes: 22 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)
[![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux-lightgrey.svg)]()
[![Claude Code](https://img.shields.io/badge/Claude%20Code-compatible-D97757.svg)](https://docs.anthropic.com/en/docs/claude-code)
[![Claude Code](https://img.shields.io/badge/Claude%20Code-compatible-D97757.svg)](https://code.claude.com/docs)

**Stop losing context. Start every session where you left off.**

A curated toolkit that gives [Claude Code](https://docs.anthropic.com/en/docs/claude-code) persistent memory, cross-project search, structured planning, and session management - so you never repeat work across projects.
A curated toolkit that gives [Claude Code](https://code.claude.com/docs) persistent memory, cross-project search, structured planning, and session management - so you never repeat work across projects.

<p align="center">
<img src="assets/demo.svg" alt="ccs demo - search, resume, team mode" width="700">
Expand Down Expand Up @@ -82,7 +82,7 @@ flowchart LR

### Prerequisites

- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed and working
- [Claude Code](https://code.claude.com/docs) installed and working
- [Go 1.21+](https://go.dev/dl/) (for Ghost)
- [Ollama](https://ollama.com/) with the `nomic-embed-text` model (required by Ghost for embeddings)
- [uv](https://github.com/astral-sh/uv) (for cc-conversation-search) - or pip
Expand Down Expand Up @@ -125,12 +125,15 @@ cd claude-code-power-stack
./install.sh
```

Flags: `./install.sh --local-only` installs only the commands, skills, rules and CLAUDE.md snippet (no Ghost, Ollama, cc-conversation-search or `ccs` binary), and `CLAUDE_DIR=/path` targets another Claude config directory. `verify.sh` and `uninstall.sh` accept the same `--local-only` flag and `CLAUDE_DIR`; `uninstall.sh --yes` skips the confirmation prompt.

The install script will:
1. Install Ghost and register it as an MCP server
1. Install Ghost, make sure Ollama is running with the `nomic-embed-text` model, and register Ghost as an MCP server
2. Install cc-conversation-search and build the initial index
3. Copy the `/rename-session` command to your Claude Code config
4. Copy the planning-with-files skill to your Claude Code config
5. Update your CLAUDE.md with usage instructions
3. Copy every command in `commands/` (`/rename-session`, `/standup`, `/wrapup`, `/team-log`, `/team-standup`) to your Claude Code config
4. Copy the planning-with-files skill and the session-naming rule
5. Install the `ccs` shortcut and shell completions
6. Append the Memory & Context System section to your `~/.claude/CLAUDE.md`

### Manual install

Expand All @@ -146,7 +149,7 @@ uv tool install cc-conversation-search
cc-conversation-search init

# Commands and skills (copy to your Claude Code config)
cp commands/rename-session.md ~/.claude/commands/
cp commands/*.md ~/.claude/commands/
cp -r skills/planning-with-files ~/.claude/skills/
cp rules/session-naming.md ~/.claude/rules/common/
```
Expand Down Expand Up @@ -508,13 +511,16 @@ Your name is auto-detected from `git config user.name`.

```
claude-code-power-stack/
.github/workflows/ci.yml # shellcheck, README anchors, local-only install test, PDF build
setup.sh # curl one-liner remote installer
install.sh # Full local setup (7 steps)
update.sh # Update all components to latest
verify.sh # Post-install verification
uninstall.sh # Clean removal
bin/
ccs # Search shortcut (numbered results)
scripts/
check_readme_anchors.py # Fails CI when a README (#anchor) link has no heading
completions/
_ccs # zsh tab-completion
ccs.bash # bash tab-completion
Expand All @@ -532,7 +538,13 @@ claude-code-power-stack/
claude-md-snippet.md # CLAUDE.md additions
docs/
cheatsheet.md # One-page quick reference
cheatsheet.pdf # Printable version (regenerated by CI from cheatsheet.md)
workflow-guide.md # Detailed workflow guide
generate-pdf.py # cheatsheet.md -> cheatsheet.pdf (markdown + weasyprint)
generate-demo.py # Renders assets/demo.svg
requirements.txt # Pins for the two docs scripts
assets/
demo.svg # README hero animation
```

---
Expand Down Expand Up @@ -576,3 +588,5 @@ MIT
- [cc-conversation-search](https://github.com/akatz-ai/cc-conversation-search) by akatz-ai
- Planning-with-files based on [Manus](https://manus.im/) context engineering principles
- Maintained by [@bluzername](https://github.com/bluzername)

Dependency status (September 2026): Ghost is actively maintained. cc-conversation-search (0.5.x) has had no upstream commits since December 2025; its CLI still matches every call `ccs` makes (`init`, `index --all`, `search --json --limit --days --project`), and CI here checks the `ccs` wrapper on every push.
2 changes: 1 addition & 1 deletion bin/ccs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

set -euo pipefail

CCS_VERSION="1.5.0"
CCS_VERSION="1.6.0"
# Short aliases for team log: d=decision, f=finding, b=blocker, h=handoff
CCS_CACHE="${HOME}/.ccs_last_results"
CCS_REPO="${HOME}/.ccs_repo_path"
Expand Down
2 changes: 2 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
markdown==3.10.3
weasyprint==70.0
38 changes: 31 additions & 7 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,21 @@ set -euo pipefail
# https://github.com/bluzername/claude-code-power-stack

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CLAUDE_DIR="${HOME}/.claude"
CLAUDE_DIR="${CLAUDE_DIR:-${HOME}/.claude}"
LOCAL_ONLY="${POWER_STACK_LOCAL_ONLY:-0}"

for arg in "$@"; do
case "$arg" in
--local-only) LOCAL_ONLY=1 ;;
-h|--help)
echo "Usage: install.sh [--local-only]"
echo " --local-only Only install commands, skills, rules and the CLAUDE.md snippet"
echo " into \$CLAUDE_DIR (default ~/.claude). Skips Ghost, Ollama,"
echo " cc-conversation-search, the ccs binary and shell completions."
exit 0 ;;
*) echo "Unknown argument: $arg" >&2; exit 2 ;;
esac
done

# Colors
RED='\033[0;31m'
Expand All @@ -31,22 +45,22 @@ echo ""

MISSING=0

if ! command -v claude &>/dev/null; then
fail "Claude Code CLI not found. Install it first: https://docs.anthropic.com/en/docs/claude-code"
if [ "$LOCAL_ONLY" -eq 0 ] && ! command -v claude &>/dev/null; then
fail "Claude Code CLI not found. Install it first: https://code.claude.com/docs"
MISSING=1
fi

if ! command -v go &>/dev/null && ! command -v brew &>/dev/null; then
if [ "$LOCAL_ONLY" -eq 0 ] && ! command -v go &>/dev/null && ! command -v brew &>/dev/null; then
fail "Neither Go nor Homebrew found. Need one to install Ghost."
MISSING=1
fi

if ! command -v uv &>/dev/null && ! command -v pip &>/dev/null; then
if [ "$LOCAL_ONLY" -eq 0 ] && ! command -v uv &>/dev/null && ! command -v pip &>/dev/null; then
fail "Neither uv nor pip found. Need one to install cc-conversation-search."
MISSING=1
fi

if ! command -v ollama &>/dev/null; then
if [ "$LOCAL_ONLY" -eq 0 ] && ! command -v ollama &>/dev/null; then
fail "Ollama not found. Ghost requires Ollama for embeddings."
fail " Install: https://ollama.com/ or brew install ollama"
MISSING=1
Expand All @@ -58,7 +72,9 @@ if [ "$MISSING" -eq 1 ]; then
exit 1
fi

if [ ! -d "$CLAUDE_DIR" ]; then
if [ "$LOCAL_ONLY" -eq 1 ]; then
mkdir -p "$CLAUDE_DIR"
elif [ ! -d "$CLAUDE_DIR" ]; then
fail "Claude Code config directory not found at $CLAUDE_DIR"
fail "Run Claude Code at least once first."
exit 1
Expand All @@ -67,6 +83,8 @@ fi
ok "Prerequisites check passed"
echo ""

if [ "$LOCAL_ONLY" -eq 0 ]; then

# ------------------------------------------
# Step 1: Install Ghost
# ------------------------------------------
Expand Down Expand Up @@ -218,6 +236,8 @@ fi

echo ""

fi # LOCAL_ONLY

# ------------------------------------------
# Step 4: Copy commands, skills, and rules
# ------------------------------------------
Expand Down Expand Up @@ -257,6 +277,8 @@ fi

echo ""

if [ "$LOCAL_ONLY" -eq 0 ]; then

# ------------------------------------------
# Step 5: Install ccs shortcut
# ------------------------------------------
Expand Down Expand Up @@ -304,6 +326,8 @@ fi

echo ""

fi # LOCAL_ONLY

# ------------------------------------------
# Step 6: Update CLAUDE.md
# ------------------------------------------
Expand Down
Loading
Loading