cognova 0.1.0
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.
- package/.env.example +58 -0
- package/Claude/CLAUDE.md +92 -0
- package/Claude/hooks/lib/__init__.py +1 -0
- package/Claude/hooks/lib/hook_client.py +207 -0
- package/Claude/hooks/log-event.py +97 -0
- package/Claude/hooks/pre-compact.py +46 -0
- package/Claude/hooks/session-end.py +26 -0
- package/Claude/hooks/session-start.py +35 -0
- package/Claude/hooks/stop-extract.py +40 -0
- package/Claude/rules/frontmatter.md +54 -0
- package/Claude/rules/markdown.md +43 -0
- package/Claude/rules/note-organization.md +33 -0
- package/Claude/settings.json +54 -0
- package/Claude/skills/README.md +136 -0
- package/Claude/skills/_lib/__init__.py +1 -0
- package/Claude/skills/_lib/api.py +164 -0
- package/Claude/skills/_lib/output.py +95 -0
- package/Claude/skills/environment/SKILL.md +73 -0
- package/Claude/skills/environment/environment.py +239 -0
- package/Claude/skills/memory/SKILL.md +153 -0
- package/Claude/skills/memory/memory.py +270 -0
- package/Claude/skills/project/SKILL.md +105 -0
- package/Claude/skills/project/project.py +203 -0
- package/Claude/skills/skill-creator/SKILL.md +261 -0
- package/Claude/skills/task/SKILL.md +135 -0
- package/Claude/skills/task/task.py +310 -0
- package/LICENSE +21 -0
- package/README.md +176 -0
- package/app/app.config.ts +8 -0
- package/app/app.vue +39 -0
- package/app/assets/css/main.css +10 -0
- package/app/components/AppLogo.vue +40 -0
- package/app/components/AssistantPanel.client.vue +518 -0
- package/app/components/ConfirmModal.vue +84 -0
- package/app/components/TemplateMenu.vue +49 -0
- package/app/components/agents/AgentActivityChart.client.vue +105 -0
- package/app/components/agents/AgentActivityChart.server.vue +25 -0
- package/app/components/agents/AgentForm.vue +304 -0
- package/app/components/agents/AgentRunModal.vue +154 -0
- package/app/components/agents/AgentStatsCards.vue +98 -0
- package/app/components/chat/ChatInput.vue +85 -0
- package/app/components/chat/ConversationList.vue +78 -0
- package/app/components/chat/MessageBubble.vue +81 -0
- package/app/components/chat/StreamingMessage.vue +36 -0
- package/app/components/chat/ToolCallBlock.vue +77 -0
- package/app/components/editor/CodeEditor.client.vue +212 -0
- package/app/components/editor/CodeEditorFallback.vue +12 -0
- package/app/components/editor/DocumentEditor.vue +326 -0
- package/app/components/editor/DocumentMetadata.vue +140 -0
- package/app/components/editor/MarkdownEditor.vue +146 -0
- package/app/components/files/FileTree.vue +436 -0
- package/app/components/hooks/HookActivityChart.client.vue +117 -0
- package/app/components/hooks/HookActivityChart.server.vue +25 -0
- package/app/components/hooks/HookStatsCards.vue +63 -0
- package/app/components/hooks/RecentEventsTable.vue +123 -0
- package/app/components/hooks/ToolBreakdownTable.vue +72 -0
- package/app/components/search/DashboardSearch.vue +122 -0
- package/app/components/tasks/ProjectSelect.vue +35 -0
- package/app/components/tasks/TaskCard.vue +182 -0
- package/app/components/tasks/TaskDetail.vue +160 -0
- package/app/components/tasks/TaskForm.vue +280 -0
- package/app/components/tasks/TaskList.vue +69 -0
- package/app/components/view/ViewToc.vue +85 -0
- package/app/composables/useAgents.ts +153 -0
- package/app/composables/useAuth.ts +73 -0
- package/app/composables/useChat.ts +298 -0
- package/app/composables/useDocument.ts +141 -0
- package/app/composables/useEditor.ts +100 -0
- package/app/composables/useFileTree.ts +220 -0
- package/app/composables/useHookEvents.ts +68 -0
- package/app/composables/useMemories.ts +83 -0
- package/app/composables/useNotificationBus.ts +154 -0
- package/app/composables/usePreferences.ts +131 -0
- package/app/composables/useProjects.ts +97 -0
- package/app/composables/useSearch.ts +52 -0
- package/app/composables/useTasks.ts +201 -0
- package/app/composables/useTerminal.ts +135 -0
- package/app/layouts/auth.vue +20 -0
- package/app/layouts/dashboard.vue +186 -0
- package/app/layouts/view.vue +60 -0
- package/app/middleware/auth.ts +9 -0
- package/app/pages/agents/[id].vue +602 -0
- package/app/pages/agents/index.vue +412 -0
- package/app/pages/chat.vue +146 -0
- package/app/pages/dashboard.vue +80 -0
- package/app/pages/docs.vue +131 -0
- package/app/pages/hooks.vue +163 -0
- package/app/pages/index.vue +249 -0
- package/app/pages/login.vue +60 -0
- package/app/pages/memories.vue +282 -0
- package/app/pages/settings.vue +625 -0
- package/app/pages/tasks.vue +312 -0
- package/app/pages/view/[uuid].vue +376 -0
- package/dist/cli/index.js +2711 -0
- package/drizzle.config.ts +10 -0
- package/nuxt.config.ts +98 -0
- package/package.json +107 -0
- package/server/api/agents/[id]/cancel.post.ts +27 -0
- package/server/api/agents/[id]/run.post.ts +34 -0
- package/server/api/agents/[id]/runs.get.ts +45 -0
- package/server/api/agents/[id]/stats.get.ts +94 -0
- package/server/api/agents/[id].delete.ts +29 -0
- package/server/api/agents/[id].get.ts +25 -0
- package/server/api/agents/[id].patch.ts +55 -0
- package/server/api/agents/index.get.ts +15 -0
- package/server/api/agents/index.post.ts +48 -0
- package/server/api/agents/stats.get.ts +86 -0
- package/server/api/auth/[...all].ts +5 -0
- package/server/api/conversations/[id].delete.ts +16 -0
- package/server/api/conversations/[id].get.ts +34 -0
- package/server/api/conversations/index.get.ts +17 -0
- package/server/api/documents/[id]/index.delete.ts +47 -0
- package/server/api/documents/[id]/index.put.ts +102 -0
- package/server/api/documents/[id]/public.get.ts +60 -0
- package/server/api/documents/[id]/restore.post.ts +65 -0
- package/server/api/documents/by-path.post.ts +168 -0
- package/server/api/documents/index.get.ts +48 -0
- package/server/api/fs/delete.post.ts +41 -0
- package/server/api/fs/list.get.ts +99 -0
- package/server/api/fs/mkdir.post.ts +44 -0
- package/server/api/fs/move.post.ts +68 -0
- package/server/api/fs/read.post.ts +48 -0
- package/server/api/fs/rename.post.ts +55 -0
- package/server/api/fs/write.post.ts +51 -0
- package/server/api/health.get.ts +40 -0
- package/server/api/home.get.ts +26 -0
- package/server/api/hooks/events/index.get.ts +56 -0
- package/server/api/hooks/events/index.post.ts +36 -0
- package/server/api/hooks/stats.get.ts +99 -0
- package/server/api/memory/[id].delete.ts +26 -0
- package/server/api/memory/context.get.ts +83 -0
- package/server/api/memory/extract.post.ts +42 -0
- package/server/api/memory/search.get.ts +70 -0
- package/server/api/memory/store.post.ts +31 -0
- package/server/api/projects/[id]/index.delete.ts +40 -0
- package/server/api/projects/[id]/index.get.ts +25 -0
- package/server/api/projects/[id]/index.put.ts +50 -0
- package/server/api/projects/index.get.ts +20 -0
- package/server/api/projects/index.post.ts +34 -0
- package/server/api/secrets/[key].delete.ts +31 -0
- package/server/api/secrets/[key].get.ts +30 -0
- package/server/api/secrets/[key].put.ts +52 -0
- package/server/api/secrets/index.get.ts +20 -0
- package/server/api/secrets/index.post.ts +58 -0
- package/server/api/tasks/[id]/index.delete.ts +46 -0
- package/server/api/tasks/[id]/index.get.ts +24 -0
- package/server/api/tasks/[id]/index.put.ts +70 -0
- package/server/api/tasks/[id]/restore.post.ts +49 -0
- package/server/api/tasks/index.get.ts +53 -0
- package/server/api/tasks/index.post.ts +47 -0
- package/server/api/tasks/tags.get.ts +21 -0
- package/server/api/user/email.patch.ts +56 -0
- package/server/db/index.ts +76 -0
- package/server/db/migrate.ts +41 -0
- package/server/db/schema.ts +345 -0
- package/server/db/seed.ts +46 -0
- package/server/db/types.ts +28 -0
- package/server/drizzle/migrations/0000_brown_george_stacy.sql +34 -0
- package/server/drizzle/migrations/0001_stormy_pyro.sql +16 -0
- package/server/drizzle/migrations/0002_clean_colossus.sql +50 -0
- package/server/drizzle/migrations/0003_fine_joystick.sql +12 -0
- package/server/drizzle/migrations/0004_tan_groot.sql +26 -0
- package/server/drizzle/migrations/0005_cloudy_lilith.sql +33 -0
- package/server/drizzle/migrations/0006_ordinary_retro_girl.sql +13 -0
- package/server/drizzle/migrations/0007_flowery_venus.sql +15 -0
- package/server/drizzle/migrations/0008_talented_zombie.sql +13 -0
- package/server/drizzle/migrations/0009_gray_shen.sql +15 -0
- package/server/drizzle/migrations/meta/0000_snapshot.json +230 -0
- package/server/drizzle/migrations/meta/0001_snapshot.json +306 -0
- package/server/drizzle/migrations/meta/0002_snapshot.json +615 -0
- package/server/drizzle/migrations/meta/0003_snapshot.json +730 -0
- package/server/drizzle/migrations/meta/0004_snapshot.json +916 -0
- package/server/drizzle/migrations/meta/0005_snapshot.json +1127 -0
- package/server/drizzle/migrations/meta/0006_snapshot.json +1213 -0
- package/server/drizzle/migrations/meta/0007_snapshot.json +1307 -0
- package/server/drizzle/migrations/meta/0008_snapshot.json +1390 -0
- package/server/drizzle/migrations/meta/0009_snapshot.json +1487 -0
- package/server/drizzle/migrations/meta/_journal.json +76 -0
- package/server/middleware/auth.ts +79 -0
- package/server/plugins/00.env-validate.ts +38 -0
- package/server/plugins/01.api-token.ts +31 -0
- package/server/plugins/02.database.ts +54 -0
- package/server/plugins/03.file-watcher.ts +65 -0
- package/server/plugins/04.cron-agents.ts +26 -0
- package/server/routes/_ws/chat.ts +252 -0
- package/server/routes/notifications.ts +47 -0
- package/server/routes/terminal.ts +98 -0
- package/server/services/agent-executor.ts +218 -0
- package/server/services/cron-scheduler.ts +78 -0
- package/server/services/memory-extractor.ts +120 -0
- package/server/utils/agent-cleanup.ts +91 -0
- package/server/utils/agent-registry.ts +95 -0
- package/server/utils/auth.ts +33 -0
- package/server/utils/chat-session-manager.ts +59 -0
- package/server/utils/crypto.ts +40 -0
- package/server/utils/db-guard.ts +12 -0
- package/server/utils/db-state.ts +63 -0
- package/server/utils/document-sync.ts +207 -0
- package/server/utils/frontmatter.ts +84 -0
- package/server/utils/notification-bus.ts +60 -0
- package/server/utils/path-validator.ts +55 -0
- package/server/utils/pty-manager.ts +130 -0
- package/shared/types/index.ts +604 -0
- package/shared/utils/language-detection.ts +87 -0
- package/tsconfig.json +10 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project
|
|
3
|
+
description: Manage Cognova projects - create, list, update projects. ALWAYS searches for existing projects before creating new ones. ALWAYS confirms with user before creating, showing potential matches.
|
|
4
|
+
allowed-tools: Bash, Read
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Project Management Skill
|
|
8
|
+
|
|
9
|
+
Manage projects in Cognova. Projects organize related tasks.
|
|
10
|
+
|
|
11
|
+
## CRITICAL: Duplicate Prevention
|
|
12
|
+
|
|
13
|
+
**ALWAYS search for existing projects before creating:**
|
|
14
|
+
1. Run `python3 ~/.claude/skills/project/project.py search <name>` first
|
|
15
|
+
2. Show user any matches found
|
|
16
|
+
3. Only create if user confirms no existing project fits
|
|
17
|
+
|
|
18
|
+
## Commands
|
|
19
|
+
|
|
20
|
+
### Search for projects
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
python3 ~/.claude/skills/project/project.py search <query>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
```bash
|
|
28
|
+
python3 ~/.claude/skills/project/project.py search "home"
|
|
29
|
+
# Output: Found 2 projects matching "home":
|
|
30
|
+
# - homelab (#3b82f6) - ID: abc12345
|
|
31
|
+
# - home-automation (#22c55e) - ID: def67890
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### List all projects
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python3 ~/.claude/skills/project/project.py list
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Create a project
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python3 ~/.claude/skills/project/project.py create <name> --color <hex> [--description <text>]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Required:** `--color` must be a valid hex color (e.g., #3b82f6)
|
|
47
|
+
|
|
48
|
+
Example:
|
|
49
|
+
```bash
|
|
50
|
+
python3 ~/.claude/skills/project/project.py create "Cognova" --color "#8b5cf6" --description "Personal knowledge management app"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Update a project
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python3 ~/.claude/skills/project/project.py update <id> [options]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Options:
|
|
60
|
+
- `--name <name>` - New project name
|
|
61
|
+
- `--color <hex>` - New color
|
|
62
|
+
- `--description <text>` - New description
|
|
63
|
+
|
|
64
|
+
### Delete a project
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
python3 ~/.claude/skills/project/project.py delete <id>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Workflow: Creating a Project
|
|
71
|
+
|
|
72
|
+
When user asks to create a project:
|
|
73
|
+
|
|
74
|
+
1. **Search first:**
|
|
75
|
+
```bash
|
|
76
|
+
python3 ~/.claude/skills/project/project.py search "project name"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
2. **If matches found, ask user:**
|
|
80
|
+
"I found these existing projects that might match:
|
|
81
|
+
- existing-project-1
|
|
82
|
+
- existing-project-2
|
|
83
|
+
|
|
84
|
+
Would you like to use one of these, or create a new project?"
|
|
85
|
+
|
|
86
|
+
3. **If user confirms new project:**
|
|
87
|
+
- Ask for color preference (suggest one if not provided)
|
|
88
|
+
- Create with: `python3 ~/.claude/skills/project/project.py create "name" --color "#hexcolor"`
|
|
89
|
+
|
|
90
|
+
## Color Suggestions
|
|
91
|
+
|
|
92
|
+
When user doesn't specify a color, suggest based on project type:
|
|
93
|
+
- Development/Tech: Blue (#3b82f6)
|
|
94
|
+
- Personal: Purple (#8b5cf6)
|
|
95
|
+
- Health: Green (#22c55e)
|
|
96
|
+
- Finance: Yellow (#eab308)
|
|
97
|
+
- Home: Orange (#f97316)
|
|
98
|
+
- Work: Red (#ef4444)
|
|
99
|
+
|
|
100
|
+
## Natural Language Patterns
|
|
101
|
+
|
|
102
|
+
- "Create a project for..." -> Search first, then create with confirmation
|
|
103
|
+
- "List my projects" -> Use `list`
|
|
104
|
+
- "Find projects about..." -> Use `search`
|
|
105
|
+
- "Show project colors" -> Use `list` and display colors
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Project Management Skill for Cognova
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python project.py search <query>
|
|
7
|
+
python project.py list
|
|
8
|
+
python project.py create <name> --color <hex> [--description <text>]
|
|
9
|
+
python project.py update <id> [options]
|
|
10
|
+
python project.py delete <id>
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import re
|
|
15
|
+
import sys
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
sys.path.insert(0, str(Path(__file__).parent.parent / '_lib'))
|
|
19
|
+
|
|
20
|
+
from api import get, post, put, delete
|
|
21
|
+
from output import success, error, info, warn, format_project
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def validate_color(color: str) -> bool:
|
|
25
|
+
"""Validate hex color format."""
|
|
26
|
+
return bool(re.match(r'^#[0-9A-Fa-f]{6}$', color))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def find_project_by_id(id_prefix: str) -> str | None:
|
|
30
|
+
"""Find a project by ID prefix."""
|
|
31
|
+
ok, projects = get('/projects')
|
|
32
|
+
if not ok:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
for project in projects:
|
|
36
|
+
if project['id'].startswith(id_prefix):
|
|
37
|
+
return project['id']
|
|
38
|
+
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def cmd_search(args):
|
|
43
|
+
"""Search for projects by name."""
|
|
44
|
+
ok, projects = get('/projects')
|
|
45
|
+
if not ok:
|
|
46
|
+
error(f"Failed to fetch projects: {projects}")
|
|
47
|
+
sys.exit(1)
|
|
48
|
+
|
|
49
|
+
query = args.query.lower()
|
|
50
|
+
matches = [p for p in projects if query in p['name'].lower()]
|
|
51
|
+
|
|
52
|
+
if not matches:
|
|
53
|
+
print(f"No projects found matching '{args.query}'")
|
|
54
|
+
return
|
|
55
|
+
|
|
56
|
+
print(f"Found {len(matches)} project(s) matching '{args.query}':\n")
|
|
57
|
+
for p in matches:
|
|
58
|
+
print(format_project(p))
|
|
59
|
+
print()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def cmd_list(args):
|
|
63
|
+
"""List all projects."""
|
|
64
|
+
ok, projects = get('/projects')
|
|
65
|
+
if not ok:
|
|
66
|
+
error(f"Failed to fetch projects: {projects}")
|
|
67
|
+
sys.exit(1)
|
|
68
|
+
|
|
69
|
+
if not projects:
|
|
70
|
+
print("No projects found.")
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
print(f"Found {len(projects)} project(s):\n")
|
|
74
|
+
for p in projects:
|
|
75
|
+
print(format_project(p))
|
|
76
|
+
print()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def cmd_create(args):
|
|
80
|
+
"""Create a new project."""
|
|
81
|
+
if not validate_color(args.color):
|
|
82
|
+
error(f"Invalid color format: {args.color}. Use hex format like #3b82f6")
|
|
83
|
+
sys.exit(1)
|
|
84
|
+
|
|
85
|
+
# Check for existing projects with similar names
|
|
86
|
+
ok, projects = get('/projects')
|
|
87
|
+
if ok:
|
|
88
|
+
name_lower = args.name.lower()
|
|
89
|
+
similar = [p for p in projects if
|
|
90
|
+
name_lower in p['name'].lower() or
|
|
91
|
+
p['name'].lower() in name_lower]
|
|
92
|
+
if similar:
|
|
93
|
+
warn("Similar projects already exist:")
|
|
94
|
+
for p in similar:
|
|
95
|
+
print(f" - {p['name']} ({p['color']}) ID: {p['id'][:8]}", file=sys.stderr)
|
|
96
|
+
print("\nConsider using an existing project instead.", file=sys.stderr)
|
|
97
|
+
|
|
98
|
+
data = {
|
|
99
|
+
'name': args.name,
|
|
100
|
+
'color': args.color,
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if args.description:
|
|
104
|
+
data['description'] = args.description
|
|
105
|
+
|
|
106
|
+
ok, result = post('/projects', data)
|
|
107
|
+
if ok:
|
|
108
|
+
success(f"Created project: {result['name']}", result)
|
|
109
|
+
else:
|
|
110
|
+
error(f"Failed to create project: {result}")
|
|
111
|
+
sys.exit(1)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def cmd_update(args):
|
|
115
|
+
"""Update a project."""
|
|
116
|
+
data = {}
|
|
117
|
+
|
|
118
|
+
if args.name:
|
|
119
|
+
data['name'] = args.name
|
|
120
|
+
if args.color:
|
|
121
|
+
if not validate_color(args.color):
|
|
122
|
+
error(f"Invalid color format: {args.color}")
|
|
123
|
+
sys.exit(1)
|
|
124
|
+
data['color'] = args.color
|
|
125
|
+
if args.description:
|
|
126
|
+
data['description'] = args.description
|
|
127
|
+
|
|
128
|
+
if not data:
|
|
129
|
+
error("No updates specified")
|
|
130
|
+
sys.exit(1)
|
|
131
|
+
|
|
132
|
+
project_id = find_project_by_id(args.id)
|
|
133
|
+
if not project_id:
|
|
134
|
+
error(f"Project not found: {args.id}")
|
|
135
|
+
sys.exit(1)
|
|
136
|
+
|
|
137
|
+
ok, result = put(f'/projects/{project_id}', data)
|
|
138
|
+
if ok:
|
|
139
|
+
success(f"Updated project: {result['name']}", result)
|
|
140
|
+
else:
|
|
141
|
+
error(f"Failed to update project: {result}")
|
|
142
|
+
sys.exit(1)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def cmd_delete(args):
|
|
146
|
+
"""Delete a project (soft delete)."""
|
|
147
|
+
project_id = find_project_by_id(args.id)
|
|
148
|
+
if not project_id:
|
|
149
|
+
error(f"Project not found: {args.id}")
|
|
150
|
+
sys.exit(1)
|
|
151
|
+
|
|
152
|
+
ok, result = delete(f'/projects/{project_id}')
|
|
153
|
+
if ok:
|
|
154
|
+
success(f"Deleted project: {args.id}")
|
|
155
|
+
else:
|
|
156
|
+
error(f"Failed to delete project: {result}")
|
|
157
|
+
sys.exit(1)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def main():
|
|
161
|
+
parser = argparse.ArgumentParser(description='Project Management Skill')
|
|
162
|
+
subparsers = parser.add_subparsers(dest='command', required=True)
|
|
163
|
+
|
|
164
|
+
# Search
|
|
165
|
+
search_p = subparsers.add_parser('search', help='Search for projects')
|
|
166
|
+
search_p.add_argument('query', help='Search query')
|
|
167
|
+
|
|
168
|
+
# List
|
|
169
|
+
subparsers.add_parser('list', help='List all projects')
|
|
170
|
+
|
|
171
|
+
# Create
|
|
172
|
+
create_p = subparsers.add_parser('create', help='Create a new project')
|
|
173
|
+
create_p.add_argument('name', help='Project name')
|
|
174
|
+
create_p.add_argument('--color', '-c', required=True,
|
|
175
|
+
help='Hex color (e.g., #3b82f6)')
|
|
176
|
+
create_p.add_argument('--description', '-d', help='Project description')
|
|
177
|
+
|
|
178
|
+
# Update
|
|
179
|
+
update_p = subparsers.add_parser('update', help='Update a project')
|
|
180
|
+
update_p.add_argument('id', help='Project ID (prefix)')
|
|
181
|
+
update_p.add_argument('--name', help='New name')
|
|
182
|
+
update_p.add_argument('--color', help='New color')
|
|
183
|
+
update_p.add_argument('--description', help='New description')
|
|
184
|
+
|
|
185
|
+
# Delete
|
|
186
|
+
delete_p = subparsers.add_parser('delete', help='Delete a project')
|
|
187
|
+
delete_p.add_argument('id', help='Project ID (prefix)')
|
|
188
|
+
|
|
189
|
+
args = parser.parse_args()
|
|
190
|
+
|
|
191
|
+
commands = {
|
|
192
|
+
'search': cmd_search,
|
|
193
|
+
'list': cmd_list,
|
|
194
|
+
'create': cmd_create,
|
|
195
|
+
'update': cmd_update,
|
|
196
|
+
'delete': cmd_delete,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
commands[args.command](args)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
if __name__ == '__main__':
|
|
203
|
+
main()
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: skill-creator
|
|
3
|
+
description: Assists users in creating new Claude Code skills. Uses web search to find latest conventions and suggests alternative approaches (existing MCPs, plugins) when appropriate.
|
|
4
|
+
allowed-tools: Bash, Read, Write, WebSearch, WebFetch
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Skill Creator
|
|
9
|
+
|
|
10
|
+
Assists in creating new Claude Code skills for Cognova or personal use.
|
|
11
|
+
|
|
12
|
+
## Process
|
|
13
|
+
|
|
14
|
+
When a user asks to create a new skill:
|
|
15
|
+
|
|
16
|
+
### 1. Understand the Requirement
|
|
17
|
+
|
|
18
|
+
Ask clarifying questions:
|
|
19
|
+
- What should the skill do?
|
|
20
|
+
- Should it be invokable by user, Claude, or both?
|
|
21
|
+
- Does it need to call external APIs?
|
|
22
|
+
- Should it run in a subagent (forked context)?
|
|
23
|
+
|
|
24
|
+
### 2. Check for Existing Solutions
|
|
25
|
+
|
|
26
|
+
**ALWAYS search before implementing:**
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
WebSearch: "Claude Code MCP <functionality>"
|
|
30
|
+
WebSearch: "Claude Code plugin <functionality>"
|
|
31
|
+
WebSearch: "anthropic MCP server <functionality>"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If an MCP or plugin exists:
|
|
35
|
+
- Explain what it does
|
|
36
|
+
- Show how to install/configure it
|
|
37
|
+
- Ask if user still wants a custom skill
|
|
38
|
+
|
|
39
|
+
### 3. Determine Skill Type
|
|
40
|
+
|
|
41
|
+
| Type | When to Use | Example |
|
|
42
|
+
|------|-------------|---------|
|
|
43
|
+
| **Pure Instruction** | Claude can handle with existing tools | `/capture` - save note to inbox |
|
|
44
|
+
| **Python Script** | Needs API calls, complex logic | `/task` - manage tasks via API |
|
|
45
|
+
| **Subagent** | Long-running, exploratory | `/research` - deep dive on topic |
|
|
46
|
+
|
|
47
|
+
### 4. Create the Skill
|
|
48
|
+
|
|
49
|
+
#### For Pure Instruction Skills
|
|
50
|
+
|
|
51
|
+
Create only `SKILL.md` in the appropriate location:
|
|
52
|
+
|
|
53
|
+
- Personal: `~/.claude/skills/<skill-name>/SKILL.md`
|
|
54
|
+
- Project: `.claude/skills/<skill-name>/SKILL.md`
|
|
55
|
+
|
|
56
|
+
```yaml
|
|
57
|
+
---
|
|
58
|
+
name: skill-name
|
|
59
|
+
description: When to use this skill
|
|
60
|
+
allowed-tools: Bash, Read, Write, etc.
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
# Skill Name
|
|
64
|
+
|
|
65
|
+
Instructions for Claude to follow...
|
|
66
|
+
|
|
67
|
+
## Usage
|
|
68
|
+
|
|
69
|
+
/skill-name <args>
|
|
70
|
+
|
|
71
|
+
## Process
|
|
72
|
+
|
|
73
|
+
1. Step one
|
|
74
|
+
2. Step two
|
|
75
|
+
...
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### For Python Script Skills
|
|
79
|
+
|
|
80
|
+
Create `SKILL.md` + `script.py`:
|
|
81
|
+
|
|
82
|
+
**SKILL.md Template:**
|
|
83
|
+
```yaml
|
|
84
|
+
---
|
|
85
|
+
name: skill-name
|
|
86
|
+
description: Description for Claude's auto-invocation
|
|
87
|
+
allowed-tools: Bash, Read
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
# Skill Name
|
|
91
|
+
|
|
92
|
+
## Commands
|
|
93
|
+
|
|
94
|
+
\`\`\`bash
|
|
95
|
+
python3 ~/.claude/skills/<name>/<name>.py <command> [options]
|
|
96
|
+
\`\`\`
|
|
97
|
+
|
|
98
|
+
## Examples
|
|
99
|
+
...
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Python Template:**
|
|
103
|
+
```python
|
|
104
|
+
#!/usr/bin/env python3
|
|
105
|
+
"""Skill description."""
|
|
106
|
+
|
|
107
|
+
import argparse
|
|
108
|
+
import sys
|
|
109
|
+
from pathlib import Path
|
|
110
|
+
|
|
111
|
+
def main():
|
|
112
|
+
parser = argparse.ArgumentParser(description='Skill Name')
|
|
113
|
+
# Add subparsers for commands
|
|
114
|
+
args = parser.parse_args()
|
|
115
|
+
# Execute command
|
|
116
|
+
|
|
117
|
+
if __name__ == '__main__':
|
|
118
|
+
main()
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 5. Accessing Secrets & API Keys
|
|
122
|
+
|
|
123
|
+
**NEVER hardcode API keys, tokens, or sensitive values in skills.**
|
|
124
|
+
|
|
125
|
+
Cognova provides an encrypted secrets store. Use the shared API client:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
#!/usr/bin/env python3
|
|
129
|
+
import sys
|
|
130
|
+
from pathlib import Path
|
|
131
|
+
sys.path.insert(0, str(Path(__file__).parent.parent)) # Add parent for _lib
|
|
132
|
+
from _lib.api import get_secret, get, post
|
|
133
|
+
|
|
134
|
+
# Fetch a secret by key
|
|
135
|
+
success, api_key = get_secret("GOOGLE_API_KEY")
|
|
136
|
+
if not success:
|
|
137
|
+
print(f"Error: {api_key}")
|
|
138
|
+
print("Add this secret at Settings > Secrets in the dashboard")
|
|
139
|
+
sys.exit(1)
|
|
140
|
+
|
|
141
|
+
# Now use api_key safely
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Key naming convention:** `SCREAMING_SNAKE_CASE` (e.g., `DISCORD_WEBHOOK_URL`, `OPENAI_API_KEY`)
|
|
145
|
+
|
|
146
|
+
**Managing secrets:**
|
|
147
|
+
- Dashboard: Settings > Secrets tab
|
|
148
|
+
- Create: Add key + value (value is encrypted at rest)
|
|
149
|
+
- Skills fetch decrypted values via `get_secret()`
|
|
150
|
+
|
|
151
|
+
**When to use secrets vs environment variables:**
|
|
152
|
+
| Use Case | Approach |
|
|
153
|
+
|----------|----------|
|
|
154
|
+
| API keys for external services | Secrets store (`get_secret()`) |
|
|
155
|
+
| Webhook URLs, tokens | Secrets store |
|
|
156
|
+
| Cognova API URL | Environment variable (pre-configured) |
|
|
157
|
+
| Database URLs | Environment variables (system config) |
|
|
158
|
+
|
|
159
|
+
#### Environment Variables
|
|
160
|
+
|
|
161
|
+
The `_lib/api.py` module automatically handles these environment variables:
|
|
162
|
+
|
|
163
|
+
| Variable | Default | Description |
|
|
164
|
+
|----------|---------|-------------|
|
|
165
|
+
| `COGNOVA_API_URL` | `http://localhost:3000` | API base URL |
|
|
166
|
+
| `COGNOVA_API_TOKEN` | Auto-generated | Auth token (auto-read from `.api-token`) |
|
|
167
|
+
|
|
168
|
+
**For Docker deployments**, these are pre-configured in `docker-compose.yml`. Skills don't need to set them.
|
|
169
|
+
|
|
170
|
+
**For local development**, the API token is auto-generated on server startup and written to `.api-token` in the project root. The `_lib/api.py` module reads it automatically.
|
|
171
|
+
|
|
172
|
+
**Custom environment variables** can be added to `.env` (local) or `docker-compose.yml` (Docker):
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# .env
|
|
176
|
+
MY_CUSTOM_VAR=value
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
# In skill
|
|
181
|
+
import os
|
|
182
|
+
my_var = os.environ.get('MY_CUSTOM_VAR', 'default')
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 6. Skill Frontmatter Options
|
|
186
|
+
|
|
187
|
+
| Option | Values | Description |
|
|
188
|
+
|--------|--------|-------------|
|
|
189
|
+
| `name` | string | Command name (becomes `/name`) |
|
|
190
|
+
| `description` | string | When Claude should use this skill |
|
|
191
|
+
| `allowed-tools` | Bash, Read, Write, Edit, WebSearch, WebFetch, Grep, Glob | Tools Claude can use |
|
|
192
|
+
| `disable-model-invocation` | true | User-only, Claude won't auto-invoke |
|
|
193
|
+
| `user-invocable` | false | Claude-only, hidden from user menu |
|
|
194
|
+
| `context` | fork | Run in subagent |
|
|
195
|
+
| `agent` | Explore, Plan, general-purpose | Agent type for subagent |
|
|
196
|
+
|
|
197
|
+
### 7. Skill Locations
|
|
198
|
+
|
|
199
|
+
| Location | Use Case |
|
|
200
|
+
|----------|----------|
|
|
201
|
+
| `~/.claude/skills/` | Personal + Cognova bundled skills |
|
|
202
|
+
| `.claude/skills/` | Project-specific skills |
|
|
203
|
+
|
|
204
|
+
### 8. Testing
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Test Python script directly
|
|
208
|
+
python3 ~/.claude/skills/<name>/<name>.py --help
|
|
209
|
+
|
|
210
|
+
# Test via Claude Code
|
|
211
|
+
claude
|
|
212
|
+
> /skill-name test
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Example: Creating a Simple Skill
|
|
216
|
+
|
|
217
|
+
User: "I want a skill to quickly add notes to my inbox"
|
|
218
|
+
|
|
219
|
+
Response:
|
|
220
|
+
"This is perfect for a pure instruction skill. Let me create it:
|
|
221
|
+
|
|
222
|
+
**File: `~/.claude/skills/capture/SKILL.md`**
|
|
223
|
+
```yaml
|
|
224
|
+
---
|
|
225
|
+
name: capture
|
|
226
|
+
description: Quickly capture a note to the inbox folder
|
|
227
|
+
allowed-tools: Write
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
# Quick Capture
|
|
231
|
+
|
|
232
|
+
Save a quick note to the inbox.
|
|
233
|
+
|
|
234
|
+
## Usage
|
|
235
|
+
|
|
236
|
+
/capture <note content>
|
|
237
|
+
|
|
238
|
+
## Process
|
|
239
|
+
|
|
240
|
+
1. Generate filename: `inbox/YYYY-MM-DD-<slugified-title>.md`
|
|
241
|
+
2. Create file with frontmatter:
|
|
242
|
+
\`\`\`markdown
|
|
243
|
+
---
|
|
244
|
+
created: <ISO timestamp>
|
|
245
|
+
status: inbox
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
<note content>
|
|
249
|
+
\`\`\`
|
|
250
|
+
3. Confirm creation to user
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
This skill needs no Python script - Claude will use the Write tool directly."
|
|
254
|
+
|
|
255
|
+
## Web Search Patterns
|
|
256
|
+
|
|
257
|
+
For finding existing solutions:
|
|
258
|
+
- MCPs: `"MCP server" <functionality> site:github.com`
|
|
259
|
+
- Claude plugins: `"claude code" plugin <functionality>`
|
|
260
|
+
- Best practices: `"claude code" skill best practices`
|
|
261
|
+
- Latest conventions: `site:code.claude.com skills`
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task
|
|
3
|
+
description: Manage Cognova tasks - create, list, update, complete tasks. Use when the user wants to track work items, todos, or action items. Can search for and associate tasks with projects.
|
|
4
|
+
allowed-tools: Bash, Read
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Task Management Skill
|
|
8
|
+
|
|
9
|
+
Manage tasks in Cognova through natural language commands.
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
### Create a task
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
python3 ~/.claude/skills/task/task.py create "Task title" [options]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Options:
|
|
20
|
+
- `--project <name>` - Associate with project (searches for match)
|
|
21
|
+
- `--priority <1|2|3>` - Set priority (1=Low, 2=Medium, 3=High)
|
|
22
|
+
- `--due <date>` - Set due date (YYYY-MM-DD or natural: "tomorrow", "next monday")
|
|
23
|
+
- `--tags <tag1,tag2>` - Add comma-separated tags
|
|
24
|
+
- `--description <text>` - Add description
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
```bash
|
|
28
|
+
python3 ~/.claude/skills/task/task.py create "Review PR for auth feature" --project "cognova" --priority 3
|
|
29
|
+
python3 ~/.claude/skills/task/task.py create "Call dentist" --due tomorrow
|
|
30
|
+
python3 ~/.claude/skills/task/task.py create "Write documentation" --tags "docs,urgent"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### List tasks
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python3 ~/.claude/skills/task/task.py list [filters]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Filters:
|
|
40
|
+
- `--status <todo|in_progress|done|blocked>` - Filter by status
|
|
41
|
+
- `--project <name>` - Filter by project (partial match)
|
|
42
|
+
- `--search <query>` - Search title/description
|
|
43
|
+
- `--due <today|week|overdue>` - Filter by due date
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
```bash
|
|
47
|
+
python3 ~/.claude/skills/task/task.py list
|
|
48
|
+
python3 ~/.claude/skills/task/task.py list --project homelab --status todo
|
|
49
|
+
python3 ~/.claude/skills/task/task.py list --due overdue
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Update a task
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
python3 ~/.claude/skills/task/task.py update <id> [options]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Options: Same as create, plus `--status`
|
|
59
|
+
|
|
60
|
+
Example:
|
|
61
|
+
```bash
|
|
62
|
+
python3 ~/.claude/skills/task/task.py update abc123 --status in_progress --priority 3
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Complete a task
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
python3 ~/.claude/skills/task/task.py done <id_or_search>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Examples:
|
|
72
|
+
```bash
|
|
73
|
+
python3 ~/.claude/skills/task/task.py done abc123
|
|
74
|
+
python3 ~/.claude/skills/task/task.py done "PR review"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Delete a task
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
python3 ~/.claude/skills/task/task.py delete <id>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Natural Language Patterns
|
|
84
|
+
|
|
85
|
+
When users say things like:
|
|
86
|
+
- "Create a task to..." -> Use `create`
|
|
87
|
+
- "What tasks do I have..." -> Use `list`
|
|
88
|
+
- "Mark X as done" -> Use `done`
|
|
89
|
+
- "I finished the..." -> Use `done` with search
|
|
90
|
+
- "Show my todos" -> Use `list --status todo`
|
|
91
|
+
|
|
92
|
+
## Project Association
|
|
93
|
+
|
|
94
|
+
When creating tasks with `--project`:
|
|
95
|
+
1. The skill searches for matching projects
|
|
96
|
+
2. If one match found, associates automatically
|
|
97
|
+
3. If multiple matches, lists them for user to choose
|
|
98
|
+
4. If no match, creates task without project and suggests creating one
|
|
99
|
+
|
|
100
|
+
## Frontmatter Standards
|
|
101
|
+
|
|
102
|
+
All markdown documents in the vault use YAML frontmatter for metadata. When new documents are created or discovered without frontmatter, defaults are automatically added:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
---
|
|
106
|
+
tags: []
|
|
107
|
+
shared: false
|
|
108
|
+
---
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Frontmatter Fields
|
|
112
|
+
|
|
113
|
+
| Field | Type | Default | Description |
|
|
114
|
+
|-------|------|---------|-------------|
|
|
115
|
+
| `tags` | string[] | `[]` | Array of tag strings for categorization |
|
|
116
|
+
| `shared` | boolean | `false` | Visibility: `false` = hidden (auth required) |
|
|
117
|
+
| `shareType` | string | - | When `shared: true`: `'private'` (link only) or `'public'` (indexed) |
|
|
118
|
+
| `title` | string | - | Optional override; extracted from H1 or filename if not set |
|
|
119
|
+
| `project` | string | - | Project ID for document association |
|
|
120
|
+
|
|
121
|
+
### Visibility Modes
|
|
122
|
+
|
|
123
|
+
Documents support three visibility levels:
|
|
124
|
+
|
|
125
|
+
1. **Hidden** (default) - `shared: false`
|
|
126
|
+
- Requires authentication
|
|
127
|
+
- Never publicly accessible
|
|
128
|
+
|
|
129
|
+
2. **Private** - `shared: true, shareType: 'private'`
|
|
130
|
+
- Accessible via direct link
|
|
131
|
+
- Not indexed by search engines
|
|
132
|
+
|
|
133
|
+
3. **Public** - `shared: true, shareType: 'public'`
|
|
134
|
+
- Publicly accessible
|
|
135
|
+
- Indexed by search engines
|