aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-19 11:43:29 +0200
committerDanilo M. <danix@danix.xyz>2026-10-19 11:43:29 +0200
commit3737bc1b011510253a63fafb3e756dddb36cf37b (patch)
tree92bf7376017b6b66480618293fb14b5746570759
parent393e2ccc4eb3bb3c279b7d60652a4380e701c065 (diff)
downloaddesktop-assistant-3737bc1b011510253a63fafb3e756dddb36cf37b.tar.gz
desktop-assistant-3737bc1b011510253a63fafb3e756dddb36cf37b.zip
docs: spec the new project tool
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--docs/superpowers/specs/2026-10-19-project-tool-design.md119
1 files changed, 119 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-10-19-project-tool-design.md b/docs/superpowers/specs/2026-10-19-project-tool-design.md
new file mode 100644
index 0000000..e1b69e9
--- /dev/null
+++ b/docs/superpowers/specs/2026-10-19-project-tool-design.md
@@ -0,0 +1,119 @@
+# New project tool: design
+
+Date: 2026-10-19. Status: approved, not implemented.
+
+## Goal
+
+Ask the assistant to start a new project and get a folder in
+`~/Programming/GIT` laid out like the user's other repos (AGENTS.md,
+CLAUDE.md pointing at it, README.md, LICENSE), a GPG-signed first commit,
+and a kitty tab in that folder running Claude Code, already told what the
+project is.
+
+This tool writes more than one bit, so unlike `mode` it has a review step:
+the model repeats name, description and license and calls the tool only
+after the user says yes. A misheard name would otherwise become a folder.
+
+## Tool
+
+`examples/tools/project.toml`, installed to `~/.config/desktop-assistant/tools/`
+like the others. No change to `assistant.py`.
+
+```toml
+description = "Start a new programming project: a folder in ~/Programming/GIT with AGENTS.md, CLAUDE.md, README.md, LICENSE and a signed first commit, then a kitty tab running Claude Code in it. Before calling, tell the user the name, description and license you will use, and call only after they say yes."
+command = ["project.sh", "{name}", "{license}", "{description}"]
+timeout = 120
+
+[params.name]
+type = "string"
+description = "Folder name: lowercase letters, digits, - _ . (e.g. photo-sorter)"
+
+[params.license]
+type = "string"
+description = "gpl2 (GPLv2 only, default), gpl2+ (GPLv2 or later), gpl3 or mit. Empty means gpl2."
+
+[params.description]
+type = "string"
+description = "What the project is, one or two sentences, in the user's words"
+```
+
+The 120 s timeout leaves room for the Nitrokey PIN dialog: gpg-agent uses
+`pinentry-qt`, which shows up from the daemon's login session.
+
+## project.sh
+
+Bash, GPLv2 header like the other tool scripts.
+
+1. **Validate.** Name matches `^[a-z0-9][a-z0-9._-]*$`; license in
+ `gpl2 gpl2+ gpl3 mit` (empty = gpl2); description not empty. Refuse
+ if `$PROJECTS_DIR/<name>` exists (`PROJECTS_DIR` defaults to
+ `~/Programming/GIT`, overridable for the check). Each refusal is one
+ line on stderr naming what is accepted, exit 1.
+2. **Write files.**
+ - `CLAUDE.md`: the init-repo house text, verbatim (thin pointer,
+ `@AGENTS.md`).
+ - `AGENTS.md`: "What this is" (name and description), "Conventions"
+ (placeholders only in code, docs, tests and commits), "Testing" (No
+ test suite yet.), "Repo facts" (license, work directly on master).
+ - `README.md`: title, description, License section with
+ `Copyright (C) <year> Danilo M. <danix@danix.xyz>` and the license
+ name, then the "Development Approach" section verbatim from the
+ global preferences.
+ - `LICENSE`: copied from `examples/tools/licenses/<file>`, found next
+ to the script (`gpl-2.0.txt` for gpl2 and gpl2+, `gpl-3.0.txt`,
+ `mit.txt`). The texts are fetched once from gnu.org and
+ opensource.org and committed, so the tool works offline. MIT's
+ copyright line is filled with the year and name.
+ - No em dashes, no personal data beyond the copyright line.
+3. **Commit.** `git init -b master`, `git add -A`,
+ `git commit -S -m "Initial commit"` with the attribution trailer
+ left out (the user's commit, made by their tool). Signing is never
+ disabled. If the commit fails (PIN cancelled, hook rejection), the
+ folder stays and the output says so with git's first error line; the
+ tab still opens.
+4. **Open Claude Code.** Prompt: `New project: <description>. Fill in
+ AGENTS.md and README.md from this, then wait.`
+ - Socket: newest `$XDG_RUNTIME_DIR/kitty-*` that answers
+ `kitty @ --to unix:<sock> ls`. Then `kitty @ --to unix:<sock> launch
+ --type=tab --cwd=<dir> claude <prompt>` and
+ `hyprctl dispatch focuswindow class:kitty`.
+ - No socket answers: `setsid -f kitty -d <dir> claude <prompt>`, a new
+ window, detached.
+ - `KITTY` env var overrides the `kitty` binary, for the check.
+5. **Output**, one line: `created <path> (<license>), committed <short
+ sha> | not committed: <reason>, opened in a kitty tab | window`.
+
+## kitty-conf (separate repo)
+
+`~/.config/kitty/kitty.conf` links to the `kitty-conf` repo. Add:
+
+```
+allow_remote_control socket-only
+listen_on unix:${XDG_RUNTIME_DIR}/kitty-{kitty_pid}
+```
+
+`socket-only` keeps remote control off the tty escape codes, so programs
+inside kitty cannot drive it. Takes effect after kitty restarts once.
+
+## Check
+
+`examples/tools/test-project.sh`, like `test-mode.sh`: a temporary
+`PROJECTS_DIR`, `KITTY=true` so no tab opens. Asserts the four files and
+a signed commit (`git log --format=%G?` is `G`), then the refusals: bad
+name (`Foo`, `../x`, empty), existing folder, unknown license, empty
+description. The commit is really signed: with a cold PIN cache the
+dialog appears once.
+
+Live, against the running model:
+
+- 5 phrasings, Italian and English. The model must state name,
+ description and license and wait: no tool call before the yes, 5/5.
+- One creation end to end: folder, signed commit, kitty tab focused,
+ Claude Code started with the prompt.
+- kitty not running: a new window opens instead.
+
+## Not included
+
+Remotes (gitctl, gh, tea), language scaffolding, source-file headers
+(there are no sources yet). The Claude Code session in the new tab
+handles those.