Compare commits
9
Commits
fccb75298e
...
75dcd21776
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75dcd21776 | ||
|
|
94a1925f1b | ||
|
|
623117d6c5 | ||
|
|
ab12436d07 | ||
|
|
79a4040b0a | ||
|
|
43952188ad | ||
|
|
1a1ba1131c | ||
|
|
312bfd18be | ||
|
|
8c8a352945 |
@@ -141,6 +141,12 @@ EOF
|
||||
|
||||
An effort task is the same call with `--projects '[[atribot]]'`, no actor tag, and `--prop git_branch=…` when the work is not on main.
|
||||
|
||||
Efforts and tickets are worked from the frontier, not a calendar, so none carries a scheduled date. The plugin stamps `date_scheduled: <today>` on every task it creates, and `tn` cannot suppress or clear it — empty `--scheduled` values are dropped by both `create` and `update`. Strip it right after each create:
|
||||
|
||||
```sh
|
||||
obsidian property:remove name=date_scheduled path='TaskNotes/Dev/atribot/Network isolation/Split obsync into its own container.md'
|
||||
```
|
||||
|
||||
Create in dependency order so a blocker's title exists before the ticket naming it. Flag reference: `tasknotes-cli`.
|
||||
|
||||
A second `--blocked-by` does not add a second blocker — the flag is read once, so every blocker goes in one comma-separated value as above. Commas inside `[[...]]` are literal, so titles containing commas are safe.
|
||||
@@ -274,6 +280,8 @@ tn list --filter 'projects:contains:"[[Network isolation]]" AND dependencies.isB
|
||||
- **`tn update`** for everything TaskNotes models — status, priority, dates, estimate, tags, contexts, projects, `blockedBy` — and all queries. It goes through the update service, which maintains `date_modified` and recurring-instance bookkeeping.
|
||||
- **`obsidian`** for what `tn update` has no flag for: custom properties after creation (`agent_session`, `git_branch`, `git_worktree`) and body text. `obsidian property:set` writes YAML directly and skips the update service.
|
||||
|
||||
In a sandboxed session, invoke `obsidian` only as a simple or `&&`-chained command. The command is the Obsidian AppImage, and the sandbox denies its FUSE mount when the call sits inside a shell loop — every iteration fails with `fuse: device not found`. Write a batch over many notes as chained single calls, not a loop.
|
||||
|
||||
Mid-flight dependency edits are rare, since blockers are written at creation. When one is needed:
|
||||
|
||||
```sh
|
||||
|
Before Width: | Height: | Size: 420 B After Width: | Height: | Size: 420 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -1,8 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
podman run --rm -i \
|
||||
-v ${HOME}/Music:/downloads:z \
|
||||
--userns keep-id:uid=1000,gid=1000 \
|
||||
--entrypoint scdl \
|
||||
yt-dlp:latest $@
|
||||
|
||||
+8
-2
@@ -64,7 +64,11 @@ fi
|
||||
alias tmux="tmux -2"
|
||||
alias grep="grep --color=auto"
|
||||
|
||||
if command -v brew >/dev/null 2>&1; then
|
||||
eval "$(brew shellenv)"
|
||||
elif [[ -x /home/linuxbrew/.linuxbrew/bin/brew ]]; then
|
||||
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
|
||||
fi
|
||||
|
||||
# Fix gpg signing
|
||||
# https://github.com/keybase/keybase-issues/issues/2798
|
||||
@@ -78,8 +82,8 @@ export TERM="xterm-256color"
|
||||
export EDITOR=$(which nvim)
|
||||
|
||||
# Adding applications to path
|
||||
if [[ -d ${HOME}/.dotfiles/bin/linux ]]; then
|
||||
export PATH=$PATH:${HOME}/.dotfiles/bin/linux
|
||||
if [[ -d ${HOME}/.local/bin ]] && [[ ":${PATH}:" != *":${HOME}/.local/bin:"* ]]; then
|
||||
export PATH=${HOME}/.local/bin:${PATH}
|
||||
fi
|
||||
if [[ -d ${HOME}/bin ]]; then
|
||||
export PATH=$PATH:${HOME}/bin
|
||||
@@ -88,7 +92,9 @@ fi
|
||||
|
||||
# Enable atuin
|
||||
# https://docs.atuin.sh
|
||||
if command -v atuin >/dev/null 2>&1; then
|
||||
eval "$(atuin init bash)"
|
||||
fi
|
||||
|
||||
# fzf
|
||||
#eval "$(fzf --bash)"
|
||||
|
||||
+50
-13
@@ -33,7 +33,31 @@
|
||||
],
|
||||
"defaultMode": "auto"
|
||||
},
|
||||
"model": "opus[1m]",
|
||||
"disableClaudeAiConnectors": true,
|
||||
"hooks": {
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "atuin hook claude-code"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUseFailure": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "atuin hook claude-code"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
@@ -47,22 +71,33 @@
|
||||
"command": "~/.claude/hooks/block-file-deletion.sh"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "atuin hook claude-code"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"disableWorkflows": true,
|
||||
"disableArtifact": true,
|
||||
"statusLine": {
|
||||
"type": "command",
|
||||
"command": "bash /home/tgrosinger/.claude/statusline-command.sh"
|
||||
},
|
||||
"enabledPlugins": {
|
||||
"pr-review-toolkit@claude-plugins-official": true,
|
||||
"gopls-lsp@claude-plugins-official": true,
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"code-simplifier@claude-plugins-official": true,
|
||||
"skill-creator@claude-plugins-official": true,
|
||||
"typescript-lsp@claude-plugins-official": true,
|
||||
"claude-md-management@claude-plugins-official": true,
|
||||
"security-guidance@claude-plugins-official": true
|
||||
"code-simplifier@claude-plugins-official": true,
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"gopls-lsp@claude-plugins-official": true,
|
||||
"pr-review-toolkit@claude-plugins-official": true,
|
||||
"security-guidance@claude-plugins-official": true,
|
||||
"skill-creator@claude-plugins-official": true,
|
||||
"typescript-lsp@claude-plugins-official": true
|
||||
},
|
||||
"sandbox": {
|
||||
"enabled": true,
|
||||
@@ -86,19 +121,23 @@
|
||||
"filesystem": {
|
||||
"allowWrite": [
|
||||
"~/.local/share/pnpm",
|
||||
"~/.cache/pnpm"
|
||||
"~/.cache/pnpm",
|
||||
"~/Documents/Atrium"
|
||||
],
|
||||
"denyRead": [
|
||||
"~/.ssh",
|
||||
"~/.config/Signal",
|
||||
"~/Documents"
|
||||
],
|
||||
"allowRead": [
|
||||
"~/Documents/Atrium"
|
||||
]
|
||||
},
|
||||
"excludedCommands": [
|
||||
"git push *",
|
||||
"brew *",
|
||||
"devbox add *",
|
||||
"nix *"
|
||||
"tn *",
|
||||
"obsidian *"
|
||||
]
|
||||
},
|
||||
"spinnerVerbs": {
|
||||
@@ -118,9 +157,7 @@
|
||||
"autoDreamEnabled": true,
|
||||
"theme": "light",
|
||||
"editorMode": "vim",
|
||||
"remoteControlAtStartup": false,
|
||||
"agentPushNotifEnabled": true,
|
||||
"disableClaudeAiConnectors": true,
|
||||
"disableWorkflows": true,
|
||||
"disableArtifact": true,
|
||||
"skipAutoPermissionPrompt": true
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Mise shims so non-interactive shells (scripts, editor spawns) find tools.
|
||||
# Interactive sessions get exact versions from `mise activate` below.
|
||||
fish_add_path ~/.local/share/mise/shims
|
||||
fish_add_path --global ~/.local/bin ~/.local/share/mise/shims ~/go/bin
|
||||
|
||||
if status is-interactive
|
||||
# Commands to run in interactive sessions can go here
|
||||
@@ -9,7 +9,9 @@ if status is-interactive
|
||||
# https://fishshell.com/docs/current/cmds/fish_greeting.html
|
||||
set -g fish_greeting
|
||||
|
||||
if test -f /home/linuxbrew/.linuxbrew/bin/brew
|
||||
if command -q brew
|
||||
brew shellenv | source
|
||||
else if test -x /home/linuxbrew/.linuxbrew/bin/brew
|
||||
/home/linuxbrew/.linuxbrew/bin/brew shellenv | source
|
||||
end
|
||||
if command -q atuin
|
||||
@@ -35,9 +37,6 @@ if status is-interactive
|
||||
# https://fishshell.com/docs/current/cmds/abbr.html
|
||||
abbr --add --position command pc process-compose
|
||||
|
||||
# Set Path
|
||||
fish_add_path -p /home/tgrosinger/.dotfiles/bin/linux
|
||||
|
||||
# Per-directory toolchains and global tools.
|
||||
# https://mise.jdx.dev/getting-started.html
|
||||
if type -q mise
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
# This file contains fish universal variable definitions.
|
||||
# VERSION: 3.0
|
||||
SETUVAR __fish_initialized:4300
|
||||
SETUVAR fish_user_paths:/home/tgrosinger/\x2elocal/bin\x1e/home/tgrosinger/\x2elocal/share/mise/shims\x1e/home/tgrosinger/go/bin\x1e/home/tgrosinger/\x2edotfiles/bin/linux
|
||||
|
||||
+4
-4
@@ -36,10 +36,10 @@
|
||||
sync = "!git fetch -p && git rebase origin/$(git default-branch)"
|
||||
|
||||
[core]
|
||||
editor = /home/linuxbrew/.linuxbrew/bin/nvim
|
||||
editor = nvim
|
||||
pager = delta
|
||||
attributesfile = /home/tgrosinger/.gitattributes
|
||||
excludesfile = /home/tgrosinger/.gitignore_global
|
||||
attributesfile = ~/.gitattributes
|
||||
excludesfile = ~/.gitignore_global
|
||||
|
||||
[help]
|
||||
autocorrect = prompt
|
||||
@@ -58,7 +58,7 @@
|
||||
renames = true
|
||||
|
||||
[include]
|
||||
path = /home/tgrosinger/.config/delta/themes/catppuccin.gitconfig
|
||||
path = ~/.config/delta/themes/catppuccin.gitconfig
|
||||
|
||||
[delta]
|
||||
# Does not behave well for comments
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
.github/instructions
|
||||
.plans
|
||||
.scratch
|
||||
.magpie
|
||||
|
||||
**/.claude/settings.local.json
|
||||
**/.claude/.cc-writes/
|
||||
CLAUDE.local.md
|
||||
|
||||
.worktree-setup.sh
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
podman run --rm \
|
||||
-v ${HOME}/Videos/youtube:/downloads:z \
|
||||
--userns keep-id:uid=1000,gid=1000 \
|
||||
yt-dlp:latest -S 'res:1080' $@
|
||||
yt-dlp:latest -S 'res:1080' --extractor-args "youtube:player-client=web_embedded" $@
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Atuin extension for pi.
|
||||
*
|
||||
* Tracks bash commands executed by pi in Atuin history with author `pi`.
|
||||
*
|
||||
* Install with:
|
||||
* atuin hook install pi
|
||||
*
|
||||
* Then restart pi or run /reload.
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
||||
|
||||
const ATUIN_AUTHOR = "pi";
|
||||
const ATUIN_TIMEOUT_MS = 10_000;
|
||||
|
||||
async function startHistory(
|
||||
pi: ExtensionAPI,
|
||||
cwd: string,
|
||||
command: string,
|
||||
): Promise<string | undefined> {
|
||||
try {
|
||||
const result = await pi.exec(
|
||||
"atuin",
|
||||
["history", "start", "--author", ATUIN_AUTHOR, "--", command],
|
||||
{ cwd, timeout: ATUIN_TIMEOUT_MS },
|
||||
);
|
||||
|
||||
if (result.code !== 0) return undefined;
|
||||
|
||||
const id = result.stdout.trim();
|
||||
return id.length > 0 ? id : undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async function endHistory(
|
||||
pi: ExtensionAPI,
|
||||
cwd: string,
|
||||
historyId: string,
|
||||
exitCode: number,
|
||||
): Promise<void> {
|
||||
try {
|
||||
await pi.exec(
|
||||
"atuin",
|
||||
["history", "end", historyId, "--exit", String(exitCode)],
|
||||
{ cwd, timeout: ATUIN_TIMEOUT_MS },
|
||||
);
|
||||
} catch {
|
||||
// Ignore Atuin failures so command execution is never blocked.
|
||||
}
|
||||
}
|
||||
|
||||
// The bash tool reports failures by appending a status line to the result
|
||||
// text rather than exposing a numeric exit code, so recover it from there.
|
||||
function exitCodeFromResult(result: unknown, isError: boolean): number {
|
||||
if (!isError) return 0;
|
||||
|
||||
const content = (result as { content?: unknown } | undefined)?.content;
|
||||
const text = Array.isArray(content)
|
||||
? content
|
||||
.map((part) => {
|
||||
const t = (part as { text?: unknown } | undefined)?.text;
|
||||
return typeof t === "string" ? t : "";
|
||||
})
|
||||
.join("\n")
|
||||
: "";
|
||||
|
||||
const exited = text.match(/Command exited with code (\d+)\s*$/);
|
||||
if (exited) return Number(exited[1]);
|
||||
if (/Command aborted\s*$/.test(text)) return 130;
|
||||
if (/Command timed out after \S+ seconds\s*$/.test(text)) return 124;
|
||||
return 1;
|
||||
}
|
||||
|
||||
export default function atuinPiExtension(pi: ExtensionAPI) {
|
||||
// Atuin history IDs for in-flight bash tool calls, keyed by tool call ID.
|
||||
const pending = new Map<string, string>();
|
||||
|
||||
// Observe bash executions through events instead of registering a bash
|
||||
// tool: registering one conflicts with other extensions that provide
|
||||
// their own bash tool (sandboxes, RTK, remote runners), while events
|
||||
// fire no matter which extension's bash tool ends up executing the
|
||||
// command.
|
||||
pi.on("tool_call", async (event, ctx: ExtensionContext) => {
|
||||
if (event.toolName !== "bash") return;
|
||||
|
||||
const command = (event.input as { command?: unknown }).command;
|
||||
if (typeof command !== "string" || command.length === 0) return;
|
||||
|
||||
const historyId = await startHistory(pi, ctx.cwd, command);
|
||||
if (historyId) pending.set(event.toolCallId, historyId);
|
||||
});
|
||||
|
||||
// tool_execution_end also fires when another extension blocks the call,
|
||||
// unlike tool_result, so entries started above are always closed.
|
||||
pi.on("tool_execution_end", async (event, ctx: ExtensionContext) => {
|
||||
const historyId = pending.get(event.toolCallId);
|
||||
if (!historyId) return;
|
||||
pending.delete(event.toolCallId);
|
||||
|
||||
await endHistory(pi, ctx.cwd, historyId, exitCodeFromResult(event.result, event.isError));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user