diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index d53695515..588680411 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -375,7 +375,7 @@ { "name": "github-app", "description": "Automatic GitHub App token lifecycle for Claude Code sessions. Generates installation tokens on session start, monitors expiry via PreToolUse hook, and refreshes transparently before commands that need authentication.", - "version": "0.3.1", + "version": "0.3.2", "author": { "name": "Nathan Heaps" }, @@ -755,23 +755,24 @@ ] }, { - "name": "task-parallelization", - "description": "Intelligent skill that helps Claude parallelize Task tool calls when working on repetitive or batch operations, optimizing throughput based on task complexity", - "version": "0.2.25", + "name": "task-utils", + "description": "Unified task management plugin — commit-on-complete, session awareness, active-task guard, stop guard, and provider-based task sync. Consolidates todo-plus-plus, todo-sync, and task-parallelization.", + "version": "0.1.0", "author": { "name": "Nathan Heaps" }, - "source": "./plugins/task-parallelization", + "source": "./plugins/task-utils", "category": "utility", "tags": ["utility", "skill"], "keywords": [ + "tasks", + "commit", + "workflow", + "ephemeral", "parallelization", - "task", - "agent", - "batch", - "performance", - "optimization", - "concurrent" + "sync", + "agent-teams", + "productivity" ] }, { @@ -798,30 +799,6 @@ "tags": ["utility", "command", "skill"], "keywords": ["tmux", "subagent", "parallel", "iterm", "terminal", "isolation", "delegation"] }, - { - "name": "todo-plus-plus", - "description": "Enforces commit-on-complete for tasks and reminds about ephemeral session awareness", - "version": "0.1.5", - "author": { - "name": "Nathan Heaps" - }, - "source": "./plugins/todo-plus-plus", - "category": "utility", - "tags": ["utility", "skill"], - "keywords": ["tasks", "commit", "workflow", "ephemeral", "agent-teams"] - }, - { - "name": "todo-sync", - "description": "Automatically syncs todos and plans from ~/.claude/ to the current project's .claude/ directory", - "version": "0.2.4", - "author": { - "name": "Nathan Heaps" - }, - "source": "./plugins/todo-sync", - "category": "utility", - "tags": ["utility", "skill"], - "keywords": ["todos", "plans", "sync", "workflow", "productivity"] - }, { "name": "web-auto-approve", "description": "Auto-approve Edit, Write, and Bash permission requests in Claude Code web sessions to suppress interactive permission prompts", diff --git a/.claude/settings.json b/.claude/settings.json index e22892c2f..bc11697d9 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -130,7 +130,6 @@ "mise@ai-mktpl": true, "scm-utils@ai-mktpl": true, "sequential-thinking@ai-mktpl": false, - "todo-sync@ai-mktpl": false, "web-auto-approve@ai-mktpl": true }, "extraKnownMarketplaces": { diff --git a/plugins/github-app/.claude-plugin/plugin.json b/plugins/github-app/.claude-plugin/plugin.json index 2e23c0e64..d247207e0 100644 --- a/plugins/github-app/.claude-plugin/plugin.json +++ b/plugins/github-app/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "github-app", - "version": "0.3.1", + "version": "0.3.2", "description": "Automatic GitHub App token lifecycle for Claude Code sessions. Generates installation tokens on session start, monitors expiry via PreToolUse hook, and refreshes transparently before commands that need authentication.", "author": { "name": "Nathan Heaps", diff --git a/plugins/renovate/skills/renovate-setup/SKILL.md b/plugins/renovate/skills/renovate-setup/SKILL.md index 6a5fb0730..0ddf8fee3 100644 --- a/plugins/renovate/skills/renovate-setup/SKILL.md +++ b/plugins/renovate/skills/renovate-setup/SKILL.md @@ -44,10 +44,10 @@ The correct file name changed from `default.json` to `default.json5`: ```json5 // renovate.json5 { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": [ - "github>nsheaps/renovate-config" // uses default.json5 automatically - ] + $schema: "https://docs.renovatebot.com/renovate-schema.json", + extends: [ + "github>nsheaps/renovate-config", // uses default.json5 automatically + ], } ``` @@ -59,33 +59,41 @@ settings, schedule, package rules, etc.). When a Renovate PR is stuck and not auto-merging: 1. **Repo setting enabled?** + ```bash gh api repos/nsheaps/ --jq '.allow_auto_merge' # should return: true ``` 2. **PR has auto-merge queued?** + ```bash gh pr view --repo nsheaps/ --json autoMergeRequest # autoMergeRequest should be non-null ``` + If null, enable it: + ```bash gh pr merge --repo nsheaps/ --auto --squash ``` 3. **Branch protection / rulesets blocking?** + ```bash gh api repos/nsheaps//rules/branches/main ``` + Common blockers: - `pull_request` rule requiring `required_approving_review_count: 1` → approve the PR - Required status checks that aren't running → check CI config 4. **Required status checks failing?** + ```bash gh pr view --repo nsheaps/ --json statusCheckRollup ``` + Empty `statusCheckRollup` + BLOCKED usually means a required check is configured but no CI run has happened (missing workflow trigger or CI never ran). diff --git a/plugins/task-parallelization/.claude-plugin/plugin.json b/plugins/task-parallelization/.claude-plugin/plugin.json deleted file mode 100644 index 51dc0738d..000000000 --- a/plugins/task-parallelization/.claude-plugin/plugin.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "task-parallelization", - "version": "0.2.25", - "description": "Intelligent skill that helps Claude parallelize Task tool calls when working on repetitive or batch operations, optimizing throughput based on task complexity", - "author": { - "name": "Nathan Heaps", - "email": "nsheaps@gmail.com", - "url": "https://github.com/nsheaps" - }, - "homepage": "https://github.com/nsheaps/ai-mktpl/tree/main/plugins/task-parallelization", - "keywords": [ - "parallelization", - "task", - "agent", - "batch", - "performance", - "optimization", - "concurrent" - ] -} diff --git a/plugins/task-parallelization/CHANGELOG.md b/plugins/task-parallelization/CHANGELOG.md deleted file mode 100644 index b3333c5bf..000000000 --- a/plugins/task-parallelization/CHANGELOG.md +++ /dev/null @@ -1,77 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines. - -## 0.2.24 (2026-01-16) - -## 0.2.23 (2026-01-16) - -## 0.2.22 (2026-01-16) - -## 0.2.21 (2026-01-16) - -## 0.2.20 (2026-01-16) - -## 0.2.19 (2026-01-16) - -## 0.2.18 (2026-01-16) - -## 0.2.17 (2026-01-16) - -## 0.2.16 (2026-01-16) - -## 0.2.15 (2026-01-16) - -## 0.2.14 (2026-01-16) - -## 0.2.13 (2026-01-16) - -## 0.2.12 (2026-01-16) - -## 0.2.11 (2026-01-16) - -### Bug Fixes - -- improve version bump workflow and CI integration ([#73](https://github.com/nsheaps/.ai/issues/73)) ([d89cca3](https://github.com/nsheaps/.ai/commit/d89cca31f5691fbe1bf11dd5f21b8800ccae3c41)) - -## 0.2.10 (2026-01-16) - -## 0.2.9 (2026-01-16) - -## 0.2.8 (2026-01-16) - -## 0.2.7 (2026-01-16) - -## 0.2.6 (2026-01-16) - -## 0.2.5 (2026-01-16) - -## 0.2.4 (2026-01-16) - -## 0.2.3 (2026-01-16) - -## 0.2.2 (2026-01-16) - -### Bug Fixes - -- **self-terminate:** traverse process tree to find Claude ([9caa408](https://github.com/nsheaps/.ai/commit/9caa408369b3120868927b2d5f0cbdeca71aef5a)) - -## 0.2.1 (2026-01-16) - -### Features - -- add self-terminate plugin for graceful session exit ([9d120e8](https://github.com/nsheaps/.ai/commit/9d120e88d621263049463073af9750b99259a5c2)) - -## 0.0.8 (2026-01-16) - -## 0.0.7 (2026-01-16) - -## 0.0.6 (2026-01-16) - -## 0.0.5 (2026-01-16) - -## 0.0.4 (2026-01-16) - -## 0.0.3 (2026-01-16) - -## 0.0.2 (2026-01-16) diff --git a/plugins/task-parallelization/README.md b/plugins/task-parallelization/README.md deleted file mode 100644 index b9bb460ec..000000000 --- a/plugins/task-parallelization/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# Task Parallelization Plugin - -An intelligent skill that helps Claude Code parallelize Task tool calls when working on batch operations, repetitive changes, or research tasks. - -## Overview - -When you ask Claude to perform the same operation across many items (files, components, services), this skill automatically guides Claude to: - -1. **Identify parallelizable work** - Recognize when tasks can run concurrently -2. **Assess optimal parallelization** - Determine how many tasks to run in parallel based on complexity -3. **Execute efficiently** - Batch and run tasks for maximum throughput -4. **Handle failures gracefully** - Retry failed tasks and report results clearly - -## Features - -### Intelligent Parallelization Levels - -The skill defines 5 parallelization levels based on task characteristics: - -| Level | Concurrent Tasks | Use Case | -| -------------- | ---------------- | ---------------------------------------------- | -| **Maximum** | 8-10 | Read-only research, exploration, analysis | -| **High** | 5-7 | Simple templated changes, bulk updates | -| **Moderate** | 3-4 | Refactoring, migrations, context-aware changes | -| **Limited** | 2 | Complex logic, subtle dependencies | -| **Sequential** | 1 | Explicit dependencies, shared state | - -### Automatic Complexity Assessment - -The skill evaluates each batch operation for: - -- Task independence (can tasks run without affecting each other?) -- Resource requirements (CPU, memory, I/O intensity) -- Failure impact (what happens if one task fails?) -- Task complexity (simple pattern vs. complex reasoning) - -### Model Selection Guidance - -For cost-effective parallel execution: - -- **haiku**: Simple, repetitive tasks (renaming, imports, templated edits) -- **sonnet**: Moderate complexity (refactoring, documentation) -- **opus**: Complex reasoning (architecture, debugging) - -## Example Use Cases - -### High Parallelization Examples - -``` -"Research how 10 different libraries handle authentication" -"Add the same import to all 50 component files" -"Check which of these 20 APIs are still active" -``` - -### Moderate Parallelization Examples - -``` -"Refactor these 15 functions to use the new error handling pattern" -"Update all configuration files to the new schema" -"Add JSDoc comments to all exported functions" -``` - -### Sequential Examples - -``` -"Create the base class, then create all derived classes" -"Update the API schema, then update all callers" -``` - -## Installation - -See [Installation Guide](../../docs/installation.md) for all installation methods. - -### Quick Install - -```bash -# Via marketplace (recommended) -# Follow marketplace setup: ../../docs/manual-installation.md - -# Or via GitHub -claude plugins install github:nsheaps/ai-mktpl/plugins/task-parallelization - -# Or locally for testing -cc --plugin-dir /path/to/plugins/task-parallelization -``` - -## How It Works - -When you make a request that involves repetitive or batch operations, Claude will: - -1. **Recognize the pattern** - Identify that multiple similar tasks need to be performed -2. **Consult this skill** - Use the parallelization guidelines to plan execution -3. **Create task batches** - Group independent tasks based on the recommended parallelization level -4. **Execute in parallel** - Launch multiple Task agents concurrently -5. **Aggregate results** - Collect and summarize outcomes from all tasks - -## Best Practices - -### Do - -- Be specific about what needs to change across items -- Provide examples of the expected transformation -- Mention if there are any dependencies between items - -### Don't - -- Ask to parallelize tasks that modify the same file -- Expect shared context between parallel tasks -- Assume order of completion matches order of launch - -## License - -MIT License - See repository root for details. diff --git a/plugins/task-utils/.claude-plugin/plugin.json b/plugins/task-utils/.claude-plugin/plugin.json new file mode 100644 index 000000000..9df2f4665 --- /dev/null +++ b/plugins/task-utils/.claude-plugin/plugin.json @@ -0,0 +1,20 @@ +{ + "name": "task-utils", + "version": "0.1.0", + "description": "Unified task management plugin — commit-on-complete, session awareness, active-task guard, stop guard, and provider-based task sync. Consolidates todo-plus-plus, todo-sync, and task-parallelization.", + "author": { + "name": "Nathan Heaps", + "email": "nsheaps@gmail.com", + "url": "https://github.com/nsheaps" + }, + "keywords": [ + "tasks", + "commit", + "workflow", + "ephemeral", + "parallelization", + "sync", + "agent-teams", + "productivity" + ] +} diff --git a/plugins/task-parallelization/.release-it.js b/plugins/task-utils/.release-it.js similarity index 100% rename from plugins/task-parallelization/.release-it.js rename to plugins/task-utils/.release-it.js diff --git a/plugins/task-utils/README.md b/plugins/task-utils/README.md new file mode 100644 index 000000000..423bb5e06 --- /dev/null +++ b/plugins/task-utils/README.md @@ -0,0 +1,84 @@ +# task-utils + +Unified task management plugin for Claude Code agents. Consolidates `todo-plus-plus`, `todo-sync`, and `task-parallelization` into a single cohesive plugin. + +See the full spec at [`docs/spec.md`](docs/spec.md). + +## Features + +- **Commit-on-Complete** (`TaskCompleted` hook): Blocks task completion if there are uncommitted or unpushed changes +- **Session Awareness** (`SessionStart` hook): Reminds agents that Tasks are session-scoped and not persistent; to always commit before completing tasks +- **Active-Task Guard** (`PreToolUse` hook, advisory): Warns when a tool is used with no active task (scaffold — no-op in this release) +- **Stop Guard** (`Stop` hook, advisory): Warns when a session ends with in-progress tasks (scaffold — no-op in this release) +- **Provider-based Task Sync** (`PostToolUse:TaskCreate/TaskUpdate`): Syncs task state to configured backends (Filesystem, GitHub Issues) (scaffold — no-op in this release) +- **Task Parallelization skill**: Migrated from `task-parallelization` — guidance on running parallel sub-agents +- **Task Management skill**: New skill covering the full task lifecycle, naming conventions, and delegation patterns + +## Installation + +Add `task-utils` to your `enabledPlugins` in `settings.json`. Remove `todo-plus-plus`, `todo-sync`, and `task-parallelization` if previously installed. + +## Configuration + +> **Not yet implemented.** The configuration knobs below are planned for v1.1. In v0.1.0, all hooks use hardcoded defaults — `commitCheck` is always on, stub hooks always exit 0, and no provider sync runs. No `plugins.settings.yaml` is read. + +```yaml +# plugins.settings.yaml (planned — not read in v0.1.0) +task-utils: + providers: + filesystem: + enabled: true # writes task state to $CLAUDE_PROJECT_DIR/.claude/tasks/ + githubIssues: + enabled: false # set true to enable GitHub issue sync + repo: "owner/repo" # required if enabled: true + labels: + - "agent-task" + closeOnComplete: true + commitCheck: + enabled: true # block TaskCompleted if uncommitted changes exist + stopGuard: + enabled: true # warn on Stop if in_progress tasks remain + activeTaskGuard: + enabled: true # warn on tool use if no active task +``` + +## File Structure + +``` +task-utils/ +├── .claude-plugin/ +│ └── plugin.json +├── docs/ +│ └── spec.md # full specification +├── hooks/ +│ ├── hooks.json +│ └── scripts/ +│ ├── check-uncommitted.sh # TaskCompleted — commit guard +│ ├── session-start.sh # SessionStart — awareness message +│ ├── active-task-guard.sh # PreToolUse — active task advisory +│ ├── stop-guard.sh # Stop — in-progress task advisory +│ ├── sync-task-create.sh # PostToolUse:TaskCreate — provider sync +│ └── sync-task-update.sh # PostToolUse:TaskUpdate — provider sync +├── lib/ +│ └── log.sh # shared logging helpers +├── skills/ +│ ├── task-parallelization/ +│ │ └── SKILL.md # migrated from task-parallelization plugin +│ └── task-management/ +│ └── SKILL.md # new — task lifecycle and naming conventions +└── README.md +``` + +## Migration from Previous Plugins + +If you used `todo-plus-plus`, `todo-sync`, and/or `task-parallelization`: + +1. Install `task-utils` +2. Remove the old plugins from `enabledPlugins` +3. Configure `providers.githubIssues` if you used todo-sync's GitHub sync + +No data migration required — task state lives in Claude Code's native task store. + +## License + +MIT diff --git a/plugins/task-utils/docs/spec.md b/plugins/task-utils/docs/spec.md new file mode 100644 index 000000000..064d40d66 --- /dev/null +++ b/plugins/task-utils/docs/spec.md @@ -0,0 +1,229 @@ +--- +name: task-utils +status: in-progress +description: Unified task management plugin consolidating todo-plus-plus, todo-sync, and task-parallelization into a single cohesive plugin with provider-based task sync. +--- + +# task-utils Plugin Spec + +## Problem Statement + +Task management is currently fragmented across three separate plugins: + +- **todo-plus-plus** (v0.1.5): lifecycle hooks (commit check, session restore, stop guard) +- **todo-sync** (v0.2.4): syncs TodoWrite output to GitHub issues and initializes `.gitignore` +- **task-parallelization** (v0.2.25): skill for running tasks in parallel + +These overlap in concern, share no config namespace, and require three separate install/update cycles. Agents must install all three to get complete task management behavior, and there is no single place to configure task-related settings. + +## Goals + +1. Single `task-utils` plugin replacing all three +2. Provider-based task sync — pluggable backends (filesystem, GitHub issues, extensible to others) +3. Complete task lifecycle management (session restore, commit guard, stop guard) +4. Parallelization skill migrated in +5. Clean migration path with no behavior regression for todo-plus-plus / task-parallelization users + +## Non-Goals + +- Task storage backend (tasks remain in Claude Code's native task store) +- Multi-agent task coordination (out of scope for v1) +- Custom task types or fields beyond what TaskCreate/TaskUpdate support + +## Provider Architecture + +Task sync is handled by a configurable list of **providers**. Each provider implements a standard interface and is invoked on task lifecycle events. + +### Provider Interface + +```typescript +interface TaskProvider { + onTaskCreate(task: Task): Promise; + onTaskUpdate(task: Task): Promise; + onTaskComplete(task: Task): Promise; +} +``` + +### Built-in Providers + +#### `FilesystemProvider` + +Writes task state to `$CLAUDE_PROJECT_DIR/.claude/tasks/` as JSON files. + +- Source: migrated from todo-sync's filesystem output +- Purpose: provides local task persistence for environments where file access is available +- Status: **enabled by default in v1**, expected to be deprecated as agent environments become ephemeral (no persistent filesystem) +- Config key: `providers.filesystem` + +#### `GitHubIssuesProvider` + +Syncs task state to GitHub issues on the agent's configured repo. + +- Source: adapted from todo-sync (redesigned) +- **Sync behavior**: uses a haiku sub-agent to find existing issues matching the task (by title/ID) before creating new ones. Updates existing issues rather than creating duplicates. +- On `onTaskCreate`: search for existing issue → update if found, create if not +- On `onTaskUpdate`: update issue labels/status to match task state +- On `onTaskComplete`: close issue (or add "done" label, per config) +- Config key: `providers.githubIssues` + +### Design for Extensibility + +The provider list is open — future providers (e.g., Linear, Jira, Slack) can be added by implementing the `TaskProvider` interface and registering in config. No plugin changes required for new providers. + +### Provider Configuration + +```yaml +task-utils: + providers: + filesystem: + enabled: true # writes to $CLAUDE_PROJECT_DIR/.claude/tasks/ + githubIssues: + enabled: false # set true to enable GitHub issue sync + repo: "owner/repo" # required if enabled: true + labels: # optional labels to apply to created/updated issues + - "agent-task" + closeOnComplete: true # close issue when task completes +``` + +## Hooks (7 total) + +### 1. `TaskCompleted` — Commit Check + +**Source**: todo-plus-plus `TaskCompleted` hook +**Behavior**: Block task completion if uncommitted changes exist in the working directory. Forces agents to commit before marking a task done. +**Configurable**: `commitCheck.enabled` (default: `true`) +**Advisory**: No — blocks when enabled + +### 2. `SessionStart` — Task Awareness + Restore + +**Source**: todo-plus-plus `SessionStart` hook +**Behavior**: + +- Injects task-awareness context into the session (reminder to use TaskCreate on every action request) +- Task restore is **deferred to v1.1** — currently emits a static awareness message only + +**Advisory**: No — always runs + +### 3. `PreToolUse` (advisory) — No Active Task Warning + +**Source**: New (fills gap in todo-plus-plus) +**Behavior**: When a non-conversational tool is invoked and no task is `in_progress`, emit an advisory warning reminding the agent to create/activate a task. +**Advisory**: Yes — warns, does not block +**Configurable**: `activeTaskGuard.enabled` (default: `true`) +**Status**: **Deferred to v1.1** — script exists but is not wired in `hooks.json`. Running a no-op on every tool call adds per-call overhead for zero benefit; will be wired when guard logic is implemented. + +### 4. `Stop` (advisory) — In-Progress Task Warning + +**Source**: todo-plus-plus `Stop` hook — **migrated from agent repo to plugin** +**Behavior**: When the session is about to end, warn if any tasks remain `in_progress`. Reminds the agent to complete or hand off work. +**Advisory**: Yes — warns, does not block +**Status**: Registered as a **no-op stub, full logic deferred to v1.1** +**Configurable**: `stopGuard.enabled` (default: `true`) + +### 5. `PostToolUse:TaskCreate` — Sync New Task to Providers + +**Source**: todo-sync (redesigned) +**Behavior**: After `TaskCreate` succeeds, invoke each enabled provider's `onTaskCreate`. The `GitHubIssuesProvider` uses a haiku sub-agent to find existing matching issues and update them, or create a new issue only if none exists. +**Configurable**: per-provider `enabled` flags +**Advisory**: No (when enabled) — failure emits warning but does not block + +### 6. `PostToolUse:TaskUpdate` — Sync Task Update to Providers + +**Source**: New +**Behavior**: After `TaskUpdate` changes task status, invoke each enabled provider's `onTaskUpdate`. GitHub issues receive label and status updates. +**Configurable**: per-provider `enabled` flags +**Advisory**: No (when enabled) — failure emits warning but does not block + +### 7. `PostToolUse:TodoWrite` — Sync Todo JSON _(deferred post-MVP)_ + +**Source**: todo-sync +**Behavior**: After `TodoWrite`, sync the todo list to a GitHub issue or comment for visibility. +**Status**: **Deferred** — included in plugin structure but disabled by default. Will be enabled in v1.1 once TodoWrite→Task interop is better understood. + +## Skills + +### `task-parallelization` (migrated) + +Migrated verbatim from task-parallelization v0.2.25. No functional changes in v1. +Documents how to run multiple tasks in parallel using background agents. + +### `task-management` (new) + +New skill covering: + +- When and how to use TaskCreate, TaskUpdate, TaskList, TaskGet +- Task naming conventions (include ID and ticket number) +- The full task lifecycle (created → in_progress → completed/cancelled) +- When to delegate tasks to sub-agents vs. execute directly + +## Configuration + +> **Not yet implemented.** The configuration below is the planned interface for v1.1. In v0.1.0, no `plugin_get_config` calls exist and no `plugins.settings.yaml` is read — all hooks use hardcoded defaults. + +Full configuration reference via `plugins.settings.yaml` in the consuming agent's repo (planned): + +```yaml +task-utils: + providers: + filesystem: + enabled: true # writes task state to $CLAUDE_PROJECT_DIR/.claude/tasks/ + githubIssues: + enabled: false # set true to enable GitHub issue sync + repo: "owner/repo" # required if enabled: true + labels: + - "agent-task" + closeOnComplete: true + commitCheck: + enabled: true # block TaskCompleted if uncommitted changes exist + stopGuard: + enabled: true # warn on Stop if in_progress tasks remain (commented out initially) + activeTaskGuard: + enabled: true # warn on tool use if no active task +``` + +## Migration Path + +For agents currently using the three separate plugins: + +1. Install `task-utils` (adds this plugin to `enabledPlugins`) +2. Remove `todo-plus-plus`, `todo-sync`, `task-parallelization` from `enabledPlugins` +3. Copy any custom config from old plugins into `task-utils` config block +4. Configure `providers.githubIssues.enabled` if you previously used todo-sync's GitHub sync (was previously always-on in todo-sync) + +No data migration required — task state lives in Claude Code's native store. + +**Note**: TodoWrite gitignore initialization (from todo-sync's `SessionStart`) is deferred post-MVP. + +## MVP Scope (v1) + +| Feature | Status | +| --------------------------------------------------------- | ---------------------- | +| TaskCompleted commit check | **Implemented** | +| SessionStart awareness message | **Implemented** | +| PreToolUse active-task guard | **Stub** (no-op, v1.1) | +| Stop guard | **Stub** (no-op, v1.1) | +| FilesystemProvider | **Stub** (no-op, v1.1) | +| GitHubIssuesProvider (find-or-create via haiku sub-agent) | **Stub** (no-op, v1.1) | +| task-parallelization skill (migrated) | **Implemented** | +| task-management skill (new) | **Implemented** | +| PostToolUse:TodoWrite sync | **Deferred** | +| TodoWrite gitignore init | **Deferred** | + +## Deferred Items (post-MVP) + +- **TodoWrite sync** (`PostToolUse:TodoWrite`): sync todo JSON state to GitHub. Needs clearer spec for what "syncing" means at the issue level. +- **GitIgnore init** (from todo-sync `SessionStart`): auto-add `.claude/todos/` to `.gitignore`. Low priority; agents can do this manually. +- **Task→PR linking**: automatically link tasks to open PRs when a TaskCreate happens on a feature branch. +- **FilesystemProvider deprecation**: once agent environments are consistently ephemeral, filesystem provider will be removed. For now it stays enabled by default. +- **Additional providers**: Linear, Jira, Slack, etc. — implementing the provider interface is sufficient to add new backends. + +## References + +- [#64](https://github.com/nsheaps/ai-mktpl/issues/64) — original todo-plus-plus issue +- [#65](https://github.com/nsheaps/ai-mktpl/issues/65) — todo-sync issue +- [#138](https://github.com/nsheaps/ai-mktpl/issues/138) — task-parallelization issue +- [#319](https://github.com/nsheaps/ai-mktpl/issues/319) — consolidation tracking +- [#320](https://github.com/nsheaps/ai-mktpl/issues/320) — GitHub sync design +- [#330](https://github.com/nsheaps/ai-mktpl/issues/330) — config namespace design +- [#370](https://github.com/nsheaps/ai-mktpl/issues/370) — migration path +- [Discord design thread](https://discord.com/channels/1490863845252665415/1497254984696205445) diff --git a/plugins/task-utils/hooks/hooks.json b/plugins/task-utils/hooks/hooks.json new file mode 100644 index 000000000..16fe3ac0b --- /dev/null +++ b/plugins/task-utils/hooks/hooks.json @@ -0,0 +1,63 @@ +{ + "description": "Task lifecycle hooks: commit check, session awareness + restore, active-task guard, stop guard, and provider sync", + "hooks": { + "TaskCompleted": [ + { + "matcher": "*", + "hooks": [ + { + "type": "command", + "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-uncommitted.sh", + "timeout": 15 + } + ] + } + ], + "SessionStart": [ + { + "matcher": "*", + "hooks": [ + { + "type": "command", + "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/session-start.sh", + "timeout": 10 + } + ] + } + ], + "Stop": [ + { + "matcher": "*", + "hooks": [ + { + "type": "command", + "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/stop-guard.sh", + "timeout": 10 + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "TaskCreate", + "hooks": [ + { + "type": "command", + "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/sync-task-create.sh", + "timeout": 30 + } + ] + }, + { + "matcher": "TaskUpdate", + "hooks": [ + { + "type": "command", + "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/sync-task-update.sh", + "timeout": 30 + } + ] + } + ] + } +} diff --git a/plugins/task-utils/hooks/scripts/active-task-guard.sh b/plugins/task-utils/hooks/scripts/active-task-guard.sh new file mode 100755 index 000000000..1323aa118 --- /dev/null +++ b/plugins/task-utils/hooks/scripts/active-task-guard.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# active-task-guard.sh — Advisory warning when a tool is used with no active task +# Triggered by PreToolUse hook (advisory only — does not block) +# +# This is a new hook with no predecessor in the consolidated plugins. +# Exit code 0 = allow (advisory warnings do not block) + +set -euo pipefail + +# Read hook input from stdin +input=$(cat) + +# Extract the tool name from the hook input +# Hook input format: {"tool_name": "...", "tool_input": {...}, ...} +tool_name="" +if command -v jq &>/dev/null; then + tool_name=$(echo "$input" | jq -r '.tool_name // empty' 2>/dev/null || echo "") +fi + +# Conversational tools that don't require an active task +EXEMPT_TOOLS=( + "TodoRead" + "TodoWrite" + "TaskList" + "TaskGet" +) + +# Check if the tool is exempt +for exempt in "${EXEMPT_TOOLS[@]}"; do + if [ "$tool_name" = "$exempt" ]; then + exit 0 + fi +done + +# Stub: active task detection would query TaskList here. +# For now this hook exits 0 (pass-through) — full implementation in v1.1 +# when TaskList output can be reliably parsed from within a hook. + +exit 0 diff --git a/plugins/todo-plus-plus/scripts/check-uncommitted.sh b/plugins/task-utils/hooks/scripts/check-uncommitted.sh similarity index 85% rename from plugins/todo-plus-plus/scripts/check-uncommitted.sh rename to plugins/task-utils/hooks/scripts/check-uncommitted.sh index a905c25b9..fc8c7ee76 100755 --- a/plugins/todo-plus-plus/scripts/check-uncommitted.sh +++ b/plugins/task-utils/hooks/scripts/check-uncommitted.sh @@ -1,15 +1,16 @@ #!/usr/bin/env bash -# check-uncommitted.sh - Blocks task completion if there are uncommitted changes +# check-uncommitted.sh — Blocks task completion if there are uncommitted changes # Triggered by TaskCompleted hook # # Exit code 2 = block completion and send stderr as feedback to Claude # Exit code 0 = allow completion +# +# Source: migrated from todo-plus-plus v0.1.5 set -euo pipefail -LOG_PREFIX="todo-plus-plus" -# shellcheck source=../lib/log.sh -source "$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)/lib/log.sh" +LOG_PREFIX="task-utils" +source "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/lib/log.sh" # Read hook input from stdin (consume it so the pipe doesn't break) cat > /dev/null diff --git a/plugins/task-utils/hooks/scripts/session-start.sh b/plugins/task-utils/hooks/scripts/session-start.sh new file mode 100755 index 000000000..76b15696b --- /dev/null +++ b/plugins/task-utils/hooks/scripts/session-start.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# session-start.sh — Injects task-awareness context into the session +# Triggered by SessionStart hook +# +# Source: migrated and extended from todo-plus-plus v0.1.5 SessionStart hook + +set -euo pipefail + +# Read hook input (consume stdin) +cat > /dev/null + +# Emit session context as a systemMessage via JSON output +cat <<'EOF' +{"systemMessage": "IMPORTANT SESSION CONTEXT: You may be running in an ephemeral session (a sub-agent, teammate, or temporary context). The Tasks system (TaskCreate, TaskUpdate, TaskList) is for tracking YOUR local work items within THIS session only. Do NOT use Tasks for persistent project tracking, feature backlogs, or cross-session work items. Those belong in external systems (GitHub Issues, Linear, etc.). Tasks are session-scoped and will not survive session end. Also: when you complete a task, ALWAYS commit and push your changes before marking it complete. Use TaskCreate on EVERY action request from the user — even simple, one-off tasks. Always keep your task list up to date."} +EOF + +exit 0 diff --git a/plugins/task-utils/hooks/scripts/stop-guard.sh b/plugins/task-utils/hooks/scripts/stop-guard.sh new file mode 100755 index 000000000..c21ea6492 --- /dev/null +++ b/plugins/task-utils/hooks/scripts/stop-guard.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +# stop-guard.sh — Advisory warning when session ends with in-progress tasks +# Triggered by Stop hook (advisory only — does not block) +# +# Source: migrated from agent repo (was in .claude/rules as a hook, not a plugin hook). +# Commented out initially pending validation in plugin context — see spec. +# +# Exit code 0 = allow session to stop (advisory) + +set -euo pipefail + +# Read hook input (consume stdin) +cat > /dev/null + +# TODO: Implement in-progress task detection via TaskList. +# Full implementation deferred to v1.1 pending reliable TaskList access from hooks. +# The hook is registered in hooks.json and runs, but currently exits 0 (no-op). + +exit 0 diff --git a/plugins/task-utils/hooks/scripts/sync-task-create.sh b/plugins/task-utils/hooks/scripts/sync-task-create.sh new file mode 100755 index 000000000..d17917016 --- /dev/null +++ b/plugins/task-utils/hooks/scripts/sync-task-create.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# sync-task-create.sh — Syncs a newly created task to configured providers +# Triggered by PostToolUse:TaskCreate hook +# +# Source: new hook — replaces todo-sync's TodoWrite sync with provider-based architecture. +# Providers are configured in plugins.settings.yaml under task-utils.providers. + +set -euo pipefail + +LOG_PREFIX="task-utils" +source "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/lib/log.sh" + +# Read hook input from stdin +input=$(cat) + +# Extract task info (if jq is available) +if ! command -v jq &>/dev/null; then + log_warn "jq not found — skipping provider sync" + exit 0 +fi + +# TODO: verify `.tool_result` vs `.tool_response` in the actual hook payload schema +# when providers are implemented (follow-up task). +task_id=$(echo "$input" | jq -r '.tool_result.taskId // empty' 2>/dev/null || echo "") +task_title=$(echo "$input" | jq -r '.tool_result.subject // empty' 2>/dev/null || echo "") + +if [ -z "$task_id" ]; then + # No task ID in output — nothing to sync + exit 0 +fi + +# TODO: Read provider config from plugins.settings.yaml and invoke each enabled provider. +# FilesystemProvider and GitHubIssuesProvider will be implemented in the full v1 release. +# This stub exits 0 so the hook is registered and wired but does not fail. + +log_info "TaskCreate sync stub: task_id=$task_id title='$task_title' (providers not yet implemented)" + +exit 0 diff --git a/plugins/task-utils/hooks/scripts/sync-task-update.sh b/plugins/task-utils/hooks/scripts/sync-task-update.sh new file mode 100755 index 000000000..2088d65a9 --- /dev/null +++ b/plugins/task-utils/hooks/scripts/sync-task-update.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# sync-task-update.sh — Syncs task status changes to configured providers +# Triggered by PostToolUse:TaskUpdate hook +# +# Source: new hook — provider-based architecture (see spec.md). +# Providers are configured in plugins.settings.yaml under task-utils.providers. + +set -euo pipefail + +LOG_PREFIX="task-utils" +source "$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)/lib/log.sh" + +# Read hook input from stdin +input=$(cat) + +# Extract task info (if jq is available) +if ! command -v jq &>/dev/null; then + log_warn "jq not found — skipping provider sync" + exit 0 +fi + +task_id=$(echo "$input" | jq -r '.tool_input.id // empty' 2>/dev/null || echo "") +new_status=$(echo "$input" | jq -r '.tool_input.status // empty' 2>/dev/null || echo "") + +if [ -z "$task_id" ]; then + # No task ID in input — nothing to sync + exit 0 +fi + +# TODO: Read provider config from plugins.settings.yaml and invoke each enabled provider. +# FilesystemProvider and GitHubIssuesProvider will be implemented in the full v1 release. +# This stub exits 0 so the hook is registered and wired but does not fail. + +log_info "TaskUpdate sync stub: task_id=$task_id status='$new_status' (providers not yet implemented)" + +exit 0 diff --git a/plugins/todo-plus-plus/lib/log.sh b/plugins/task-utils/lib/log.sh similarity index 100% rename from plugins/todo-plus-plus/lib/log.sh rename to plugins/task-utils/lib/log.sh diff --git a/plugins/task-utils/skills/task-management/SKILL.md b/plugins/task-utils/skills/task-management/SKILL.md new file mode 100644 index 000000000..b5d8a019b --- /dev/null +++ b/plugins/task-utils/skills/task-management/SKILL.md @@ -0,0 +1,157 @@ +--- +name: task-management +description: Task lifecycle management for Claude Code agents. Use this skill when working with TaskCreate, TaskUpdate, TaskList, TaskGet, or when asked about task naming conventions, the task lifecycle, or when to delegate tasks to sub-agents. +--- + +# Task Management Skill + +This skill covers the full task lifecycle for Claude Code agents: when to create tasks, how to name them, how to track their state, and when to delegate to sub-agents. + +## Core Rule: Always Use Tasks for Action Requests + +ALWAYS use TaskCreate to track your tasks on EVERY action request from the user. Even if it is a simple, one-off task. + +**Exception**: When the user asks a question, answer it first. Do NOT create tasks for questions — only create tasks after the user confirms they want action. + +## When and How to Use TaskCreate + +### Trigger: Any action request from the user + +``` +User: "Fix the bug in the login flow" +→ TaskCreate: { subject: "#23: Fix the bug in the login flow" } +``` + +### Do NOT create tasks for: + +- Questions ("What is X?", "Why does Y happen?") +- Conversational responses +- Clarifications + +## Task Naming Conventions + +Tasks MUST always include the task ID in the subject and activeForm. + +**GOOD:** + +``` +#23: Fix the bug in the login flow +``` + +**BAD:** + +``` +Fix the bug in the login flow +``` + +### Ticket/PR References + +- If a task directly relates to a ticket in an external tracking system, include the ticket number in the subject. +- If a task relates to a PR, include the PR number if the user is referencing change sets by PR number. + +**Examples:** + +``` +#23: [GH-456] Fix the authentication bug +#24: [PR #789] Review and address feedback +``` + +## Task Lifecycle + +``` +created → in_progress → completed + → cancelled +``` + +1. **created**: Task is defined but work has not started +2. **in_progress**: Actively working on this task right now +3. **completed**: Work is done, changes are committed and pushed +4. **cancelled**: Task is no longer needed + +### Rules + +- Only ONE task should be `in_progress` at a time (unless delegated to parallel sub-agents) +- Use TaskUpdate to change status before and after each phase +- Always commit and push before marking a task `completed` +- Update Tasks BEFORE any tool use — never have stale Tasks + +## Keeping Tasks Up to Date + +Before using ANY tool (Read, Edit, Write, Bash, Grep, etc.), you MUST first check your Tasks: + +1. If Tasks don't reflect what you're about to do, update them first +2. Never have stale Tasks that don't match your current work +3. Mark the current task `in_progress` before starting work + +## Delegating Tasks to Sub-Agents + +When working on a task, prefer delegating to an appropriate sub-agent rather than executing directly in your own context. + +### Why Delegate + +- Better isolation of work +- Clearer permission boundaries +- More efficient context usage +- Agents can be resumed for related follow-up work + +### When to Delegate + +| Task Type | Delegate? | +| ------------------------------------ | ---------------------------------- | +| Codebase investigation / exploration | Yes — use Explore agent with haiku | +| Architectural decisions | Yes — use Plan agent | +| Implementation tasks (3+ files) | Yes — use general-purpose agent | +| Simple 1-file edits | No — execute directly | +| Quick lookups | No — execute directly | + +### Sub-Agent Prompt Pattern + +When delegating, always tell the sub-agent: + +1. What task it is working on (include task ID) +2. What to produce or change +3. Where to save any output +4. NOT to return large outputs inline — save to files and summarize + +``` +You are working on Task #23: Fix the authentication bug. + +Your job: [specific instructions] + +Output: Save findings to docs/research/auth-bug-investigation.md +Return: A summary of what you changed and any file paths created/modified. +Do NOT return the full file contents inline. +``` + +### Agent Resumption + +When continuing work on a related task, prefer resuming an existing agent by ID rather than starting fresh. This preserves context and reduces redundant exploration. + +## Task List Hygiene + +- Review TaskList at the start of each session +- Archive or cancel stale tasks that are no longer relevant +- Never let completed tasks sit as `in_progress` +- Use TaskGet to read full task details before resuming work + +## When Tasks Are Blocked + +If you cannot complete a task (blocked by dependency, missing info, external factor): + +1. Leave the task `in_progress` (it's still your responsibility) +2. Create a new task for the blocker: "#24: Unblock task #23 — [reason]" +3. Resolve the blocker first, then return to the original task + +## Task Completion Checklist + +Before marking a task `completed`: + +- [ ] The original user request is fully satisfied +- [ ] Changes have been tested and validated +- [ ] Code review feedback has been addressed +- [ ] All changes are committed and pushed to remote +- [ ] No known issues remain + +## Related Skills + +- `task-parallelization` — how to run multiple tasks concurrently for batch operations diff --git a/plugins/task-parallelization/skills/task-parallelization/SKILL.md b/plugins/task-utils/skills/task-parallelization/SKILL.md similarity index 100% rename from plugins/task-parallelization/skills/task-parallelization/SKILL.md rename to plugins/task-utils/skills/task-parallelization/SKILL.md diff --git a/plugins/todo-plus-plus/.claude-plugin/plugin.json b/plugins/todo-plus-plus/.claude-plugin/plugin.json deleted file mode 100644 index 613f6ccc0..000000000 --- a/plugins/todo-plus-plus/.claude-plugin/plugin.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "todo-plus-plus", - "version": "0.1.5", - "description": "Enforces commit-on-complete for tasks and reminds about ephemeral session awareness", - "author": { - "name": "Nathan Heaps", - "email": "nsheaps@gmail.com" - }, - "keywords": ["tasks", "commit", "workflow", "ephemeral", "agent-teams"] -} diff --git a/plugins/todo-plus-plus/.release-it.js b/plugins/todo-plus-plus/.release-it.js deleted file mode 100644 index 539d53629..000000000 --- a/plugins/todo-plus-plus/.release-it.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - extends: "../../.release-it.base.json", - plugins: { - "@release-it/bumper": { - in: ".claude-plugin/plugin.json", - out: ".claude-plugin/plugin.json", - }, - }, -}; diff --git a/plugins/todo-plus-plus/README.md b/plugins/todo-plus-plus/README.md deleted file mode 100644 index 43ad57795..000000000 --- a/plugins/todo-plus-plus/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Todo++ Plugin - -Enforces commit-on-complete for tasks and provides ephemeral session awareness. - -## Features - -- **Commit-on-Complete**: Blocks task completion if there are uncommitted or unpushed changes -- **Ephemeral Session Awareness**: Reminds agents that Tasks are session-scoped, not persistent - -## Installation - -Add to your project or user settings.json enabledPlugins. - -## How It Works - -### TaskCompleted Hook - -When any task is marked complete (via TaskUpdate), the hook: - -1. Checks `git status` for uncommitted changes -2. Checks for unpushed commits -3. If either exists, blocks completion with a message telling Claude to commit and push first - -### SessionStart Hook - -On session start, injects a prompt reminding Claude that: - -- Tasks are for local session work only -- Always commit and push before completing tasks -- Use external systems for persistent project tracking - -## File Structure - -``` -todo-plus-plus/ -├── .claude-plugin/ -│ └── plugin.json -├── hooks/ -│ └── hooks.json # TaskCompleted + SessionStart hooks -├── scripts/ -│ └── check-uncommitted.sh # Git status checker -├── skills/ -│ └── todo-plus-plus/ -│ └── SKILL.md -└── README.md -``` - -## Related Plugins - -- **todo-sync** -- Syncs todos from ~/.claude/ to project .claude/ (complementary) -- **scm-utils** -- Git workflow utilities - -## License - -MIT diff --git a/plugins/todo-plus-plus/hooks/hooks.json b/plugins/todo-plus-plus/hooks/hooks.json deleted file mode 100644 index 448fdd33d..000000000 --- a/plugins/todo-plus-plus/hooks/hooks.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "description": "Commit enforcement on task completion and ephemeral session awareness on start", - "hooks": { - "TaskCompleted": [ - { - "matcher": "*", - "hooks": [ - { - "type": "command", - "command": "bash ${CLAUDE_PLUGIN_ROOT}/scripts/check-uncommitted.sh", - "timeout": 15 - } - ] - } - ], - "SessionStart": [ - { - "matcher": "*", - "hooks": [ - { - "type": "command", - "command": "echo '{\"systemMessage\": \"IMPORTANT SESSION CONTEXT: You may be running in an ephemeral session (a sub-agent, teammate, or temporary context). The Tasks system (TaskCreate, TaskUpdate, TaskList) is for tracking YOUR local work items within THIS session only. Do NOT use Tasks for persistent project tracking, feature backlogs, or cross-session work items. Those belong in external systems (GitHub Issues, Linear, etc.). Tasks are session-scoped and will not survive session end. Also: when you complete a task, ALWAYS commit and push your changes before marking it complete.\"}'", - "timeout": 5 - } - ] - } - ] - } -} diff --git a/plugins/todo-plus-plus/skills/todo-plus-plus/SKILL.md b/plugins/todo-plus-plus/skills/todo-plus-plus/SKILL.md deleted file mode 100644 index 106435aee..000000000 --- a/plugins/todo-plus-plus/skills/todo-plus-plus/SKILL.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -name: todo-plus-plus -description: Task workflow enforcement plugin. Use when asking about commit-on-complete behavior, task completion requirements, ephemeral session awareness, or why a task completion was blocked. ---- - -# Todo++ Plugin - -This plugin enforces two workflow rules for Claude Code sessions: - -## 1. Commit-on-Complete - -A **TaskCompleted** hook checks for uncommitted changes when any task is marked complete. If there are uncommitted or unpushed changes, the completion is **blocked** until you commit and push. - -### Why - -Agents frequently complete work but forget to commit. In ephemeral sessions (teammates, sub-agents), uncommitted work is **lost** when the session ends. This hook prevents that. - -### What Gets Checked - -1. **Uncommitted changes**: Any staged, unstaged, or untracked files (`git status --porcelain`) -2. **Unpushed commits**: Local commits that haven't been pushed to the remote - -### If Blocked - -When task completion is blocked: - -1. Run `git status` to see what needs attention -2. Stage and commit your changes -3. Push to remote -4. Then mark the task complete again - -### Exceptions - -- If not in a git repository, the check is skipped -- The hook only fires on TaskCompleted events (team task system) - -## 2. Ephemeral Session Awareness - -A **SessionStart** hook injects a reminder that: - -- Tasks (TaskCreate/TaskUpdate/TaskList) are for **local session work only** -- Tasks do NOT persist across sessions -- Persistent tracking belongs in external systems (GitHub Issues, Linear, etc.) -- Always commit and push before marking tasks complete - -### Why - -Agents sometimes use the Task system as if it were a persistent project tracker, creating tasks they expect to survive session boundaries. This wastes context and creates confusion when tasks disappear. - -## Configuration - -No configuration required. Install the plugin and it works automatically. - -## Disabling - -To temporarily disable commit enforcement, you can: - -1. Disable the plugin in settings.json -2. Or remove the plugin from enabledPlugins diff --git a/plugins/todo-sync/.claude-plugin/plugin.json b/plugins/todo-sync/.claude-plugin/plugin.json deleted file mode 100644 index 763531b05..000000000 --- a/plugins/todo-sync/.claude-plugin/plugin.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "todo-sync", - "version": "0.2.4", - "description": "Automatically syncs todos and plans from ~/.claude/ to the current project's .claude/ directory", - "author": { - "name": "Nathan Heaps", - "email": "nsheaps@gmail.com" - }, - "keywords": ["todos", "plans", "sync", "workflow", "productivity"] -} diff --git a/plugins/todo-sync/.release-it.js b/plugins/todo-sync/.release-it.js deleted file mode 100644 index 539d53629..000000000 --- a/plugins/todo-sync/.release-it.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - extends: "../../.release-it.base.json", - plugins: { - "@release-it/bumper": { - in: ".claude-plugin/plugin.json", - out: ".claude-plugin/plugin.json", - }, - }, -}; diff --git a/plugins/todo-sync/README.md b/plugins/todo-sync/README.md deleted file mode 100644 index 89da10735..000000000 --- a/plugins/todo-sync/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# Todo Sync Plugin - -Automatically syncs todos and plans from `~/.claude/` to your current project's `.claude/` directory. - -## Features - -- **Automatic sync**: Triggers after every `TodoWrite` call via PostToolUse hook -- **Smart merge**: Deduplicates todos by content when merging -- **Plans support**: Syncs plan files from global to project directory -- **Session-aware**: Only syncs the current session's todos - -## Installation - -Add to your project's `.claude/settings.json`: - -```json -{ - "plugins": ["/path/to/todo-sync"] -} -``` - -Or install from the marketplace (if published). - -## How It Works - -``` -TodoWrite called - ↓ -PostToolUse hook fires - ↓ -sync-todos.sh executes - ↓ -~/.claude/todos/{session}.json → .claude/todos/{session}.json -~/.claude/plans/*.md → .claude/plans/*.md -``` - -## File Structure - -``` -todo-sync/ -├── .claude-plugin/ -│ └── plugin.json # Plugin manifest -├── hooks/ -│ └── hooks.json # Hook configuration (SessionStart, UserPromptSubmit, PostToolUse) -├── scripts/ -│ ├── init-gitignore.sh # Ensures global gitignore patterns -│ └── sync-todos.sh # Sync logic -├── skills/ -│ └── todo-sync/ -│ └── SKILL.md # Usage documentation -└── README.md -``` - -## Configuration - -No configuration required. The plugin works automatically once installed. - -### Git Integration - -The plugin automatically ensures `~/.config/git/ignore` (the global gitignore) contains patterns for `.claude/todos/` and `.claude/plans/` directories. This ignores all synced files in any project by default. - -To track todos in version control for a specific project, add explicit `!.claude/todos/` pattern to that project's `.gitignore`. - -## Troubleshooting - -Run Claude Code in debug mode to see hook execution: - -```bash -claude --debug -``` - -Look for `PostToolUse` events on `TodoWrite` to verify the hook is firing. - -## License - -MIT diff --git a/plugins/todo-sync/hooks/hooks.json b/plugins/todo-sync/hooks/hooks.json deleted file mode 100644 index cf5d5c1c9..000000000 --- a/plugins/todo-sync/hooks/hooks.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "description": "Syncs todos and plans from ~/.claude/ to project .claude/ directory after TodoWrite", - "hooks": { - "SessionStart": [ - { - "matcher": "*", - "hooks": [ - { - "type": "command", - "command": "${CLAUDE_PLUGIN_ROOT}/scripts/init-gitignore.sh", - "timeout": 5 - } - ] - } - ], - "UserPromptSubmit": [ - { - "matcher": "*", - "hooks": [ - { - "type": "command", - "command": "${CLAUDE_PLUGIN_ROOT}/scripts/init-gitignore.sh", - "timeout": 5 - } - ] - } - ], - "PostToolUse": [ - { - "matcher": "TodoWrite", - "hooks": [ - { - "type": "command", - "command": "${CLAUDE_PLUGIN_ROOT}/scripts/sync-todos.sh", - "timeout": 10 - } - ] - } - ] - } -} diff --git a/plugins/todo-sync/lib/hook-output.sh b/plugins/todo-sync/lib/hook-output.sh deleted file mode 120000 index 4c67a420b..000000000 --- a/plugins/todo-sync/lib/hook-output.sh +++ /dev/null @@ -1 +0,0 @@ -../../../shared/lib/hook-output.sh \ No newline at end of file diff --git a/plugins/todo-sync/lib/log.sh b/plugins/todo-sync/lib/log.sh deleted file mode 120000 index 3d035ca54..000000000 --- a/plugins/todo-sync/lib/log.sh +++ /dev/null @@ -1 +0,0 @@ -../../../shared/lib/log.sh \ No newline at end of file diff --git a/plugins/todo-sync/scripts/init-gitignore.sh b/plugins/todo-sync/scripts/init-gitignore.sh deleted file mode 100755 index 6e0d9fbc4..000000000 --- a/plugins/todo-sync/scripts/init-gitignore.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -# init-gitignore.sh - Ensures .claude/todos and .claude/plans are globally ignored -# Triggered by SessionStart and UserPromptSubmit hooks -# -# This approach adds patterns to ~/.config/git/ignore so that: -# 1. All projects automatically ignore these directories -# 2. No per-project .gitignore files needed -# 3. No commits required in each project - -set -euo pipefail - -# shellcheck source=../lib/hook-output.sh -source "${CLAUDE_PLUGIN_ROOT}/lib/hook-output.sh" - -# Global gitignore location -global_gitignore="$HOME/.config/git/ignore" - -# Patterns to ensure are present -patterns=( - "**/.claude/plans" - "**/.claude/todos" -) - -# Create directory if needed -mkdir -p "$(dirname "$global_gitignore")" - -# Create file if it doesn't exist -touch "$global_gitignore" - -# Add each pattern if not already present -for pattern in "${patterns[@]}"; do - if ! grep -qxF "$pattern" "$global_gitignore" 2>/dev/null; then - echo "$pattern" >> "$global_gitignore" - fi -done - -hook_msg "todo-sync: gitignore patterns configured" diff --git a/plugins/todo-sync/scripts/sync-todos.sh b/plugins/todo-sync/scripts/sync-todos.sh deleted file mode 100755 index c6dc9ffed..000000000 --- a/plugins/todo-sync/scripts/sync-todos.sh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env bash -# sync-todos.sh - Syncs todos and plans from ~/.claude/ to project .claude/ -# Triggered by PostToolUse hook on TodoWrite - -set -euo pipefail - -PLUGIN_NAME="todo-sync" -# shellcheck source=../lib/log.sh -source "${CLAUDE_PLUGIN_ROOT}/lib/log.sh" - -# Check for jq dependency -if ! command -v jq &>/dev/null; then - log_warn "jq not found, skipping sync" - exit 0 -fi - -# Read hook input from stdin -input=$(cat) - -# Extract session_id from hook input -session_id=$(echo "$input" | jq -r '.session_id // empty') - -if [ -z "$session_id" ]; then - log_warn "No session_id in hook input, skipping sync" - exit 0 -fi - -# Determine project directory -project_dir="${CLAUDE_PROJECT_DIR:-$(pwd)}" - -# Create target directories if they don't exist -mkdir -p "$project_dir/.claude/todos" -mkdir -p "$project_dir/.claude/plans" - -# ============================================================================ -# SYNC TODOS -# ============================================================================ - -# Find the todo file for current session in ~/.claude/todos/ -# Files are named: {session-id}-agent-{agent-id}.json or just {session-id}.json -global_todos_dir="$HOME/.claude/todos" - -if [ -d "$global_todos_dir" ]; then - # Find files matching this session_id (using while read to handle filenames with spaces) - find "$global_todos_dir" -name "${session_id}*.json" -type f 2>/dev/null | while IFS= read -r src_file; do - filename=$(basename "$src_file") - dest_file="$project_dir/.claude/todos/$filename" - - # Read source todos - src_content=$(cat "$src_file" 2>/dev/null || echo "[]") - - # Skip empty arrays - if [ "$src_content" = "[]" ]; then - continue - fi - - # Check if destination exists for merge - if [ -f "$dest_file" ]; then - dest_content=$(cat "$dest_file" 2>/dev/null || echo "[]") - - # Merge: combine arrays, remove duplicates by content field - merged=$(jq -s ' - .[0] + .[1] | - unique_by(.content // .) - ' <(echo "$dest_content") <(echo "$src_content")) - - echo "$merged" > "$dest_file" - else - # No destination file, just copy - cp "$src_file" "$dest_file" - fi - done -fi - -# ============================================================================ -# SYNC PLANS -# ============================================================================ - -global_plans_dir="$HOME/.claude/plans" - -if [ -d "$global_plans_dir" ]; then - # Sync all plan files (they're markdown, so we just copy newer versions) - for src_file in "$global_plans_dir"/*.md; do - [ -f "$src_file" ] || continue - - filename=$(basename "$src_file") - dest_file="$project_dir/.claude/plans/$filename" - - # Only copy if source is newer or destination doesn't exist - if [ ! -f "$dest_file" ] || [ "$src_file" -nt "$dest_file" ]; then - cp "$src_file" "$dest_file" - fi - done -fi - -# Output success message (shown in transcript) -log_info "Synced todos and plans to $project_dir/.claude/" - -exit 0 diff --git a/plugins/todo-sync/skills/todo-sync/SKILL.md b/plugins/todo-sync/skills/todo-sync/SKILL.md deleted file mode 100644 index 5e14bfaa9..000000000 --- a/plugins/todo-sync/skills/todo-sync/SKILL.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -name: Todo Sync -description: Automatically syncs todos and plans from ~/.claude/ to the current project. Use this skill when asking about todo sync behavior, troubleshooting sync issues, or understanding where todos are stored. ---- - -# Todo Sync Plugin - -This plugin automatically synchronizes your todos and plans from the global Claude directory (`~/.claude/`) to your current project's `.claude/` directory. - -## How It Works - -The plugin uses a **PostToolUse hook** that triggers after every `TodoWrite` tool call: - -1. When you create or update todos using TodoWrite, the hook fires -2. The sync script finds your session's todo file in `~/.claude/todos/` -3. It merges the todos into `.claude/todos/` in your project -4. It also syncs any plan files from `~/.claude/plans/` to `.claude/plans/` - -## File Locations - -### Source (Global) - -- **Todos**: `~/.claude/todos/{session-id}.json` -- **Plans**: `~/.claude/plans/{plan-name}.md` - -### Destination (Project) - -- **Todos**: `.claude/todos/{session-id}.json` -- **Plans**: `.claude/plans/{plan-name}.md` - -## Merge Behavior - -**Todos**: When both source and destination files exist, todos are merged by deduplicating on the `content` field. This prevents duplicate todo entries. - -**Plans**: Plans are copied if the source is newer than the destination or if the destination doesn't exist. - -## Troubleshooting - -### Todos not syncing - -1. Check if `~/.claude/todos/` contains files for your session -2. Verify the plugin is enabled: look for it in `/plugins` command output -3. Check hook execution with `claude --debug` - -### Permission errors - -The script creates directories automatically. If you see permission errors: - -1. Ensure you have write access to your project directory -2. Check that `.claude/` isn't gitignored with restrictive permissions - -### Empty todo files - -Files containing only `[]` (empty arrays) are skipped during sync to avoid cluttering the project. - -## Integration with Git - -The plugin automatically adds patterns to `~/.config/git/ignore` (the global gitignore) for `.claude/todos/` and `.claude/plans/` directories. This prevents synced files from being committed in any project by default. - -If you want to track todos in version control for a specific project, add explicit `!.claude/todos/` pattern to that project's `.gitignore`. - -## Manual Sync - -The sync happens automatically on TodoWrite. If you need to manually trigger it, simply update your todos: - -``` -TodoWrite: [your todos here] -``` - -The hook will fire and sync will occur.