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.
Files changed (205) hide show
  1. package/.env.example +58 -0
  2. package/Claude/CLAUDE.md +92 -0
  3. package/Claude/hooks/lib/__init__.py +1 -0
  4. package/Claude/hooks/lib/hook_client.py +207 -0
  5. package/Claude/hooks/log-event.py +97 -0
  6. package/Claude/hooks/pre-compact.py +46 -0
  7. package/Claude/hooks/session-end.py +26 -0
  8. package/Claude/hooks/session-start.py +35 -0
  9. package/Claude/hooks/stop-extract.py +40 -0
  10. package/Claude/rules/frontmatter.md +54 -0
  11. package/Claude/rules/markdown.md +43 -0
  12. package/Claude/rules/note-organization.md +33 -0
  13. package/Claude/settings.json +54 -0
  14. package/Claude/skills/README.md +136 -0
  15. package/Claude/skills/_lib/__init__.py +1 -0
  16. package/Claude/skills/_lib/api.py +164 -0
  17. package/Claude/skills/_lib/output.py +95 -0
  18. package/Claude/skills/environment/SKILL.md +73 -0
  19. package/Claude/skills/environment/environment.py +239 -0
  20. package/Claude/skills/memory/SKILL.md +153 -0
  21. package/Claude/skills/memory/memory.py +270 -0
  22. package/Claude/skills/project/SKILL.md +105 -0
  23. package/Claude/skills/project/project.py +203 -0
  24. package/Claude/skills/skill-creator/SKILL.md +261 -0
  25. package/Claude/skills/task/SKILL.md +135 -0
  26. package/Claude/skills/task/task.py +310 -0
  27. package/LICENSE +21 -0
  28. package/README.md +176 -0
  29. package/app/app.config.ts +8 -0
  30. package/app/app.vue +39 -0
  31. package/app/assets/css/main.css +10 -0
  32. package/app/components/AppLogo.vue +40 -0
  33. package/app/components/AssistantPanel.client.vue +518 -0
  34. package/app/components/ConfirmModal.vue +84 -0
  35. package/app/components/TemplateMenu.vue +49 -0
  36. package/app/components/agents/AgentActivityChart.client.vue +105 -0
  37. package/app/components/agents/AgentActivityChart.server.vue +25 -0
  38. package/app/components/agents/AgentForm.vue +304 -0
  39. package/app/components/agents/AgentRunModal.vue +154 -0
  40. package/app/components/agents/AgentStatsCards.vue +98 -0
  41. package/app/components/chat/ChatInput.vue +85 -0
  42. package/app/components/chat/ConversationList.vue +78 -0
  43. package/app/components/chat/MessageBubble.vue +81 -0
  44. package/app/components/chat/StreamingMessage.vue +36 -0
  45. package/app/components/chat/ToolCallBlock.vue +77 -0
  46. package/app/components/editor/CodeEditor.client.vue +212 -0
  47. package/app/components/editor/CodeEditorFallback.vue +12 -0
  48. package/app/components/editor/DocumentEditor.vue +326 -0
  49. package/app/components/editor/DocumentMetadata.vue +140 -0
  50. package/app/components/editor/MarkdownEditor.vue +146 -0
  51. package/app/components/files/FileTree.vue +436 -0
  52. package/app/components/hooks/HookActivityChart.client.vue +117 -0
  53. package/app/components/hooks/HookActivityChart.server.vue +25 -0
  54. package/app/components/hooks/HookStatsCards.vue +63 -0
  55. package/app/components/hooks/RecentEventsTable.vue +123 -0
  56. package/app/components/hooks/ToolBreakdownTable.vue +72 -0
  57. package/app/components/search/DashboardSearch.vue +122 -0
  58. package/app/components/tasks/ProjectSelect.vue +35 -0
  59. package/app/components/tasks/TaskCard.vue +182 -0
  60. package/app/components/tasks/TaskDetail.vue +160 -0
  61. package/app/components/tasks/TaskForm.vue +280 -0
  62. package/app/components/tasks/TaskList.vue +69 -0
  63. package/app/components/view/ViewToc.vue +85 -0
  64. package/app/composables/useAgents.ts +153 -0
  65. package/app/composables/useAuth.ts +73 -0
  66. package/app/composables/useChat.ts +298 -0
  67. package/app/composables/useDocument.ts +141 -0
  68. package/app/composables/useEditor.ts +100 -0
  69. package/app/composables/useFileTree.ts +220 -0
  70. package/app/composables/useHookEvents.ts +68 -0
  71. package/app/composables/useMemories.ts +83 -0
  72. package/app/composables/useNotificationBus.ts +154 -0
  73. package/app/composables/usePreferences.ts +131 -0
  74. package/app/composables/useProjects.ts +97 -0
  75. package/app/composables/useSearch.ts +52 -0
  76. package/app/composables/useTasks.ts +201 -0
  77. package/app/composables/useTerminal.ts +135 -0
  78. package/app/layouts/auth.vue +20 -0
  79. package/app/layouts/dashboard.vue +186 -0
  80. package/app/layouts/view.vue +60 -0
  81. package/app/middleware/auth.ts +9 -0
  82. package/app/pages/agents/[id].vue +602 -0
  83. package/app/pages/agents/index.vue +412 -0
  84. package/app/pages/chat.vue +146 -0
  85. package/app/pages/dashboard.vue +80 -0
  86. package/app/pages/docs.vue +131 -0
  87. package/app/pages/hooks.vue +163 -0
  88. package/app/pages/index.vue +249 -0
  89. package/app/pages/login.vue +60 -0
  90. package/app/pages/memories.vue +282 -0
  91. package/app/pages/settings.vue +625 -0
  92. package/app/pages/tasks.vue +312 -0
  93. package/app/pages/view/[uuid].vue +376 -0
  94. package/dist/cli/index.js +2711 -0
  95. package/drizzle.config.ts +10 -0
  96. package/nuxt.config.ts +98 -0
  97. package/package.json +107 -0
  98. package/server/api/agents/[id]/cancel.post.ts +27 -0
  99. package/server/api/agents/[id]/run.post.ts +34 -0
  100. package/server/api/agents/[id]/runs.get.ts +45 -0
  101. package/server/api/agents/[id]/stats.get.ts +94 -0
  102. package/server/api/agents/[id].delete.ts +29 -0
  103. package/server/api/agents/[id].get.ts +25 -0
  104. package/server/api/agents/[id].patch.ts +55 -0
  105. package/server/api/agents/index.get.ts +15 -0
  106. package/server/api/agents/index.post.ts +48 -0
  107. package/server/api/agents/stats.get.ts +86 -0
  108. package/server/api/auth/[...all].ts +5 -0
  109. package/server/api/conversations/[id].delete.ts +16 -0
  110. package/server/api/conversations/[id].get.ts +34 -0
  111. package/server/api/conversations/index.get.ts +17 -0
  112. package/server/api/documents/[id]/index.delete.ts +47 -0
  113. package/server/api/documents/[id]/index.put.ts +102 -0
  114. package/server/api/documents/[id]/public.get.ts +60 -0
  115. package/server/api/documents/[id]/restore.post.ts +65 -0
  116. package/server/api/documents/by-path.post.ts +168 -0
  117. package/server/api/documents/index.get.ts +48 -0
  118. package/server/api/fs/delete.post.ts +41 -0
  119. package/server/api/fs/list.get.ts +99 -0
  120. package/server/api/fs/mkdir.post.ts +44 -0
  121. package/server/api/fs/move.post.ts +68 -0
  122. package/server/api/fs/read.post.ts +48 -0
  123. package/server/api/fs/rename.post.ts +55 -0
  124. package/server/api/fs/write.post.ts +51 -0
  125. package/server/api/health.get.ts +40 -0
  126. package/server/api/home.get.ts +26 -0
  127. package/server/api/hooks/events/index.get.ts +56 -0
  128. package/server/api/hooks/events/index.post.ts +36 -0
  129. package/server/api/hooks/stats.get.ts +99 -0
  130. package/server/api/memory/[id].delete.ts +26 -0
  131. package/server/api/memory/context.get.ts +83 -0
  132. package/server/api/memory/extract.post.ts +42 -0
  133. package/server/api/memory/search.get.ts +70 -0
  134. package/server/api/memory/store.post.ts +31 -0
  135. package/server/api/projects/[id]/index.delete.ts +40 -0
  136. package/server/api/projects/[id]/index.get.ts +25 -0
  137. package/server/api/projects/[id]/index.put.ts +50 -0
  138. package/server/api/projects/index.get.ts +20 -0
  139. package/server/api/projects/index.post.ts +34 -0
  140. package/server/api/secrets/[key].delete.ts +31 -0
  141. package/server/api/secrets/[key].get.ts +30 -0
  142. package/server/api/secrets/[key].put.ts +52 -0
  143. package/server/api/secrets/index.get.ts +20 -0
  144. package/server/api/secrets/index.post.ts +58 -0
  145. package/server/api/tasks/[id]/index.delete.ts +46 -0
  146. package/server/api/tasks/[id]/index.get.ts +24 -0
  147. package/server/api/tasks/[id]/index.put.ts +70 -0
  148. package/server/api/tasks/[id]/restore.post.ts +49 -0
  149. package/server/api/tasks/index.get.ts +53 -0
  150. package/server/api/tasks/index.post.ts +47 -0
  151. package/server/api/tasks/tags.get.ts +21 -0
  152. package/server/api/user/email.patch.ts +56 -0
  153. package/server/db/index.ts +76 -0
  154. package/server/db/migrate.ts +41 -0
  155. package/server/db/schema.ts +345 -0
  156. package/server/db/seed.ts +46 -0
  157. package/server/db/types.ts +28 -0
  158. package/server/drizzle/migrations/0000_brown_george_stacy.sql +34 -0
  159. package/server/drizzle/migrations/0001_stormy_pyro.sql +16 -0
  160. package/server/drizzle/migrations/0002_clean_colossus.sql +50 -0
  161. package/server/drizzle/migrations/0003_fine_joystick.sql +12 -0
  162. package/server/drizzle/migrations/0004_tan_groot.sql +26 -0
  163. package/server/drizzle/migrations/0005_cloudy_lilith.sql +33 -0
  164. package/server/drizzle/migrations/0006_ordinary_retro_girl.sql +13 -0
  165. package/server/drizzle/migrations/0007_flowery_venus.sql +15 -0
  166. package/server/drizzle/migrations/0008_talented_zombie.sql +13 -0
  167. package/server/drizzle/migrations/0009_gray_shen.sql +15 -0
  168. package/server/drizzle/migrations/meta/0000_snapshot.json +230 -0
  169. package/server/drizzle/migrations/meta/0001_snapshot.json +306 -0
  170. package/server/drizzle/migrations/meta/0002_snapshot.json +615 -0
  171. package/server/drizzle/migrations/meta/0003_snapshot.json +730 -0
  172. package/server/drizzle/migrations/meta/0004_snapshot.json +916 -0
  173. package/server/drizzle/migrations/meta/0005_snapshot.json +1127 -0
  174. package/server/drizzle/migrations/meta/0006_snapshot.json +1213 -0
  175. package/server/drizzle/migrations/meta/0007_snapshot.json +1307 -0
  176. package/server/drizzle/migrations/meta/0008_snapshot.json +1390 -0
  177. package/server/drizzle/migrations/meta/0009_snapshot.json +1487 -0
  178. package/server/drizzle/migrations/meta/_journal.json +76 -0
  179. package/server/middleware/auth.ts +79 -0
  180. package/server/plugins/00.env-validate.ts +38 -0
  181. package/server/plugins/01.api-token.ts +31 -0
  182. package/server/plugins/02.database.ts +54 -0
  183. package/server/plugins/03.file-watcher.ts +65 -0
  184. package/server/plugins/04.cron-agents.ts +26 -0
  185. package/server/routes/_ws/chat.ts +252 -0
  186. package/server/routes/notifications.ts +47 -0
  187. package/server/routes/terminal.ts +98 -0
  188. package/server/services/agent-executor.ts +218 -0
  189. package/server/services/cron-scheduler.ts +78 -0
  190. package/server/services/memory-extractor.ts +120 -0
  191. package/server/utils/agent-cleanup.ts +91 -0
  192. package/server/utils/agent-registry.ts +95 -0
  193. package/server/utils/auth.ts +33 -0
  194. package/server/utils/chat-session-manager.ts +59 -0
  195. package/server/utils/crypto.ts +40 -0
  196. package/server/utils/db-guard.ts +12 -0
  197. package/server/utils/db-state.ts +63 -0
  198. package/server/utils/document-sync.ts +207 -0
  199. package/server/utils/frontmatter.ts +84 -0
  200. package/server/utils/notification-bus.ts +60 -0
  201. package/server/utils/path-validator.ts +55 -0
  202. package/server/utils/pty-manager.ts +130 -0
  203. package/shared/types/index.ts +604 -0
  204. package/shared/utils/language-detection.ts +87 -0
  205. 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